diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index 6a964a5..0000000 --- a/AUTHORS +++ /dev/null @@ -1,3 +0,0 @@ -Mario Danic -Thomas Schmitt - diff --git a/CONTRIBUTORS b/CONTRIBUTORS deleted file mode 100644 index 31b77c5..0000000 --- a/CONTRIBUTORS +++ /dev/null @@ -1,6 +0,0 @@ -Joe Neeman -Philippe Rouquier -Gabriel Craciunescu -George Danchev -Jean-Francois Wauthy -Lorenzo Taylor diff --git a/COPYING b/COPYING deleted file mode 100644 index 5a965fb..0000000 --- a/COPYING +++ /dev/null @@ -1,280 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS diff --git a/COPYRIGHT b/COPYRIGHT deleted file mode 100644 index 7b7b4b7..0000000 --- a/COPYRIGHT +++ /dev/null @@ -1,18 +0,0 @@ -Derek Foreman and Ben Jansens -Copyright (C) 2002-2006 Derek Foreman and Ben Jansens -Mario Danic , Thomas Schmitt -Copyright (C) 2006-2008 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. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA diff --git a/ChangeLog b/ChangeLog deleted file mode 100644 index 7001d0f..0000000 --- a/ChangeLog +++ /dev/null @@ -1 +0,0 @@ -nothing here now diff --git a/INSTALL b/INSTALL deleted file mode 100644 index 5458714..0000000 --- a/INSTALL +++ /dev/null @@ -1,234 +0,0 @@ -Installation Instructions -************************* - -Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, -2006 Free Software Foundation, Inc. - -This file is free documentation; the Free Software Foundation gives -unlimited permission to copy, distribute and modify it. - -Basic Installation -================== - -Briefly, the shell commands `./configure; make; make install' should -configure, build, and install this package. The following -more-detailed instructions are generic; see the `README' file for -instructions specific to this package. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, and a -file `config.log' containing compiler output (useful mainly for -debugging `configure'). - - It can also use an optional file (typically called `config.cache' -and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. Caching is -disabled by default to prevent problems with accidental use of stale -cache files. - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If you are using the cache, and at -some point `config.cache' contains results you don't want to keep, you -may remove or edit it. - - The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You need `configure.ac' if -you want to change it or regenerate `configure' using a newer version -of `autoconf'. - -The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. - - Running `configure' might take a while. While running, it prints - some messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package. - - 4. Type `make install' to install the programs and any data files and - documentation. - - 5. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - -Compilers and Options -===================== - -Some systems require unusual options for compilation or linking that the -`configure' script does not know about. Run `./configure --help' for -details on some of the pertinent environment variables. - - You can give `configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here -is an example: - - ./configure CC=c99 CFLAGS=-g LIBS=-lposix - - *Note Defining Variables::, for more details. - -Compiling For Multiple Architectures -==================================== - -You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you can use GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. - - With a non-GNU `make', it is safer to compile the package for one -architecture at a time in the source code directory. After you have -installed the package for one architecture, use `make distclean' before -reconfiguring for another architecture. - -Installation Names -================== - -By default, `make install' installs the package's commands under -`/usr/local/bin', include files under `/usr/local/include', etc. You -can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX'. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -pass the option `--exec-prefix=PREFIX' to `configure', the package uses -PREFIX as the prefix for installing programs and libraries. -Documentation and other data files still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=DIR' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - -Optional Features -================= - -Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - -Specifying the System Type -========================== - -There may be some features `configure' cannot figure out automatically, -but needs to determine by the type of machine the package will run on. -Usually, assuming the package is built to be run on the _same_ -architectures, `configure' can figure that out, but if it prints a -message saying it cannot guess the machine type, give it the -`--build=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name which has the form: - - CPU-COMPANY-SYSTEM - -where SYSTEM can have one of these forms: - - OS KERNEL-OS - - See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the machine type. - - If you are _building_ compiler tools for cross-compiling, you should -use the option `--target=TYPE' to select the type of system they will -produce code for. - - If you want to _use_ a cross compiler, that generates code for a -platform different from the build platform, you should specify the -"host" platform (i.e., that on which the generated programs will -eventually be run) with `--host=TYPE'. - -Sharing Defaults -================ - -If you want to set default values for `configure' scripts to share, you -can create a site shell script called `config.site' that gives default -values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Defining Variables -================== - -Variables not defined in a site shell script can be set in the -environment passed to `configure'. However, some packages may run -configure again during the build, and the customized values of these -variables may be lost. In order to avoid this problem, you should set -them in the `configure' command line, using `VAR=value'. For example: - - ./configure CC=/usr/local2/bin/gcc - -causes the specified `gcc' to be used as the C compiler (unless it is -overridden in the site shell script). - -Unfortunately, this technique does not work for `CONFIG_SHELL' due to -an Autoconf bug. Until the bug is fixed you can use this workaround: - - CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash - -`configure' Invocation -====================== - -`configure' recognizes the following options to control how it operates. - -`--help' -`-h' - Print a summary of the options to `configure', and exit. - -`--version' -`-V' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`--cache-file=FILE' - Enable the cache: use and save the results of the tests in FILE, - traditionally `config.cache'. FILE defaults to `/dev/null' to - disable caching. - -`--config-cache' -`-C' - Alias for `--cache-file=config.cache'. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`configure' also accepts some other, not widely useful, options. Run -`configure --help' for more details. - diff --git a/Makefile.am b/Makefile.am deleted file mode 100644 index f1a4e42..0000000 --- a/Makefile.am +++ /dev/null @@ -1,202 +0,0 @@ -pkgconfigdir=$(libdir)/pkgconfig -libincludedir=$(includedir)/libburn - -lib_LTLIBRARIES = libburn/libburn.la - -## ========================================================================= ## - -# Build libraries -libburn_libburn_la_LDFLAGS = \ - -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) -libburn_libburn_la_LIBADD = $(LIBBURN_ARCH_LIBS) $(THREAD_LIBS) -libburn_libburn_la_SOURCES = \ - libburn/async.c \ - libburn/async.h \ - libburn/back_hacks.h \ - libburn/cleanup.c \ - libburn/cleanup.h \ - libburn/crc.c \ - libburn/crc.h \ - libburn/debug.c \ - libburn/debug.h \ - libburn/drive.c \ - libburn/drive.h \ - libburn/error.h \ - libburn/file.c \ - libburn/file.h \ - libburn/init.c \ - libburn/init.h \ - libburn/lec.c \ - libburn/lec.h \ - libburn/libburn.h \ - libburn/libdax_audioxtr.h \ - libburn/libdax_audioxtr.c \ - libburn/libdax_msgs.h \ - libburn/libdax_msgs.c \ - libburn/mmc.c \ - libburn/mmc.h \ - libburn/null.c \ - libburn/null.h \ - libburn/options.c \ - libburn/options.h \ - libburn/os.h \ - libburn/read.c \ - libburn/read.h \ - libburn/sbc.c \ - libburn/sbc.h \ - libburn/sector.c \ - libburn/sector.h \ - libburn/sg.c \ - libburn/sg.h \ - libburn/source.h \ - libburn/source.c \ - libburn/spc.c \ - libburn/spc.h \ - libburn/structure.c \ - libburn/structure.h \ - libburn/toc.c \ - libburn/toc.h \ - libburn/transport.h \ - libburn/util.c \ - libburn/util.h \ - libburn/write.c \ - libburn/write.h \ - version.h - -## libburn/sg-@ARCH@.c \ - -libinclude_HEADERS = \ - libburn/libburn.h - -## ========================================================================= ## - -## Build test applications -noinst_PROGRAMS = \ - test/libburner \ - test/telltoc \ - test/dewav \ - test/fake_au \ - test/poll \ - test/structest - -bin_PROGRAMS = \ - cdrskin/cdrskin - -test_libburner_CPPFLAGS = -Ilibburn -test_libburner_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS) -test_libburner_SOURCES = test/libburner.c -test_telltoc_CPPFLAGS = -Ilibburn -test_telltoc_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS) -test_telltoc_SOURCES = test/telltoc.c -test_dewav_CPPFLAGS = -Ilibburn -test_dewav_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS) -test_dewav_SOURCES = test/dewav.c -test_fake_au_CPPFLAGS = -test_fake_au_LDADD = -test_fake_au_SOURCES = test/fake_au.c -test_poll_CPPFLAGS = -Ilibburn -test_poll_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS) -test_poll_SOURCES = test/poll.c -test_structest_CPPFLAGS = -Ilibburn -test_structest_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS) -test_structest_SOURCES = test/structest.c - -## cdrskin construction site - ts A60816 - A80510 -cdrskin_cdrskin_CPPFLAGS = -Ilibburn -cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_4_6 - -# 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_SOURCES = cdrskin/cdrskin.c cdrskin/cdrfifo.c cdrskin/cdrfifo.h cdrskin/cdrskin_timestamp.h -## -## Open questions: how to compute $timestamp and express -DX="$timestamp" -## - - - -## ========================================================================= ## - -## Build documentation (You need Doxygen for this to work) -webhost = http://libburn-api.pykix.org -webpath = / -docdir = $(DESTDIR)$(prefix)/share/doc/$(PACKAGE)-$(VERSION) - -doc: doc/html - -doc/html: doc/doxygen.conf - if [ -f ./doc/doc.lock ]; then \ - $(RM) -r doc/html; \ - doxygen doc/doxygen.conf; \ - fi - -doc-upload: doc/html - scp -r $ and Thomas Schmitt -Copyright (C) 2006-2008 Mario Danic, Thomas Schmitt - -Still containing parts of -Libburn. By Derek Foreman and - Ben Jansens -Copyright (C) 2002-2006 Derek Foreman and Ben Jansens -These parts are to be replaced by own code of above libburnia-project.org -copyright holders and then libburnia-project.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 ------------------------------------------------------------------------------- - - Build and Installation - -Our build system is based on autotools. For preparing the build of a SVN -snapshot you will need autotools of at least version 1.7. -Check out from SVN by - svn co http://svn.libburnia-project.org/libburn/trunk libburn -go into directory libburn 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 - make - -To make the libraries accessible for running resp. developing applications -and to install the cdrecord compatibility binary cdrskin, do: - make install - - -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. - - ------------------------------------------------------------------------------- - - - Overview of libburnia-project.org - -libburnia-project.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. - -The project comprises of several more or less interdependent parts which -together strive to be a usable foundation for application development. -These are libraries, language bindings, and middleware binaries which emulate -classical (and valuable) Linux tools. - -Our scope is currently Linux 2.4 and 2.6 only. For ports to other systems -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. - -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). - 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. - 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 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. - 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). - - ------------------------------------------------------------------------------- -Project history as far as known to me: - -- Founded in 2002 as it seems. See mailing list archives - http://lists.freedesktop.org/archives/libburn/ - The site of this founder team is reachable and offers download of a - (somewhat outdated) tarball and from CVS : - http://icculus.org/burn/ - Copyright holders and most probably founders: - Derek Foreman and Ben Jansens. - -- I came to using libburn in 2005. Founded the cdrskin project and submitted - necessary patches which were accepted or implemented better. Except one - remaining patch which prevented cdrskin from using vanilla libburn from CVS. - The cdrskin project site is reachable and offers download of the heavily - patched (elsewise outdated) tarball under the name cdrskin-0.1.2 : - http://scdbackup.sourceforge.net/cdrskin_eng.html - It has meanwhile moved to use vanilla libburn.pykix.org , though. - Version 0.1.4 constitutes the first release of this kind. - -- In July 2006 our team mate Mario Danic announced a revival of libburn - which by about nearly everybody else was perceived as unfriendly fork. - Derek Foreman four days later posted a message which expressed his - 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 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 - -- Mid August 2006 project cdrskin established a branch office in - libburn.pykix.org so that all maintainers of our tools have one single place - to get the current (at least slightely) usable coordinated versions of - everything. - Project cdrskin will live forth independendly for a while but it is committed - to stay in sync with libburn.pykix.org (or some successor, if ever). - cdrskin is also committed to support icculus.org/burn if the pending fork - is made reality by content changes in that project. It will cease to maintain - a patched version of icculus.org/burn though. Precondition for a new - release of cdrskin on base of icculus.org/burn would be the pending - "whitelist patch" therefore. - I would rather prefer if both projects find consense and merge, or at least - cooperate. I have not given up hope totally, yet. - I, personally, will honor any approach. - -- 2nd September 2006 the decision is made to strive for a consolidation of - copyright and a commitment to GPL in a reasonable and open minded way. - This is to avoid long term problems with code of unknown origin and - with finding consense among the not so clearly defined group of copyright - claimers and -holders. - libisofs is already claimed sole copyright Mario Danic. - cdrskin and libburner are already claimed sole copyright Thomas Schmitt. - Rewrites of other components will follow and concluded by claiming full - copyright within the group of libburn.pykix.org-copyright holders. - -- 16th September 2006 feature freeze for release of libburn-0.2.2 . - -- 20th September 2006 release of libburn-0.2.2 . - -- 26th October 2006 feature freeze for cdrskin-0.2.4 based on libburn-0.2.3 . - This version of cdrskin is much more cdrecord compatible in repect - to drive addressing and audio features. - -- 30th October 2006 release of cdrskin-0.2.4 . - -- 13th November 2006 splitting releases of libburn+cdrskin from libisofs. - -- 24th November 2006 release of libburn-0.2.6 and cdrskin-0.2.6 . cdrskin has - become suitable for unaware frontends as long as they perform only the core - of cdrecord use cases (including open-ended input streams, audio, and - multi-session). - -- 28th November 2006 the umbrella project which encloses both, libisofs and - libburn, is now called libburnia. For the origin of this name, see - http://en.wikipedia.org/wiki/Liburnians . - -- 16th January 2007 release of libburn-0.3.0 and cdrskin-0.3.0 . Now the scope - is widened to a first class of DVD media: overwriteable single layer types - DVD-RAM, DVD+RW, DVD-RW. This is not a cdrecord emulation but rather inspired - by dvd+rw-tools' "poor man" writing facility for this class of media. - Taking a bow towards Andy Polyakov. - -- 11th February 2007 version 0.3.2 covers sequential DVD-RW and DVD-R with - multi-session and with DAO. - -- 12th March 2007 version 0.3.4 supports DVD+R and thus covers all single layer - DVD media. Code for double layer DVD+/-R is implemented but awaits a tester - yet. - -- 23th April 2007 version 0.3.6 follows the unanimous opinion of Linux kernel - people that one should not use /dev/sg on kernel 2.6. - -- 31st July 2007 version 0.3.8 marks the first anniversary of libburn revival. - 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 cdrcord 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. - - ------------------------------------------------------------------------------- - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation. To be exact: version 2 of that License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - ------------------------------------------------------------------------------- -Clarification in my name and in the name of Mario Danic, upcoming copyright -holders on toplevel of libburnia. To be fully in effect after the remaining -other copyrighted code has been replaced by ours and by copyright-free -contributions of our friends: ------------------------------------------------------------------------------- - -We, the copyright holders, agree on the interpretation that -dynamical linking of our libraries constitutes "use of" and -not "derivation from" our work in the sense of GPL, provided -those libraries are compiled from our unaltered code. - -Thus you may link our libraries dynamically with applications -which are not under GPL. You may distribute our libraries and -application tools in binary form, if you fulfill the usual -condition of GPL to offer a copy of the source code -altered -or unaltered- under GPL. - -We ask you politely to use our work in open source spirit -and with the due reference to the entire open source community. - -If there should really arise the case where above clarification -does not suffice to fulfill a clear and neat request in open source -spirit that would otherwise be declined for mere formal reasons, -only in that case we will duely consider to issue a special license -covering only that special case. -It is the open source idea of responsible freedom which will be -decisive and you will have to prove that you exhausted all own -means to qualify for GPL. - -For now we are firmly committed to maintain one single license: GPL. - -signed: Mario Danic, Thomas Schmitt - diff --git a/acinclude.m4 b/acinclude.m4 deleted file mode 100644 index 861847b..0000000 --- a/acinclude.m4 +++ /dev/null @@ -1,22 +0,0 @@ -AC_DEFUN([TARGET_SHIZZLE], -[ - ARCH="" - - AC_MSG_CHECKING([target operating system]) - - case $target in - *-*-linux*) - ARCH=linux - LIBBURN_ARCH_LIBS= - ;; - *-*-freebsd*) - ARCH=freebsd - LIBBURN_ARCH_LIBS=-lcam - ;; - *) - AC_ERROR([You are attempting to compile for an unsupported platform]) - ;; - esac - - AC_MSG_RESULT([$ARCH]) -]) diff --git a/bootstrap b/bootstrap deleted file mode 100755 index 86709bf..0000000 --- a/bootstrap +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -x - -aclocal -libtoolize --copy --force -autoconf - -# ts A61101 : libburn is not prepared for config.h -# autoheader - -automake --foreign --add-missing --copy --include-deps diff --git a/cdrskin/README b/cdrskin/README deleted file mode 100644 index b2bb0f8..0000000 --- a/cdrskin/README +++ /dev/null @@ -1,481 +0,0 @@ ------------------------------------------------------------------------------- - libburnia-project.org scdbackup.sourceforge.net/cdrskin_eng.html ------------------------------------------------------------------------------- -cdrskin. By Thomas Schmitt -Integrated sub project of libburnia-project.org but also published via: -http://scdbackup.sourceforge.net/cdrskin_eng.html -http://scdbackup.sourceforge.net/cdrskin-0.4.6.pl00.tar.gz -Copyright (C) 2006-2008 Thomas Schmitt, provided under GPL version 2. ------------------------------------------------------------------------------- - - -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. - -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 ..." - - - Compilation, First Glimpse, Installation - -Obtain cdrskin-0.4.6.pl00.tar.gz, take it to a directory of your choice and do: - - tar xzf cdrskin-0.4.6.pl00.tar.gz - cd cdrskin-0.4.6 - -Within that directory execute: - - ./configure --prefix=/usr - make - -This will already produce a cdrskin binary. But it will be necessary to -install libburn in order to use this binary. Installation of libburn is -beyond the scope of cdrskin. For this, see included libburn docs. - -In order to surely get a standalone binary, execute - - cdrskin/compile_cdrskin.sh - -Version identification and help texts available afterwards: - cdrskin/cdrskin -version - cdrskin/cdrskin --help - 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. - -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.: - - cp cdrskin/cdrskin /usr/bin/cdrskin - -Check the version timestamps of the globally installed binary - cdrskin -version - -It is not necessary for the standalone cdrskin binary to have libburn -installed, since it incorporates the necessary libburn parts at compile time. -It will not collide with an installed version of libburn either. -But libpthread must be installed on the system and glibc has to match. (See -below for a way to create a statically linked binary.) - -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 - -The user of cdrskin needs rw-permission for the CD burner device. -A list of rw-accessible drives can be obtained by - - cdrskin --devices - -CD devices which offer no rw-permission are invisible to normal users. -The superuser should be able to see any usable drive and then set the -permissions as needed. If this hangs then there is a drive with -unexpected problems (locked, busy, broken, whatever). You might have to -guess the address of your (non-broken) burner by other means, then. -On Linux 2.4 this would be some /dev/sgN and on 2.6. some /dev/srM or /dev/hdX. - -The output of cdrskin --devices might look like - - 0 dev='/dev/sr0' rwrwr- : '_NEC' 'DVD_RW ND-4570A' - 1 dev='/dev/sr1' rwrw-- : 'HL-DT-ST' 'DVDRAM GSA-4082B' - -So full and insecure enabling of both for everybody would look like - - chmod a+rw /dev/sr0 /dev/sr1 - -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 - -For options and recordable media classes see - man 1 cdrskin - -Get an overview of cdrecord style addresses of available devices - cdrskin -scanbus - cdrskin dev=ATA -scanbus - cdrskin --devices - -Adresses reported with dev=ATA need prefix "ATA:". Address examples: - dev=0,1,0 dev=ATA:1,0,0 dev=/dev/sg1 dev=/dev/hdc dev=/dev/sr0 -See also "Drive Addressing" below. - -Obtain some info about the drive - cdrskin dev=0,1,0 -checkdrive - -Obtain some info about the drive and the inserted media - cdrskin dev=0,1,0 -atip -v - -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 - -De-format DVD-RW to make it capable of multi-session again - cdrskin -v dev=/dev/sr0 blank=deformat_sequential - -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] - cdrskin dev=/dev/hdc padsize=300k -multi 1.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 -tao \ - driveropts=burnfree padsize=300k - - -Burn 6 audio tracks from files with different formats to CD (not to any DVD). -Anything except .wav or .au files has to be converted into raw format first. -See below "Audio CD" for specifications. - ogg123 -d raw -f track01.cd /path/to/track1.ogg - oggdec -R -o track02.cd /path/to/track2.ogg - lame --decode -t /path/to/track3.mp3 track03.cd - madplay -o raw:track04.cd /path/to/track4.mp3 - mppdec --raw-le /path/to/track5.mpc track05.cd - - cdrskin -v dev=0,1,0 blank=fast -eject speed=48 -sao \ - -audio -swab track0[1-5].cd /path/to/track6.wav - - - Restrictions - -Several advanced CD related options of cdrecord are still unsupported. -See output of command - cdrskin --list_ignored_options -If you have use cases for them, please report your wishes and expectations. - -DVD support is restricted to single layer DVD for now. Double layer media -are implemented but untested. -On the other hand, the capability of multi-session and of writing streams -of unpredicted lenght surpass the current DVD capabilities of cdrecord. - - - 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.) - -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. -I have the hope that Joerg feels more flattered than annoyed by cdrskin. - -Many thanks to Andy Polyakov for his dvd+rw-tools - http://fy.chalmers.se/~appro/linux/DVD+RW/tools -which provide me with examples and pointers into MMC specs for DVD writing. - - - Startup Files - -If not --no_rc is the first argument then cdrskin attempts on startup to read -arguments from the following three files: - /etc/default/cdrskin - /etc/opt/cdrskin/rc - /etc/cdrskin/cdrskin.conf - $HOME/.cdrskinrc -The files are read in the sequence given above. -Each readable line is treated as one single argument. No extra blanks. -A first character '#' marks a comment, empty lines are ignored. - -Example content of a startup file: -# This is the default device -dev=0,1,0 - -# Some more options -fifo_start_at=0 -fs=16m - - - Audio CD - -Lorenzo Taylor enabled option -audio in cdrskin (thanks !) and reports neat -results with audio data files which are : - headerless PCM (i.e. uncompressed) - 44100 Hz sampling rate - 16 bits per sample - stereo (2 channels) - little-endian byte order with option -swab, or big-endian without -swab - -Files with name extension .wav get examined wether they are in Microsoft WAVE -format with above parameters and eventually get extracted by cdrskin itself. -In the same way files with name extension .au get examined wether they are -in SUN's audio format. For both formats, track format -audio and eventual -endianness option -swab are enabled automatically. - -Any other formats are to be converted to format .wav with above parameters -or to be extracted as raw CD track data by commands like those given above -under "Usage examples". Those raw files need option -audio and in most cases -option -swab to mark them as little-endian/Intel/LSB-first 16-bit data. -Incorrect endianness setting results in random noise on CD. - -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 - -These random access 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. - -BD-RE media need formatting before first use. cdrskin option "blank=as_needed" -recognizes unformatted BD-RE and applies a lengthy formatting run. - -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 ... - - - - DVD-RW and DVD-R - -DVD-RW are usable if formatted to state "Restricted Overwrite" or if in state -"Sequential Recording". DVD-R are always in sequential state. - -"Sequential" is the state of unused media and of media previously blanked -or written by cdrecord. dvd+rw-format -blank can also achieve this state. -The according cdrskin option is blank=deformat_sequential . -If "Incremental Streaming" is available, then sequential media are capable -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 -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.) - -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.) - -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 -drive and media, formatting can yield unusable media. It seems that those die -too on blanking by cdrecord, dvd+rw-format or cdrskin. Perils of DVD-RW. - -There are three DVD-RW formatting variants with cdrskin currently: - -blank=format_overwrite uses "DVD-RW Quick" formatting (MMC-type 15h) -and writes a first session of 128 MiB. This leads to media which are expandable -and random addressable by cdrskin. - -blank=format_overwrite_quickest uses "DVD-RW Quick" formatting (type 15h) too, -but leaves the media in "intermediate" state. In the first session of writing -one may only write sequentially to such a DVD. After that, it gets random -addressable by cdrskin. DVD-ROM drives might show ill behavior with them. - -blank=format_overwrite_full uses preferrably "Full Format" (type 00h). -This formatting lasts as long as writing a full DVD. It includes writing of -lead-out which is said to be good for DVD ROM compatibility. - -De-formatting options are available to make overwriteable DVD-RW sequential: - -blank=deformat_sequential performs thorough blanking of all states of DVD-RW. -blank=all and blank=fast perform the same thorough blanking, but refuse to do -this with overwriteable DVD-RW, thus preserving their formatting. The specs -allow minimal blanking but the resulting media on my drives offer no -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 - -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 ia 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. - - ------------------------------------------------------------------------------- - - Special compilation variations - -You may get a (super fat) statically linked binary by : - cdrskin/compile_cdrskin.sh -static -if your system supports static linking, at all. This will not help with kernels -which do not properly support the necessary low-level interfaces chosen by -your compile-time libraries. - -A size reduced but fully functional binary may be produced by - cdrskin/compile_cdrskin.sh -do_strip - -An extra lean binary with reduced capabilities is created by - cdrskin/compile_cdrskin.sh -do_diet -do_strip -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 implied the need to reboot the -system because of drives gnawing endlessly on ill media. Permanent hardware -damage did not occur in 1.5 years of development. - ------------------------------------------------------------------------------- - -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. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - 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 and Thomas Schmitt -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 and - Ben Jansens -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: ------------------------------------------------------------------------------- - -We, the copyright holders, agree on the interpretation that -dynamical linking of our libraries constitutes "use of" and -not "derivation from" our work in the sense of GPL, provided -those libraries are compiled from our unaltered code. - -Thus you may link our libraries dynamically with applications -which are not under GPL. You may distribute our libraries and -application tools in binary form, if you fulfill the usual -condition of GPL to offer a copy of the source code -altered -or unaltered- under GPL. - -We ask you politely to use our work in open source spirit -and with the due reference to the entire open source community. - -If there should really arise the case where above clarification -does not suffice to fulfill a clear and neat request in open source -spirit that would otherwise be declined for mere formal reasons, -only in that case we will duely consider to issue a special license -covering only that special case. -It is the open source idea of responsible freedom which will be -decisive and you will have to prove that you exhausted all own -means to qualify for GPL. - -For now we are firmly committed to maintain one single license: GPL. - -signed for cdrskin: Thomas Schmitt diff --git a/cdrskin/add_ts_changes_to_libburn_0_4_6 b/cdrskin/add_ts_changes_to_libburn_0_4_6 deleted file mode 100755 index e632a10..0000000 --- a/cdrskin/add_ts_changes_to_libburn_0_4_6 +++ /dev/null @@ -1,244 +0,0 @@ -#!/bin/sh - -set -x - -# This script documents how this cdrskin version was derived from -# a vanilla libburn version. It is not intended nor needed for any -# use of cdrskin but included here only to show the technical -# relationship between both projects - which are close friends -# and issue roughly the same software. -# -# Package maintainers are advised to cover rather libburn than -# cdrskin unless they put only emphasis on the cdrecord emulation -# provided by cdrskin. libburn contains cdrskin - cdrskin is an -# oscillating, friendly and coordinated fork of libburn. -# -# Script results are a source tarball and two binaries -# one dynamic and one static in respect to system libs. -# Both binaries are static in respect to libburn. -# -# The script is to be run in the directory above the toplevel -# directory of libburn resp. cdrskin development. -# - -# The top level directory in the SVN snapshot is named -intermediate="./libburn_pykix" - -# libburn source used: http://libburnia.pykix.org -# Downloaded by: -# $ 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_release.tgz" -# Historic moments: -# original="./libburn_svn_A60815.tgz" -# original="./libburn_cdrskin_A60819.tgz" - - -# My changes are in $changes , mainly in $changes/cdrskin -changes="./libburn-release" - -skin_release="0.4.6" -patch_level=".pl00" -skin_rev="$skin_release""$patch_level" - -# The result directory and the name of the result tarballs -target="./cdrskin-${skin_release}" -cdrskin_tarball="./cdrskin-${skin_rev}.tar.gz" -cdrskin_tarball_svn="./cdrskin-${skin_rev}.svn.tar.gz" - -# (This once earned me an embarrassingly blooping source tarball) -# compile_dir="$changes" - -compile_dir="$target" -compile_cmd="./cdrskin/compile_cdrskin.sh" -compile_static_opts="-static" -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_static="$bintarget_dynamic"-static - -if test -d "$changes" -then - dummy=dummy -else - echo "$0 : FATAL : no directory $changes" >&2 - exit 1 -fi - -for i in "$target" "$intermediate" -do - if test -e "$i" - then - echo "$0 : FATAL : already existing $i" >&2 - exit 2 - fi -done - -if test -f "$original" -then - dummy=dummy -else - echo "$0 : FATAL : no file $original" >&2 - exit 3 -fi - - -# Unpack SVN snapshot. -tar xzf "$original" - - -# Rename the directory to the cdrskin name -mv "$intermediate" "$target" - - -# Copy the changes from the development tree -# -cdrskin_dir="$changes"/cdrskin -libburn_dir="$changes"/libburn -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 - -# Add the cdrskin files -if test -e "$cdrskin_target" -then - rm -rf "$cdrskin_target" -fi -cp -a "$cdrskin_dir" "$cdrskin_target" - -# Remove copied vim.swp and binaries -rm "$cdrskin_target"/.*.swp -rm "$cdrskin_target"/*.o -rm "$cdrskin_target"/cdrfifo -rm "$cdrskin_target"/cdrskin -rm "$cdrskin_target"/cleanup -for i in std new make old -do - if test -e "$cdrskin_target"/cdrskin_"$i" - then - rm "$cdrskin_target"/cdrskin_"$i" - fi -done - -# Remove eventual SVN stuff from cdrskin directory -for i in .deps .dirstamp .libs -do - if test -e "$cdrskin_target"/"$i" - then - rm -rf "$cdrskin_target"/"$i" - fi -done - -# Remove GIFs of cdrskin_eng.html -rm "$cdrskin_target"/doener_*.gif "$cdrskin_target"/doener_*.png - -# Remove automatically generated HTML man page -rm "$cdrskin_target"/man_1_cdrskin.html - -# Remove all add_ts_changes_to_libburn besides this one -for i in "$cdrskin_target"/add_ts_changes_to_libburn* -do - if test $(basename "$0") = $(basename "$i") - then - dummy=dummy - else - rm $i - fi -done - -# Remove libcevap -rm -rf "$target"/libcevap - - -# Remove unwanted SVN stuff (TODO: avoid downloading it) -for i in "$target"/.svn "$target"/*/.svn -do - if test "$i" = "$target"'/*/.svn' - then - dummy=dummy - else - if test -e "$i" - then - rm -rf "$i" - fi - fi -done - - -# Make SVN state tarball for the libburn team -tar czf "$cdrskin_tarball_svn" "$target" - - -# Get over dependecy on autotools. Rely only on cc, make et. al. -# This is not the same as "make dist" but i can do it without -# having to evaluate the quality of said "make dist" -# -( cd "$target" ; ./bootstrap ) - -# Remove unwanted stuff after bootstrap -for i in "$target"/autom4te.cache -do - if echo "$i" | grep '\*' >/dev/null - then - dummy=dummy - else - if test -e "$i" - then - rm -rf "$i" - fi - fi -done - -# Repair non-portable shell code output of ./bootstrap -( - cd "$compile_dir" || exit 1 - sed -e 's/^for ac_header in$/test -z 1 \&\& for ac_header in dummy/' \ - < ./configure > ./configure-repaired - if test "$?" = 0 - then - echo "$0: Empty 'for ac_header in' found in configure." >&2 - fi - mv ./configure-repaired ./configure - chmod a+rx,go-w,u+w ./configure -) - -# Pack it up to the new libburn+cdrskin-tarball -tar czf "$cdrskin_tarball" "$target" - -# Produce a static and a dynamic binary, and a HTML man page -( - cd "$compile_dir" || exit 1 - ./configure - make - "$compile_cmd" -O2 -do_strip - cp "$compile_result" "../$bintarget_dynamic" - if test -n "$compile_static_opts" - then - "$compile_cmd" $compile_static_opts -O2 -do_strip - cp "$compile_result" "../$bintarget_static" - fi - "$man_to_html_cmd" - mv "$man_page_html" .. -) - -# Remove the build area -# Disable this for debugging the merge process -rm -rf "$target" - -# Show the result -./"$bintarget_dynamic" -version -./"$bintarget_static" -version -ls -l "$cdrskin_tarball" -ls -l "$bintarget_dynamic" -ls -l "$bintarget_static" -ls -l $(basename "$man_page_html") - diff --git a/cdrskin/add_ts_changes_to_libburn_0_4_7 b/cdrskin/add_ts_changes_to_libburn_0_4_7 deleted file mode 100755 index 3da243e..0000000 --- a/cdrskin/add_ts_changes_to_libburn_0_4_7 +++ /dev/null @@ -1,245 +0,0 @@ -#!/bin/sh - -set -x - -# This script documents how this cdrskin version was derived from -# a vanilla libburn version. It is not intended nor needed for any -# use of cdrskin but included here only to show the technical -# relationship between both projects - which are close friends -# and issue roughly the same software. -# -# Package maintainers are advised to cover rather libburn than -# cdrskin unless they put only emphasis on the cdrecord emulation -# provided by cdrskin. libburn contains cdrskin - cdrskin is an -# oscillating, friendly and coordinated fork of libburn. -# -# Script results are a source tarball and two binaries -# one dynamic and one static in respect to system libs. -# Both binaries are static in respect to libburn. -# -# The script is to be run in the directory above the toplevel -# directory of libburn resp. cdrskin development. -# - -# The top level directory in the SVN snapshot is named -intermediate="./libburn_pykix" - -# libburn source used: http://libburnia-project.org -# Downloaded by: -# $ svn co http://libburnia-project.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" -# Historic moments: -# original="./libburn_svn_A60815.tgz" -# original="./libburn_cdrskin_A60819.tgz" - - -# My changes are in $changes , mainly in $changes/cdrskin -changes="./libburn-develop" - -skin_release="0.4.7" -patch_level="" -skin_rev="$skin_release""$patch_level" - -# The result directory and the name of the result tarballs -target="./cdrskin-${skin_release}" -cdrskin_tarball="./cdrskin-${skin_rev}.tar.gz" -cdrskin_tarball_svn="./cdrskin-${skin_rev}.svn.tar.gz" - -# (This once earned me an embarrassingly blooping source tarball) -# compile_dir="$changes" - -compile_dir="$target" -compile_cmd="./cdrskin/compile_cdrskin.sh" -compile_static_opts="-static" -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_static="$bintarget_dynamic"-static - -if test -d "$changes" -then - dummy=dummy -else - echo "$0 : FATAL : no directory $changes" >&2 - exit 1 -fi - -for i in "$target" "$intermediate" -do - if test -e "$i" - then - echo "$0 : FATAL : already existing $i" >&2 - exit 2 - fi -done - -if test -f "$original" -then - dummy=dummy -else - echo "$0 : FATAL : no file $original" >&2 - exit 3 -fi - - -# Unpack SVN snapshot. -tar xzf "$original" - - -# Rename the directory to the cdrskin name -mv "$intermediate" "$target" - - -# Copy the changes from the development tree -# -cdrskin_dir="$changes"/cdrskin -libburn_dir="$changes"/libburn -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 - -# Add the cdrskin files -if test -e "$cdrskin_target" -then - rm -rf "$cdrskin_target" -fi -cp -a "$cdrskin_dir" "$cdrskin_target" - -# Remove copied vim.swp and binaries -rm "$cdrskin_target"/.*.swp -rm "$cdrskin_target"/*.o -rm "$cdrskin_target"/cdrfifo -rm "$cdrskin_target"/cdrskin -rm "$cdrskin_target"/cleanup -for i in std new make old -do - if test -e "$cdrskin_target"/cdrskin_"$i" - then - rm "$cdrskin_target"/cdrskin_"$i" - fi -done - -# Remove eventual SVN stuff from cdrskin directory -for i in .deps .dirstamp .libs -do - if test -e "$cdrskin_target"/"$i" - then - rm -rf "$cdrskin_target"/"$i" - fi -done - -# Remove GIFs of cdrskin_eng.html -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 - if test $(basename "$0") = $(basename "$i") - then - dummy=dummy - else - rm $i - fi -done - -# Remove unwanted SVN stuff (TODO: avoid downloading it) -for i in "$target"/.svn "$target"/*/.svn -do - if test "$i" = "$target"'/*/.svn' - then - dummy=dummy - else - if test -e "$i" - then - rm -rf "$i" - fi - fi -done - - -# Make SVN state tarball for the libburn team -tar czf "$cdrskin_tarball_svn" "$target" - - -# Get over dependecy on autotools. Rely only on cc, make et. al. -# This is not the same as "make dist" but i can do it without -# having to evaluate the quality of said "make dist" -# -( cd "$target" ; ./bootstrap ) - -# Remove unwanted stuff after bootstrap -for i in "$target"/autom4te.cache -do - if echo "$i" | grep '\*' >/dev/null - then - dummy=dummy - else - if test -e "$i" - then - rm -rf "$i" - fi - fi -done - -# Repair non-portable shell code output of ./bootstrap -( - cd "$compile_dir" || exit 1 - sed -e 's/^for ac_header in$/test -z 1 \&\& for ac_header in dummy/' \ - < ./configure > ./configure-repaired - if test "$?" = 0 - then - echo "$0: Empty 'for ac_header in' found in configure." >&2 - fi - mv ./configure-repaired ./configure - chmod a+rx,go-w,u+w ./configure -) - - -# Pack it up to the new libburn+cdrskin-tarball -tar czf "$cdrskin_tarball" "$target" - -# Produce a static and a dynamic binary, and a HTML man page -( - cd "$compile_dir" || exit 1 - ./configure - make - "$compile_cmd" -libburn_svn -O2 -do_strip - cp "$compile_result" "../$bintarget_dynamic" - if test -n "$compile_static_opts" - then - "$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" .. -) - -# Remove the build area -# Disable this for debugging the merge process -rm -rf "$target" - -# Show the result -./"$bintarget_dynamic" -version -./"$bintarget_static" -version -ls -l "$cdrskin_tarball" -ls -l "$bintarget_dynamic"* -ls -l "$bintarget_static" -ls -l $(basename "$man_page_html") - diff --git a/cdrskin/cdrecord_spy.sh b/cdrskin/cdrecord_spy.sh deleted file mode 100755 index 54d7c34..0000000 --- a/cdrskin/cdrecord_spy.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh -# -# Spying on the call to cdrecord. -# -# Move $(which cdrecord) to $(dirname $(which cdrecord))/real_cdrecord . -# Install this sript instead. (Do not forget to revoke this after the test.) -# - -# The report target is set in variable rt. -# The default is this file : -rt=/tmp/cdrecord_spy_log - -# To use a bystanding xterm as target i find out the pty address by -# executing in that terminal -# sleep 12345 -# and then running in another terminal -# ps -ef | grep 'sleep 12345' -# which answers something like -# thomas 21303 30518 0 14:02 pts/23 00:00:00 sleep 12345 -# thomas 21421 30523 0 14:02 pts/24 00:00:00 grep sleep 12345 -# from which i learn that pts/23 is sleeping 12345. Now sleep can be aborted. -# -# rt=/dev/pts/23 - -echo '------------------------------------- cdrecord_spy 0.1.0 -------' >>"$rt" -date >>"$rt" -echo '----------------------------------------------------------------' >>"$rt" -echo "$0" >>"$rt" -for i in "$@" -do - echo "$i" >>"$rt" -done -echo '------------------------------------- cdrecord_spy 0.1.0 - end -' >>"$rt" - -real_cdrecord "$@" - - diff --git a/cdrskin/cdrfifo.c b/cdrskin/cdrfifo.c deleted file mode 100644 index e61c533..0000000 --- a/cdrskin/cdrfifo.c +++ /dev/null @@ -1,1253 +0,0 @@ -/* - cdrfifo.c , Copyright 2006 Thomas Schmitt - - A fd-to-fd or fd-to-memory fifo to be used within cdrskin or independently. - By chaining of fifo objects, several fifos can be run simultaneously - in fd-to-fd mode. Modes are controlled by parameter flag of - Cdrfifo_try_to_work(). - - Provided under GPL license within cdrskin and under BSD license elsewise. -*/ - -/* - Compile as standalone tool : - cc -g -o cdrfifo -DCdrfifo_standalonE cdrfifo.c -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cdrfifo.h" - - -/* Macro for creation of arrays of objects (or single objects) */ -#define TSOB_FELD(typ,anz) (typ *) malloc((anz)*sizeof(typ)); - - -#define Cdrfifo_buffer_chunK 2048 - -/** Number of follow-up fd pairs */ -#define Cdrfifo_ffd_maX 100 - - -/* 1= enable , 0= disable status messages to stderr - 2= report each -*/ -static int Cdrfifo_debuG= 0; - - -struct CdrfifO { - int chunk_size; - - int source_fd; - double in_counter; - - double fd_in_counter; - double fd_in_limit; - - char *buffer; - int buffer_size; - int buffer_is_full; - int write_idx; - int read_idx; - - int dest_fd; - double out_counter; - - struct timeval start_time; - double speed_limit; - - /* statistics */ - double interval_counter; - struct timeval interval_start_time; - double interval_start_counter; - int total_min_fill; - int interval_min_fill; - - double put_counter; - double get_counter; - double empty_counter; - double full_counter; - - /* 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 */ - int follow_up_fds[Cdrfifo_ffd_maX][2]; - - /* index of first byte in buffer which does not belong to predecessor fd */ - int follow_up_eop[Cdrfifo_ffd_maX]; - /* if follow_up_eop[i]==buffer_size : read_idx was 0 when this was set */ - int follow_up_was_full_buffer[Cdrfifo_ffd_maX]; - - /* index of first byte in buffer which belongs to [this] fd pair */ - int follow_up_sod[Cdrfifo_ffd_maX]; - - /* values for fd_in_limit */ - double follow_up_in_limits[Cdrfifo_ffd_maX]; - - /* number of defined follow-ups */ - int follow_up_fd_counter; - - /* index of currently active (i.e. reading) follow-up */ - int follow_up_fd_idx; - - - /* (simultaneous) peer chaining */ - struct CdrfifO *next; - struct CdrfifO *prev; - - /* rank in peer chain */ - int chain_idx; -}; - - -/** Create a fifo object. - @param ff Returns the address of the new object. - @param source_fd Filedescriptor opened to a readable data stream. - @param dest_fd Filedescriptor opened to a writable data stream. - To work with libburn, it needs to be attached to a - struct burn_source object. - @param chunk_size Size of buffer block for a single transaction (0=default) - @param buffer_size Size of fifo buffer - @param flag Unused yet - @return 1 on success, <=0 on failure -*/ -int Cdrfifo_new(struct CdrfifO **ff, int source_fd, int dest_fd, - int chunk_size, int buffer_size, int flag) -{ - struct CdrfifO *o; - struct timezone tz; - int i; - - (*ff)= o= TSOB_FELD(struct CdrfifO,1); - if(o==NULL) - return(-1); - if(chunk_size<=0) - chunk_size= Cdrfifo_buffer_chunK; - o->chunk_size= chunk_size; - if(buffer_size%chunk_size) - buffer_size+= chunk_size-(buffer_size%chunk_size); - o->source_fd= source_fd; - o->in_counter= 0.0; - o->fd_in_counter= 0; - o->fd_in_limit= -1.0; - o->buffer= NULL; - o->buffer_is_full= 0; - o->buffer_size= buffer_size; - o->write_idx= 0; - o->read_idx= 0; - o->dest_fd= dest_fd; - o->out_counter= 0.0; - memset(&(o->start_time),0,sizeof(o->start_time)); - gettimeofday(&(o->start_time),&tz); - o->speed_limit= 0.0; - o->interval_counter= 0.0; - memset(&(o->interval_start_time),0,sizeof(o->interval_start_time)); - gettimeofday(&(o->interval_start_time),&tz); - o->interval_start_counter= 0.0; - o->total_min_fill= buffer_size; - o->interval_min_fill= buffer_size; - o->put_counter= 0.0; - o->get_counter= 0.0; - o->empty_counter= 0.0; - o->full_counter= 0.0; - o->iso_fs_size= -1.0; - o->iso_fs_descr= NULL; - for(i= 0; ifollow_up_fds[i][0]= o->follow_up_fds[i][1]= -1; - o->follow_up_eop[i]= o->follow_up_sod[i]= -1; - o->follow_up_was_full_buffer[i]= 0; - o->follow_up_in_limits[i]= -1.0; - } - o->follow_up_fd_counter= 0; - o->follow_up_fd_idx= -1; - o->next= o->prev= NULL; - o->chain_idx= 0; - o->buffer= TSOB_FELD(char,buffer_size); - if(o->buffer==NULL) - goto failed; - return(1); -failed:; - Cdrfifo_destroy(ff,0); - return(-1); -} - - -/** Close any output fds */ -int Cdrfifo_close(struct CdrfifO *o, int flag) -{ - int i; - - if(o->dest_fd!=-1) - close(o->dest_fd); - o->dest_fd= -1; - for(i=0; ifollow_up_fd_counter; i++) - if(o->follow_up_fds[i][1]!=-1) - close(o->follow_up_fds[i][1]); - o->follow_up_fds[i][1]= -1; - return(1); -} - - -/** Release from memory a fifo object previously created by Cdrfifo_new(). - @param ff The victim (gets returned as NULL, call can stand *ff==NULL)) - @param flag Bitfield for control purposes: - bit0= do not close destination fd -*/ -int Cdrfifo_destroy(struct CdrfifO **ff, int flag) -/* flag - bit0= do not close destination fd -*/ -{ - struct CdrfifO *o; - - o= *ff; - if(o==NULL) - return(0); - if(o->next!=NULL) - o->next->prev= o->prev; - if(o->prev!=NULL) - o->prev->next= o->next; - if(!(flag&1)) - Cdrfifo_close(o,0); - - /* 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); - (*ff)= NULL; - return(1); -} - - -int Cdrfifo_get_sizes(struct CdrfifO *o, int *chunk_size, int *buffer_size, - int flag) -{ - *chunk_size= o->chunk_size; - *buffer_size= o->buffer_size; - return(1); -} - -/** Set a speed limit for buffer output. - @param o The fifo object - @param bytes_per_second >0 catch up slowdowns over the whole run time - <0 catch up slowdowns only over one interval - =0 disable speed limit -*/ -int Cdrfifo_set_speed_limit(struct CdrfifO *o, double bytes_per_second, - int flag) -{ - o->speed_limit= bytes_per_second; - return(1); -} - - -/** Set a fixed size for input in order to cut off any unwanted tail - @param o The fifo object - @param idx index for fds attached via Cdrfifo_attach_follow_up_fds(), - first attached is 0, <0 directs limit to active fd limit - (i.e. first track is -1, second track is 0, third is 1, ...) -*/ -int Cdrfifo_set_fd_in_limit(struct CdrfifO *o, double fd_in_limit, int idx, - int flag) -{ - if(idx<0) { - o->fd_in_limit= fd_in_limit; - return(1); - } - if(idx >= o->follow_up_fd_counter) - return(0); - o->follow_up_in_limits[idx]= fd_in_limit; - return(1); -} - - -int Cdrfifo_set_fds(struct CdrfifO *o, int source_fd, int dest_fd, int flag) -{ - o->source_fd= source_fd; - o->dest_fd= dest_fd; - return(1); -} - - -int Cdrfifo_get_fds(struct CdrfifO *o, int *source_fd, int *dest_fd, int flag) -{ - *source_fd= o->source_fd; - *dest_fd= o->dest_fd; - return(1); -} - - -/** Attach a further pair of input and output fd which will use the same - fifo buffer when its predecessors are exhausted. Reading will start as - soon as reading of the predecessor encounters EOF. Writing will start - as soon as all pending predecessor data are written. - @return index number of new item + 1, <=0 indicates error -*/ -int Cdrfifo_attach_follow_up_fds(struct CdrfifO *o, int source_fd, int dest_fd, - int flag) -{ - if(o->follow_up_fd_counter>=Cdrfifo_ffd_maX) - return(0); - o->follow_up_fds[o->follow_up_fd_counter][0]= source_fd; - o->follow_up_fds[o->follow_up_fd_counter][1]= dest_fd; - o->follow_up_fd_counter++; - return(o->follow_up_fd_counter); -} - - -/** Attach a further fifo which shall be processed simultaneously with this - one by Cdrfifo_try_to_work() in fd-to-fd mode. -*/ -int Cdrfifo_attach_peer(struct CdrfifO *o, struct CdrfifO *next, int flag) -{ - int idx; - struct CdrfifO *s; - - for(s= o;s->prev!=NULL;s= s->prev); /* determine start of o-chain */ - for(;o->next!=NULL;o= o->next); /* determine end of o-chain */ - for(;next->prev!=NULL;next= next->prev); /* determine start of next-chain */ - next->prev= o; - o->next= next; - for(idx= 0;s!=NULL;s= s->next) - s->chain_idx= idx++; - return(1); -} - - -static int Cdrfifo_tell_buffer_space(struct CdrfifO *o, int flag) -{ - if(o->buffer_is_full) - return(0); - if(o->write_idx>=o->read_idx) - return((o->buffer_size - o->write_idx) + o->read_idx); - return(o->read_idx - o->write_idx); -} - - -/** Obtain buffer state. - @param o The buffer object - @param fill Returns the number of pending payload bytes in the buffer - @param space Returns the number of unused buffer bytes - @param flag Unused yet - @return -1=error , 0=inactive , 1=reading and writing , - 2=reading ended (but still writing) -*/ -int Cdrfifo_get_buffer_state(struct CdrfifO *o,int *fill,int *space,int flag) -/* return : - -1=error - 0=inactive - 1=reading and writing - 2=reading ended, still writing -*/ -{ - *space= Cdrfifo_tell_buffer_space(o,0); - *fill= o->buffer_size-(*space); - if(o->dest_fd==-1) - return(0); - if(o->source_fd<0) - return(2); - return(1); -} - - -int Cdrfifo_get_counters(struct CdrfifO *o, - double *in_counter, double *out_counter, int flag) -{ - *in_counter= o->in_counter; - *out_counter= o->out_counter; - return(1); -} - - -/** reads min_fill and begins measurement interval for next min_fill */ -int Cdrfifo_next_interval(struct CdrfifO *o, int *min_fill, int flag) -{ - struct timezone tz; - - o->interval_counter++; - gettimeofday(&(o->interval_start_time),&tz); - o->interval_start_counter= o->out_counter; - *min_fill= o->interval_min_fill; - o->interval_min_fill= o->buffer_size - Cdrfifo_tell_buffer_space(o,0); - return(1); -} - - -int Cdrfifo_get_min_fill(struct CdrfifO *o, int *total_min_fill, - int *interval_min_fill, int flag) -{ - *total_min_fill= o->total_min_fill; - *interval_min_fill= o->interval_min_fill; - return(1); -} - - -int Cdrfifo_get_iso_fs_size(struct CdrfifO *o, double *size_in_bytes, int flag) -{ - *size_in_bytes= o->iso_fs_size; - return(o->iso_fs_size>=2048); -} - - -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. -*/ -int Cdrfifo_get_cdr_counters(struct CdrfifO *o, - double *put_counter, double *get_counter, - double *empty_counter, double *full_counter, - int flag) -{ - *put_counter= o->put_counter; - *get_counter= o->get_counter; - *empty_counter= o->empty_counter; - *full_counter= o->full_counter; - return(1); -} - - -/** Adjust a given buffer fill value so it will not cross an eop boundary. - @param o The fifo to exploit. - @param buffer_fill The byte count to adjust. - @param eop_idx If eop boundary exactly hit: index of follow-up fd pair - @param flag Unused yet. - @return 0= nothing changed , 1= buffer_fill adjusted -*/ -int Cdrfifo_eop_adjust(struct CdrfifO *o,int *buffer_fill, int *eop_idx, - int flag) -{ - int i,eop_is_near= 0,valid_fill; - - *eop_idx= -1; - valid_fill= *buffer_fill; - for(i=0; i<=o->follow_up_fd_idx; i++) { - if(o->follow_up_eop[i]>=0 && o->follow_up_eop[i]>=o->read_idx) { - eop_is_near= 1; - if(o->follow_up_eop[i]buffer_size || o->read_idx>0) { - valid_fill= o->follow_up_eop[i]-o->read_idx; - o->follow_up_was_full_buffer[i]= 0; - } else { - /* - If an input fd change hit exactly the buffer end then follow_up_eop - points to buffer_size and not to 0. So it is time to switch output - pipes unless this is immediately after follow_up_eop was set and - read_idx was 0 (... if this is possible at all while write_idx is 0). - follow_up_was_full_buffer was set in this case and gets invalid as - soon as a non-0 read_idx is detected (see above). - */ - if(o->follow_up_was_full_buffer[i]) - valid_fill= o->buffer_size; - else - valid_fill= 0; /* the current pipe is completely served */ - } - if(valid_fill==0) - *eop_idx= i; - else if(valid_fillchunk_size) - eop_is_near= 2; /* for debugging. to carry a break point */ - break; - } - } - if(*buffer_fill>valid_fill) - *buffer_fill= valid_fill; - return(!!eop_is_near); -} - - -/* Perform pre-select activities of Cdrfifo_try_to_work() */ -static int Cdrfifo_setup_try(struct CdrfifO *o, struct timeval start_tv, - double start_out_counter, int *still_to_wait, - int *speed_limiter, int *ready_to_write, - fd_set *rds, fd_set *wts, int *max_fd, int flag) -/* flag: - bit0= enable debug pacifier (same with Cdrfifo_debuG) - bit1= do not write, just fill buffer - bit2= fd-to-memory mode (else fd-to-fd mode): - rather than writing a chunk return it and its size in reply_* - bit3= with bit2: do not check destination fd for readiness -*/ -{ - int buffer_space,buffer_fill,eop_reached= -1,eop_is_near= 0,was_closed; - int fd_buffer_fill, eop_reached_counter= 0; - struct timeval current_tv; - struct timezone tz; - double diff_time,diff_counter,limit,min_wait_time; - -setup_try:; - buffer_space= Cdrfifo_tell_buffer_space(o,0); - fd_buffer_fill= buffer_fill= o->buffer_size - buffer_space; - -#ifdef NIX - fprintf(stderr,"cdrfifo_debug: o->write_idx=%d o->read_idx=%d o->source_fd=%d\n",o->write_idx,o->read_idx,o->source_fd); - if(buffer_fill>10) - sleep(1); -#endif - - if(o->follow_up_fd_idx>=0) - eop_is_near= Cdrfifo_eop_adjust(o,&fd_buffer_fill,&eop_reached,0); - - if(fd_buffer_fill<=0 && (o->source_fd==-1 || eop_reached>=0) ) { - was_closed= 0; - if(o->dest_fd!=-1 && !(flag&4)) - close(o->dest_fd); - if(o->dest_fd<0) - was_closed= 1; - else - o->dest_fd= -1; - - if(eop_reached>=0) { /* switch to next output fd */ - o->dest_fd= o->follow_up_fds[eop_reached][1]; - if(Cdrfifo_debuG) - fprintf(stderr,"\ncdrfifo %d: new fifo destination fd : %d\n", - o->chain_idx,o->dest_fd); - o->read_idx= o->follow_up_sod[eop_reached]; - o->follow_up_eop[eop_reached]= -1; - eop_is_near= 0; - eop_reached= -1; - eop_reached_counter= 0; - goto setup_try; - } else { - /* work is really done */ - if((!was_closed) && ((flag&1)||Cdrfifo_debuG)) - fprintf(stderr, - "\ncdrfifo %d: w=%d r=%d | b=%d s=%d | i=%.f o=%.f (done)\n", - o->chain_idx,o->write_idx,o->read_idx,buffer_fill,buffer_space, - o->in_counter,o->out_counter); - return(2); - } - } else if(eop_reached>=0) - eop_reached_counter++; - if(o->interval_counter>0) { - if(o->total_min_fill>buffer_fill && o->source_fd>=0) - o->total_min_fill= buffer_fill; - if(o->interval_min_fill>buffer_fill) - o->interval_min_fill= buffer_fill; - } - *speed_limiter= 0; - if(o->speed_limit!=0) { - gettimeofday(¤t_tv,&tz); - if(o->speed_limit>0) { - diff_time= ((double) current_tv.tv_sec)-((double) o->start_time.tv_sec)+ - (((double) current_tv.tv_usec)-((double) o->start_time.tv_usec))*1e-6; - diff_counter= o->out_counter; - limit= o->speed_limit; - } else if(flag&4) { - if(o->interval_start_time.tv_sec==0) - o->interval_start_time= start_tv; - diff_time= ((double) current_tv.tv_sec) - - ((double) o->interval_start_time.tv_sec) - + (((double) current_tv.tv_usec) - -((double) o->interval_start_time.tv_usec))*1e-6; - diff_counter= o->out_counter - o->interval_start_counter; - limit= -o->speed_limit; - } else { - diff_time= ((double) current_tv.tv_sec) - ((double) start_tv.tv_sec) - + (((double) current_tv.tv_usec) - -((double)start_tv.tv_usec))*1e-6; - diff_counter= o->out_counter - start_out_counter; - limit= -o->speed_limit; - } - if(diff_time>0.0) - if(diff_counter/diff_time>limit) { - min_wait_time= (diff_counter/limit - diff_time)*1.0e6; - if(min_wait_time<*still_to_wait) - *still_to_wait= min_wait_time; - if(*still_to_wait>0) - *speed_limiter= 1; - } - } - if(o->source_fd>=0) { - if(buffer_space>0) { - FD_SET((o->source_fd),rds); - if(*max_fdsource_fd) - *max_fd= o->source_fd; - } else if(o->interval_counter>0) - o->full_counter++; - } - *ready_to_write= 0; - if(o->dest_fd>=0 && (!(flag&2)) && !*speed_limiter) { - if(fd_buffer_fill>=o->chunk_size || o->source_fd<0 || eop_is_near) { - if((flag&(4|8))==(4|8)) { - *still_to_wait= 0; - *ready_to_write= 1; - } else { - FD_SET((o->dest_fd),wts); - if(*max_fddest_fd) - *max_fd= o->dest_fd; - } - } else if(o->interval_counter>0) - o->empty_counter++; - } - return(1); -} - - -/* Perform post-select activities of Cdrfifo_try_to_work() */ -static int Cdrfifo_transact(struct CdrfifO *o, fd_set *rds, fd_set *wts, - char *reply_buffer, int *reply_count, int flag) -/* flag: - bit0= enable debug pacifier (same with Cdrfifo_debuG) - bit1= do not write, just fill buffer - bit2= fd-to-memory mode (else fd-to-fd mode): - rather than writing a chunk return it and its size in reply_* - bit3= with bit2: do not check destination fd for readiness -return: <0 = error , 0 = idle , 1 = did some work -*/ -{ - double buffer_space; - int can_read,can_write,ret,did_work= 0,idx,sod,eop_is_near,eop_idx; - - buffer_space= Cdrfifo_tell_buffer_space(o,0); - if(o->dest_fd>=0) if(FD_ISSET((o->dest_fd),wts)) { - can_write= o->buffer_size - buffer_space; - if(can_write>o->chunk_size) - can_write= o->chunk_size; - if(o->read_idx+can_write > o->buffer_size) - can_write= o->buffer_size - o->read_idx; - if(o->follow_up_fd_idx>=0) { - eop_is_near= Cdrfifo_eop_adjust(o,&can_write,&eop_idx,0); - if(can_write<=0) - goto after_write; - } - if(flag&4) { - memcpy(reply_buffer,o->buffer+o->read_idx,can_write); - *reply_count= ret= can_write; - } else { - ret= write(o->dest_fd,o->buffer+o->read_idx,can_write); - } - if(ret==-1) { - - /* >>> handle broken pipe */; - fprintf(stderr,"\ncdrfifo %d: on write: errno=%d , \"%s\"\n", - o->chain_idx,errno, - errno==0?"-no error code available-":strerror(errno)); - - if(!(flag&4)) - close(o->dest_fd); - o->dest_fd= -1; - {ret= -1; goto ex;} - } - did_work= 1; - o->get_counter++; - o->out_counter+= can_write; - o->read_idx+= can_write; - if(o->read_idx>=o->buffer_size) - o->read_idx= 0; - o->buffer_is_full= 0; - } -after_write:; - if(o->source_fd>=0) if(FD_ISSET((o->source_fd),rds)) { - can_read= o->buffer_size - o->write_idx; - if(can_read>o->chunk_size) - can_read= o->chunk_size; - if(o->write_idxread_idx && o->write_idx+can_read > o->read_idx) - can_read= o->read_idx - o->write_idx; - if(o->fd_in_limit>=0.0) - if(can_read > o->fd_in_limit - o->fd_in_counter) - can_read= o->fd_in_limit - o->fd_in_counter; - ret= 0; - if(can_read>0) - ret= read(o->source_fd,o->buffer+o->write_idx,can_read); - if(ret==-1) { - - /* >>> handle input error */; - fprintf(stderr,"\ncdrfifo %d: on read: errno=%d , \"%s\"\n", - o->chain_idx,errno, - errno==0?"-no error code available-":strerror(errno)); - - o->source_fd= -1; - } else if(ret==0) { /* eof */ - /* activate eventual follow-up source fd */ - if(Cdrfifo_debuG || (flag&1)) - fprintf(stderr,"\ncdrfifo %d: on read(%d,buffer,%d): eof\n", - o->chain_idx,o->source_fd,can_read); - if(o->follow_up_fd_idx+1 < o->follow_up_fd_counter) { - idx= ++(o->follow_up_fd_idx); - o->source_fd= o->follow_up_fds[idx][0]; - /* End-Of-Previous */ - if(o->write_idx==0) { - o->follow_up_eop[idx]= o->buffer_size; - - /* A70304 : can this happen ? */ - o->follow_up_was_full_buffer[idx]= (o->read_idx==0); - - if(Cdrfifo_debuG || (flag&1)) - fprintf(stderr,"\ncdrfifo %d: write_idx 0 on eop: read_idx= %d\n", - o->chain_idx,o->read_idx); - - } else - o->follow_up_eop[idx]= o->write_idx; - /* Start-Of-Data . Try to start at next full chunk */ - sod= o->write_idx; - if(o->write_idx%o->chunk_size) - sod+= o->chunk_size - (o->write_idx%o->chunk_size); - /* but do not catch up to the read pointer */ - if((o->write_idx<=o->read_idx && o->read_idx<=sod) || sod==o->read_idx) - sod= o->write_idx; - if(sod>=o->buffer_size) - sod= 0; - o->follow_up_sod[idx]= sod; - o->write_idx= sod; - o->fd_in_counter= 0; - o->fd_in_limit= o->follow_up_in_limits[idx]; - if(Cdrfifo_debuG || (flag&1)) - fprintf(stderr,"\ncdrfifo %d: new fifo source fd : %d\n", - o->chain_idx,o->source_fd); - } else { - o->source_fd= -1; - } - } else { - did_work= 1; - o->put_counter++; - o->in_counter+= ret; - o->fd_in_counter+= ret; - o->write_idx+= ret; - if(o->write_idx>=o->buffer_size) - o->write_idx= 0; - if(o->write_idx==o->read_idx) - o->buffer_is_full= 1; - } - } - ret= !!did_work; -ex:; - return(ret); -} - - -/** 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 - chunk of data is transfered to and/or from the fifo. - This is done for the given fifo object and all members of its next-chain. - The check and transactions are repeated until a given timespan has elapsed. - libburn applications call this function in the burn loop instead of sleep(). - It may also be used instead of read(). Then it returns as soon as an output - transaction would be performed. See flag:bit2. - @param o The fifo object - @param wait_usec The time in microseconds after which the function shall - return. - @param reply_buffer with bit2: Returns write-ready buffer chunk and must - be able to take at least chunk_size bytes - @param reply_count with bit2: Returns number of writeable bytes in reply - @param flag Bitfield for control purposes: - bit0= Enable debug pacifier (same with Cdrfifo_debuG) - bit1= Do not write, just fill buffer - bit2= fd-to-memory mode (else fd-to-fd mode): - Rather than writing a chunk return it and its size. - No simultaneous processing of chained fifos. - bit3= With bit2: do not check destination fd for readiness - @return <0 = error , 0 = idle , 1 = did some work , 2 = all work is done -*/ -int Cdrfifo_try_to_work(struct CdrfifO *o, int wait_usec, - char *reply_buffer, int *reply_count, int flag) -{ - struct timeval wt,start_tv,current_tv; - struct timezone tz; - fd_set rds,wts,exs; - int ready,ret,max_fd= -1,buffer_space,dummy,still_active= 0; - int did_work= 0,elapsed,still_to_wait,speed_limiter= 0,ready_to_write= 0; - double start_out_counter; - struct CdrfifO *ff; - - start_out_counter= o->out_counter; - gettimeofday(&start_tv,&tz); - still_to_wait= wait_usec; - if(flag&4) - *reply_count= 0; - -try_again:; - /* is there still a destination open ? */ - for(ff= o; ff!=NULL; ff= ff->next) - if(ff->dest_fd!=-1) - break; - if(ff==NULL) - return(2); - FD_ZERO(&rds); - FD_ZERO(&wts); - FD_ZERO(&exs); - - for(ff= o; ff!=NULL; ff= ff->next) { - ret= Cdrfifo_setup_try(ff,start_tv,start_out_counter, - &still_to_wait,&speed_limiter,&ready_to_write, - &rds,&wts,&max_fd,flag&15); - if(ret<=0) - return(ret); - else if(ret==2) { - /* This fifo is done */; - } else - still_active= 1; - if(flag&2) - break; - } - if(!still_active) - return(2); - - if(still_to_wait>0 || max_fd>=0) { - wt.tv_sec= still_to_wait/1000000; - wt.tv_usec= still_to_wait%1000000; - ready= select(max_fd+1,&rds,&wts,&exs,&wt); - } else - ready= 0; - if(ready<=0) { - if(!ready_to_write) - goto check_wether_done; - FD_ZERO(&rds); - } - if(ready_to_write) - FD_SET((o->dest_fd),&wts); - - for(ff= o; ff!=NULL; ff= ff->next) { - ret= Cdrfifo_transact(ff,&rds,&wts,reply_buffer,reply_count,flag&15); - if(ret<0) - goto ex; - if(ret>0) - did_work= 1; - if(flag&2) - break; - } - -check_wether_done:; - if((flag&4) && *reply_count>0) - {ret= 1; goto ex;} - gettimeofday(¤t_tv,&tz); - elapsed= (current_tv.tv_sec-start_tv.tv_sec)*1000000 + - (((int) current_tv.tv_usec) - ((int) start_tv.tv_usec)); - still_to_wait= wait_usec-elapsed; - if(still_to_wait>0) - goto try_again; - ret= !!did_work; -ex:; - if(flag&4) { - gettimeofday(¤t_tv,&tz); - elapsed= (current_tv.tv_sec - o->interval_start_time.tv_sec)*1000000 - + (((int) current_tv.tv_usec) - - ((int) o->interval_start_time.tv_usec)); - } else - elapsed= wait_usec; - if(elapsed>=wait_usec) { - if((flag&1)||Cdrfifo_debuG>=2) { - fprintf(stderr,"\n"); - for(ff= o; ff!=NULL; ff= ff->next) { - buffer_space= Cdrfifo_tell_buffer_space(ff,0); - fprintf(stderr, - "cdrfifo %d: w=%d r=%d | b=%d s=%d | i=%.f o=%.f\n", - ff->chain_idx,ff->write_idx,ff->read_idx, - ff->buffer_size-buffer_space,buffer_space, - ff->in_counter,ff->out_counter); - } - } - if(flag&4) - Cdrfifo_next_interval(o,&dummy,0); - } - return(ret); -} - - -/** Fill the fifo as far as possible without writing to destination fd */ -int Cdrfifo_fill(struct CdrfifO *o, int size, int flag) -{ - int ret,fill= 0,space,state; - - while(1) { - state= Cdrfifo_get_buffer_state(o,&fill,&space,0); - if(state==-1) { - - /* >>> handle error */; - - return(0); - } else if(state!=1) - break; - if(space<=0) - break; - if(size>=0 && fill>=size) - break; - ret= Cdrfifo_try_to_work(o,100000,NULL,NULL,2); - if(ret<0) { - - /* >>> handle error */; - - return(0); - } - if(ret==2) - break; - } - -#ifndef Cdrfifo_standalonE - if(fill>=32*2048) { - int Scan_for_iso_size(unsigned char data[2048], double *size_in_bytes, - int flag); - int bs= 16*2048; - 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) - o->iso_fs_size= size; - } -#endif - - o->total_min_fill= fill; - o->interval_min_fill= fill; - return(1); -} - - -int Cdrfifo_close_all(struct CdrfifO *o, int flag) -{ - struct CdrfifO *ff; - - if(o==NULL) - return(0); - for(ff= o; ff->prev!=NULL; ff= ff->prev); - for(; ff!=NULL; ff= ff->next) - Cdrfifo_close(ff,0); - return(1); -} - - - -#ifdef Cdrfifo_standalonE - -/* ---------------------------------------------------------------------- */ - -/** Application example. See also cdrskin.c */ - - -double Scanf_io_size(char *text, int flag) -/* - bit0= default value -1 rather than 0 -*/ -{ - int c; - double ret= 0.0; - - if(flag&1) - ret= -1.0; - if(text[0]==0) - return(ret); - sscanf(text,"%lf",&ret); - c= text[strlen(text)-1]; - if(c=='k' || c=='K') ret*= 1024.0; - if(c=='m' || c=='M') ret*= 1024.0*1024.0; - if(c=='g' || c=='G') ret*= 1024.0*1024.0*1024.0; - if(c=='t' || c=='T') ret*= 1024.0*1024.0*1024.0*1024.0; - if(c=='p' || c=='P') ret*= 1024.0*1024.0*1024.0*1024.0*1024.0; - if(c=='e' || c=='E') ret*= 1024.0*1024.0*1024.0*1024.0*1024.0*1024.0; - if(c=='s' || c=='S') ret*= 2048.0; - return(ret); -} - - -/* This is a hardcoded test mock-up for two simultaneous fifos of which the - one runs with block size 2048 and feeds the other which runs with 2352. - Both fifos have the same number of follow_up pipes (tracks) which shall - be connected 1-to-1. -*/ -int Test_mixed_bs(char **paths, int path_count, - int fs_size, double speed_limit, double interval, int flag) -/* - bit0= debugging verbousity -*/ -{ - int fd_in[100],fd_out[100],ret,pipe_fds[100][2],real_out[100]; - int i,iv,stall_counter= 0,cycle_counter= 0.0; - char buf[10240], target_path[80]; - double in_counter, out_counter, prev_in= -1.0, prev_out= -1.0; - struct CdrfifO *ff_in= NULL, *ff_out= NULL; - - if(path_count<1) - return(2); - Cdrfifo_new(&ff_in,fd_in[0],fd_out[0],2048,fs_size,0); - for(i= 0; ichain_idx,ret); - if(ret<0) - return(-7); - break; - } - cycle_counter++; - Cdrfifo_get_counters(ff_in, &in_counter, &out_counter, 0); - if(prev_in == in_counter && prev_out == out_counter) - stall_counter++; - prev_in= in_counter; - prev_out= out_counter; - } - return(1); -} - - -/* This is a hardcoded test mock-up for two simultaneous fifos of which the - first one simulates the cdrskin fifo feeding libburn and the second one - simulates libburn and the burner at given speed. Both have two fd pairs - (i.e. tracks). The tracks are read from /u/test/cdrskin/in_[12] and - written to /u/test/cdrskin/out_[12]. -*/ -int Test_multi(int fs_size, double speed_limit, double interval, int flag) -/* - bit0= debugging verbousity -*/ -{ - int fd_in[4],fd_out[4],ret,pipe_fds[4][2],real_out[4],pipe_idx; - int i,iv; - char buf[10240]; - struct CdrfifO *ff1= NULL,*ff2= NULL; - - /* open four pairs of fds */ - fd_in[0]= open("/u/test/cdrskin/in_1",O_RDONLY); - fd_in[1]= open("/u/test/cdrskin/in_2",O_RDONLY); - fd_out[2]= open("/u/test/cdrskin/out_1", - O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); - fd_out[3]= open("/u/test/cdrskin/out_2", - O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); - if(pipe(pipe_fds[0])==-1) - return(-3); - if(pipe(pipe_fds[1])==-1) - return(-3); - fd_out[0]= pipe_fds[0][1]; - fd_out[1]= pipe_fds[1][1]; - fd_in[2]= pipe_fds[0][0]; - fd_in[3]= pipe_fds[1][0]; - for(i=0;i<4;i++) { - if(fd_in[i]==-1) - return(-1); - if(fd_out[i]==-1) - return(-2); - } - - /* Create two fifos with two sequential fd pairs each and chain them for - simultaneous usage. */ - Cdrfifo_new(&ff1,fd_in[0],fd_out[0],2048,fs_size,0); - Cdrfifo_new(&ff2,fd_in[2],fd_out[2],2048,2*1024*1024,0); /*burner cache 2 MB*/ - if(ff1==NULL || ff2==NULL) - return(-3); - Cdrfifo_set_speed_limit(ff2,speed_limit,0); - ret= Cdrfifo_attach_follow_up_fds(ff1,fd_in[1],fd_out[1],0); - if(ret<=0) - return(-4); - ret= Cdrfifo_attach_follow_up_fds(ff2,fd_in[3],fd_out[3],0); - if(ret<=0) - return(-4); - Cdrfifo_attach_peer(ff1,ff2,0); - - /* Let the fifos work */ - iv= interval*1e6; - while(1) { - ret= Cdrfifo_try_to_work(ff1,iv,NULL,NULL,flag&1); - if(ret<0 || ret==2) { /* <0 = error , 2 = work is done */ - fprintf(stderr,"\ncdrfifo %d: fifo ended work with ret=%d\n", - ff1->chain_idx,ret); - if(ret<0) - return(-7); - break; - } - } - return(1); -} - - -int main(int argc, char **argv) -{ - int i,ret,exit_value= 0,verbous= 1,fill_buffer= 0,min_fill,fifo_percent,fd; - double fs_value= 4.0*1024.0*1024.0,bs_value= 2048,in_counter,out_counter; - double interval= 1.0,speed_limit= 0.0; - char output_file[4096]; - struct CdrfifO *ff= NULL; - - strcpy(output_file,"-"); - fd= 1; - - for(i= 1; i1000.0) - interval= 1; - } else if(strncmp(argv[i],"of=",3)==0) { - if(strcmp(argv[i]+3,"-")==0 || argv[i][3]==0) - continue; - fd= open(argv[i]+3,O_WRONLY|O_CREAT); - if(fd<0) { - fprintf(stderr,"cdrfifo: FATAL : cannot open output file '%s'\n", - argv[i]+3); - fprintf(stderr,"cdrfifo: errno=%d , \"%s\"\n", - errno,errno==0?"-no error code available-":strerror(errno)); - {exit_value= 4; goto ex;} - } - } else if(strncmp(argv[i],"sl=",3)==0) { - speed_limit= Scanf_io_size(argv[i]+3,0); - } else if(strncmp(argv[i],"vb=",3)==0) { - sscanf(argv[i]+3,"%d",&verbous); - - } else if(strcmp(argv[i],"-mixed_bs_test")==0) { - - ret= Test_mixed_bs(argv+i+1,argc-i-1, - (int) fs_value,speed_limit,interval,(verbous>=2)); - fprintf(stderr,"Test_mixed_bs(): ret= %d\n",ret); - exit(ret<0); - - } else if(strcmp(argv[i],"-multi_test")==0) { - - if(speed_limit==0.0) - speed_limit= 10*150*1024; - ret= Test_multi((int) fs_value,speed_limit,interval,(verbous>=2)); - fprintf(stderr,"Test_multi(): ret= %d\n",ret); - exit(ret<0); - - } else { - fprintf(stderr,"cdrfifo 0.3 : stdin-to-stdout fifo buffer.\n"); - fprintf(stderr,"usage : %s [bs=block_size] [fl=fillfirst]\n",argv[0]); - fprintf(stderr," [fs=fifo_size] [iv=interval] [of=output_file]\n"); - fprintf(stderr," [sl=bytes_per_second_limit] [vb=verbosity]\n"); - fprintf(stderr,"fl=1 reads full buffer before writing starts.\n"); - fprintf(stderr,"sl>0 allows catch up for whole run time.\n"); - fprintf(stderr,"sl<0 allows catch up for single interval.\n"); - fprintf(stderr,"vb=0 is silent, vb=2 is debug.\n"); - fprintf(stderr,"example: cdrfifo bs=8k fl=1 fs=32m iv=0.1 sl=-5400k\n"); - if(strcmp(argv[i],"-help")!=0 && strcmp(argv[i],"--help")!=0) { - fprintf(stderr,"\ncdrfifo: FATAL : option not recognized: '%s'\n", - argv[i]); - exit_value= 1; - } - goto ex; - } - } - if(verbous>=1) { - fprintf(stderr, - "cdrfifo: bs=%.lf fl=%d fs=%.lf iv=%lf of='%s' sl=%.lf vb=%d\n", - bs_value,fill_buffer,fs_value,interval,output_file,speed_limit, - verbous); - } - - ret= Cdrfifo_new(&ff,0,fd,(int) bs_value,(int) fs_value,0); - if(ret<=0) { - fprintf(stderr, - "cdrfifo: FATAL : creation of fifo object with %.lf bytes failed\n", - fs_value); - {exit_value= 3; goto ex;} - } - if(speed_limit!=0.0) - Cdrfifo_set_speed_limit(ff,speed_limit,0); - if(fill_buffer) { - ret= Cdrfifo_fill(ff,0,0); - if(ret<=0) { - fprintf(stderr, - "cdrfifo: FATAL : initial filling of fifo buffer failed\n"); - {exit_value= 4; goto ex;} - } - } - while(1) { - ret= Cdrfifo_try_to_work(ff,(int) (interval*1000000.0), - NULL,NULL,(verbous>=2)); - if(ret<0) { - fprintf(stderr,"\ncdrfifo: FATAL : fifo aborted. errno=%d , \"%s\"\n", - errno,errno==0?"-no error code available-":strerror(errno)); - {exit_value= 4; goto ex;} - } else if(ret==2) { - if(verbous>=1) { - double put_counter,get_counter,empty_counter,full_counter; - int total_min_fill; - Cdrfifo_get_counters(ff,&in_counter,&out_counter,0); - fprintf(stderr,"\ncdrfifo: done : %.lf bytes in , %.lf bytes out\n", - in_counter,out_counter); - Cdrfifo_get_min_fill(ff,&total_min_fill,&min_fill,0); - fifo_percent= 100.0*((double) total_min_fill)/fs_value; - if(fifo_percent==0 && total_min_fill>0) - fifo_percent= 1; - Cdrfifo_get_cdr_counters(ff,&put_counter,&get_counter, - &empty_counter,&full_counter,0); - fprintf(stderr,"cdrfifo: fifo had %.lf puts and %.lf gets.\n", - put_counter,get_counter); - fprintf(stderr, -"cdrfifo: fifo was %.lf times empty and %.lf times full, min fill was %d%%.\n", - empty_counter,full_counter,fifo_percent); - } - break; - } - Cdrfifo_next_interval(ff,&min_fill,0); - } - -ex:; - Cdrfifo_destroy(&ff,0); - exit(exit_value); -} - - -#endif /* Cdrfifo_standalonE */ - diff --git a/cdrskin/cdrfifo.h b/cdrskin/cdrfifo.h deleted file mode 100644 index 1237d20..0000000 --- a/cdrskin/cdrfifo.h +++ /dev/null @@ -1,171 +0,0 @@ - -/* - cdrfifo.c , Copyright 2006 Thomas Schmitt - - A fd-to-fd or fd-to-memory fifo to be used within cdrskin or independently. - By chaining of fifo objects, several fifos can be run simultaneously - in fd-to-fd mode. Modes are controlled by parameter flag of - Cdrfifo_try_to_work(). - - Provided under GPL license within cdrskin and under BSD license elsewise. -*/ - -#ifndef Cdrfifo_headerfile_includeD -#define Cdrfifo_headerfile_includeD - - -/** The fifo buffer which will smoothen the data stream from data provider - to data consumer. Although this is not a mandatory lifesaver for modern - burners any more, a fifo can speed up burning of data which is delivered - with varying bandwidths (e.g. compressed archives created on the fly - or mkisofs running at its speed limit.). - This structure is opaque to applications and may only be used via - the Cdrfifo*() methods described in cdrfifo.h . -*/ -struct CdrfifO; - - -/** Create a fifo object. - @param ff Returns the address of the new object. - @param source_fd Filedescriptor opened to a readable data stream. - @param dest_fd Filedescriptor opened to a writable data stream. - To work with libburn, it needs to be attached to a - struct burn_source object. - @param chunk_size Size of buffer block for a single transaction (0=default) - @param buffer_size Size of fifo buffer - @param flag unused yet - @return 1 on success, <=0 on failure -*/ -int Cdrfifo_new(struct CdrfifO **ff, int source_fd, int dest_fd, - int chunk_size, int buffer_size, int flag); - -/** Release from memory a fifo object previously created by Cdrfifo_new(). - @param ff The victim (gets returned as NULL, call can stand *ff==NULL) - @param flag Bitfield for control purposes: - bit0= do not close destination fd -*/ -int Cdrfifo_destroy(struct CdrfifO **ff, int flag); - -/** Close any output fds */ -int Cdrfifo_close(struct CdrfifO *o, int flag); - -/** Close any output fds of o and its chain peers */ -int Cdrfifo_close_all(struct CdrfifO *o, int flag); - -int Cdrfifo_get_sizes(struct CdrfifO *o, int *chunk_size, int *buffer_size, - int flag); - -/** Set a speed limit for buffer output. - @param o The fifo object - @param bytes_per_second >0 catch up slowdowns over the whole run time - <0 catch up slowdowns only over one interval - =0 disable speed limit -*/ -int Cdrfifo_set_speed_limit(struct CdrfifO *o, double bytes_per_second, - int flag); - -/** Set a fixed size for input in order to cut off any unwanted tail - @param o The fifo object - @param idx index for fds attached via Cdrfifo_attach_follow_up_fds(), - first attached is 0, <0 directs limit to active fd limit - (i.e. first track is -1, second track is 0, third is 1, ...) -*/ -int Cdrfifo_set_fd_in_limit(struct CdrfifO *o, double fd_in_limit, int idx, - int flag); - - -int Cdrfifo_set_fds(struct CdrfifO *o, int source_fd, int dest_fd, int flag); -int Cdrfifo_get_fds(struct CdrfifO *o, int *source_fd, int *dest_fd, int flag); - - -/** Attach a further pair of input and output fd which will use the same - fifo buffer when its predecessors are exhausted. Reading will start as - soon as reading of the predecessor encounters EOF. Writing will start - as soon as all pending predecessor data are written. - @return index number of new item + 1, <=0 indicates error -*/ -int Cdrfifo_attach_follow_up_fds(struct CdrfifO *o, int source_fd, int dest_fd, - int flag); - -/** Attach a further fifo which shall be processed simultaneously with this - one by Cdrfifo_try_to_work() in fd-to-fd mode. -*/ -int Cdrfifo_attach_peer(struct CdrfifO *o, struct CdrfifO *next, int flag); - - -/** Obtain buffer state. - @param o The buffer object - @param fill Returns the number of pending payload bytes in the buffer - @param space Returns the number of unused buffer bytes - @param flag unused yet - @return -1=error , 0=inactive , 1=reading and writing , - 2=reading ended (but still writing) -*/ -int Cdrfifo_get_buffer_state(struct CdrfifO *o,int *fill,int *space,int flag); - -int Cdrfifo_get_counters(struct CdrfifO *o, - double *in_counter, double *out_counter, int flag); - -/** reads min_fill and begins measurement interval for next min_fill */ -int Cdrfifo_next_interval(struct CdrfifO *o, int *min_fill, int flag); - -int Cdrfifo_get_min_fill(struct CdrfifO *o, int *total_min_fill, - int *interval_min_fill, int flag); - -int Cdrfifo_get_cdr_counters(struct CdrfifO *o, - double *put_counter, double *get_counter, - double *empty_counter, double *full_counter, - int flag); - -/** Inquire the eventually detected size of an eventual ISO-9660 file system - @return 0=no ISO resp. size detected, 1=size_in_bytes is valid -*/ -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 - chunk of data is transfered to and/or from the fifo. - This is done for the given fifo object and all members of its next-chain. - The check and transactions are repeated until a given timespan has elapsed. - libburn applications call this function in the burn loop instead of sleep(). - It may also be used instead of read(). Then it returns as soon as an output - transaction would be performed. See flag:bit2. - @param o The fifo object - @param wait_usec The time in microseconds after which the function shall - return. - @param reply_buffer with bit2: Returns write-ready buffer chunk and must - be able to take at least chunk_size bytes - @param reply_count with bit2: Returns number of writeable bytes in reply_pt - @param flag Bitfield for control purposes: - bit0= Enable debug pacifier (same with Cdrfifo_debuG) - bit1= Do not write, just fill buffer - bit2= fd-to-memory mode (else fd-to-fd mode): - Rather than writing a chunk return it and its size. - No simultaneous processing of chained fifos. - bit3= With bit2: do not check destination fd for readiness - @return <0 = error , 0 = idle , 1 = did some work , 2 = all work is done -*/ -int Cdrfifo_try_to_work(struct CdrfifO *o, int wait_usec, - char *reply_buffer, int *reply_count, int flag); - -/** Fill the fifo as far as possible without writing to destination fd. - @param size if >=0 : end filling after the given number of bytes - @return 1 on success, <=0 on failure -*/ -int Cdrfifo_fill(struct CdrfifO *o, int size, int flag); - - -#endif /* Cdrfifo_headerfile_includeD */ - diff --git a/cdrskin/cdrskin.1 b/cdrskin/cdrskin.1 deleted file mode 100644 index 1d4469b..0000000 --- a/cdrskin/cdrskin.1 +++ /dev/null @@ -1,1334 +0,0 @@ -.\" Hey, EMACS: -*- nroff -*- -.\" 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 "May 10, 2008" -.\" Please adjust this date whenever revising the manpage. -.\" -.\" Some roff macros, for reference: -.\" .nh disable hyphenation -.\" .hy enable hyphenation -.\" .ad l left justify -.\" .ad b justify to both left and right margins -.\" .nf disable filling -.\" .fi enable filling -.\" .br insert line break -.\" .sp 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. -.SH SYNOPSIS -.B cdrskin -.RI [ options | track_source_addresses ] -.br -.SH DESCRIPTION -.PP -.\" TeX users may be more comfortable with the \fB\fP and -.\" \fI\fP escape sequences to invode bold face and italics, -.\" 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. -You do not need to be superuser for its daily usage. -.SS -.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) -.br -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]. -.br -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. -.br -Bus scan, burnfree, speed options, retrieving media info, padding, fifo. -.br -See section EXAMPLES at the end of this text. -.SS -.B General information paragraphs: -.br -Track recording model -.br -Write mode selection -.br -Recordable CD Media -.br -Sequentially Recordable DVD Media -.br -Overwriteable DVD or BD Media -.br -Drive preparation and addressing -.br -Emulated drives -.SS -.B Track recording model: -.br -The input-output entities which get processed are called tracks. -A \fBtrack\fP stores a stream of bytes. -.br -Each track is initiated by one track source address argument, which may either -be "-" for standard input or the address of a readable file. If no write mode -is given explicitely then one will be chosen which matches the peculiarities -of track sources and the state of the output media. -.PP -More than one track can be burned by a single run of cdrskin. -In the terms of the MMC standard all tracks written by the same run constitute -a \fBsession\fP. -.br -Some media types can be kept appendable so that further tracks can -be written to them in subsequent runs of cdrskin (see option -multi). -Info about the addresses of burned tracks is kept in a table of -content (TOC) on media and can be retrieved via cdrskin option -toc. -These informations are also used by the operating systems' CD-ROM read drivers. -.PP -In general there are two types of tracks: data and audio. They differ in -sector size, throughput and readability via the systems' CD-ROM drivers -resp. by music CD players. With DVD and BD there is only type data. -.br -If not explicitely option -audio is given, then any track is burned as type -data, unless the track source is a file with suffix ".wav" or ".au" and has a -header part which identifies it as MS-WAVE resp. SUN Audio with suitable -parameters. Such files are burned as audio tracks by default. -.PP -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. 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 -.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. -.br -So the mentioning of write modes in the following paragraphs and in the -examples is not so much a demand that the user shall choose one explicitely, -but rather an illustration of what to expect with particular media types. -.SS -.B Recordable CD Media: -.br -CD-R can be initially written only once and eventually extended until they -get closed (or are spoiled because they are overly full). After that they are -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. -.br -CD-RW media can be blanked to make them re-usable for another -round of overwriting. Usually -.B blank=fast -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 -.B Sequentially Recordable DVD Media: -.br -Currently DVD-RW, DVD-R and DVD+R[/DL] can be used for the Sequential recording -model. -.br -This applies to DVD-RW only if they are 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 -.B blank=deformat_sequential . -.br -With DVD-R[W] two write modes may be available: -.br -Mode DAO has many restrictions. It does not work with -appendable media, allows no -multi and only a single track. The size of the -track needs to be known in advance. So either its source has to be a disk file -of recognizable size or the size has to be announced explicitely by options -.B tsize= -or -.B tao_to_sao_tsize= . -.br -DAO is the only mode for media which do not offer feature 21h Incremental -Streaming. DAO may also be selected explicitely by option -.B -sao . -Program growisofs uses DAO on sequential DVD-R[W] media for maximum -DVD-ROM/-Video compatibility. -.br -The other mode, Incremental Streaming, is the default write mode if -it is available and if the restrictions of DAO would prevent the job. -Incremental Streaming may be selected explicitely by option -.B -tao -as it resembles much CD TAO by allowing track sources of -unpredicted length and to keep media appendable by option -.B -multi . -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 -each track gets wrapped in an own session. There is no -dummy writing with -DVD+R[/DL]. -.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. -.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. -.br -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 -"Restricted Overwrite". Then they behave much like DVD+RW. This formatting -can be done by option -.B blank=format_overwrite . -.br -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 -.B Drive preparation and addressing: -.br -The drives, either CD burners or DVD burners, are accessed via addresses which -are specific to libburn and the operating system. Those addresses get listed -by a run of \fBcdrskin --devices\fP. -.br -On Linux, they are device files which traditionally do not offer -w-permissions for normal users. Because libburn needs rw-permission, -it might be only the -.B superuser -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"). -.br -.PP -If you only got one CD capable drive then you may leave out cdrskin option -\fBdev=\fP. Else you should use this option to address the drive you want. -.br -cdrskin option dev= not only accepts the listed addresses but also -traditional cdrecord SCSI addresses which on Linux consist of three -numbers: Bus,Target,Lun. There is also a related address family "ATA" which -accesses IDE drives not under control of Linux SCSI drivers: -ATA:Bus,Target,Lun. -.br -See option -scanbus for getting a list of cdrecord style addresses. -.br -Further are accepted on Linux: links to libburn-suitable device files, -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/" 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 -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 -version, version timestamp, build timestamp (if available), and then exit. -.PP -Alphabetical list of options which are intended to be compatible with -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. -.TP -.BI \-audio -Announces that the subsequent tracks are to be burned as audio. -The source is supposed to be uncompressed headerless PCM, 44100 Hz, 16 bit, -stereo. For little-endian byte order (which is usual on PCs) use option --swab. Unless marked explicitely by option -data, input files with suffix -".wav" are examined wether they have a header in MS-WAVE format confirming -those parameters and eventually raw audio data get extracted and burned as -audio track. Same is done for suffix ".au" and SUN Audio. -.br -Option -audio may be used only with CD media and not with DVD or BD. -.TP -.BI blank= type -Blank a CD-RW, DVD-RW, or format a DVD-RW, DVD+RW, DVD-RAM, BD-RE. -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. -.TP -all -Blank an entire CD-RW or an unformatted DVD-RW. -(See also --prodvd_cli_compatible, --grow_overwriteable_iso) -.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. -.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.) -.TP -format_overwrite_quickest -Like format_overwrite without creating a 128 MiB trailblazer session. -Leads to "intermediate" state which only allows sequential write -beginning from address 0. -The "intermediate" state ends after the first session of writing data. -.TP -format_overwrite_full -For DVD-RW this is like format_overwrite but claims full media size -rather than just 128 MiB. -Most traditional formatting is attempted. No data get written. -Much patience is required. -.br -This option treats already formatted media even if not option -force is given. -.br -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. -.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. -.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_ -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_ -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. -.RE -.TP -.BI \-checkdrive -Retrieve some info about the addressed drive and then exit. -Exits with non-zero value if the drive cannot be found and opened. -.TP -.BI \-dao -Alias for option -sao. Write CD in Session at Once mode -or DVD-R[W] in Disc-at-once mode. -.TP -.BI \-data -Subsequent tracks are data tracks. This option is default and only needed -to mark the end of the range of an eventual option -audio. -.TP -.BI dev= target -Set the address of the drive to use. Valid are at least the -addresses listed with option --devices, -X,Y,Z addresses listed with option -scanbus, -ATA:X,Y,Z addresses listed with options dev=ATA -scanbus, -and volatile libburn drive numbers (numbering starts at "0"). -Other device file addresses which lead to the same drive might work too. -.br -If no dev= is given, volatile address "dev=0" is assumed. That is the first -drive found being available. Better avoid this ambiguity on systems with more -than one drive. -.br -The special target "help" lists hints about available addressing formats. -Be aware that deprecated option --old_pseudo_scsi_adr may change the meaning -of Bus,Target,Lun addresses. -.TP -.BI driveropts= opt -Set "driveropts=noburnfree" to disable the drive's eventual protection -mechanism against temporary lack of source data (i.e. buffer underrun). -A drive that announces no such capabilities will not get them enabled anyway, -even if attempted explicitely via "driveropts=burnfree". -.TP -.BI \-dummy -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. -.TP -.BI \-eject -Eject the disc after work is done. -.TP -.BI \-force -Assume that the user knows better in situations when cdrskin or libburn are -insecure about drive or media state. This includes the attempt to blank -media which are classified as unknown or unsuitable, and the attempt to use -write modes which libburn believes they are not supported by the drive. -.br -Another application is to enforce blanking or re-formatting of media -which appear to be in the desired blank or format state already. -.br -This option enables a burn run with option -dummy even if libburn believes -that drive and media will not simulate the write mode but will write for real. -.br -.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: -.br -"k" or "K" = 1024 , "m" or "M" = 1024k , "g" or "G" = 1024m , "s" or "S" = 2048 -.br -Set size to 0 in order to disable the fifo (default is "4m"). -.br -The fifo buffers an eventual temporary surplus of track source data in order to -provide the drive with a steady stream during times of temporary lack of track -source supply. -The larger the fifo, the longer periods of poor source supply can be -compensated. -But a large fifo needs substantial time to fill up if not curbed via -option fifo_start_at=size. -.TP -.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. -If these blocks indicate an ISO-9660 filesystem then its declared size -will be used under the assumption that it is a single session filesystem. -.br -If not, then the burn run will be aborted. -.br -The range of -isosize is exactly one track. Further tracks may be preceeded -by further -isosize options, though. At least 15 blocks of padding will be -added to each -isosize track. But be advised to rather use padsize=300k. -.br -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 -modesty_on_drive=1:min_percent=:max_percent=95 -.br -Percentage is permissible between 25 and 95. -.TP -.BI msifile= path -Run option -msinfo and copy the result line into the file given by path. -Unlike -msinfo this option does not redirect all normal output away from -standard output. But it may be combined with -msinfo to achieve this. -.br -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 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 -session has been written. -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. -.br -In order to have all filesystem content accessible, the eventual ISO-9660 -filesystem of a follow-up -session needs to be prepared in a special way by the filesystem formatter -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. -.TP -.BI \-nopad -Do not add trailing zeros to the data stream. Nevertheless, since there seems -to be no use for audio tracks with incomplete last sector, this option applies -only to data tracks. There it is default. -.TP -.BI \-pad -Add 30 kiB of trailing zeros to each data track. (This is not sufficient to -avoid problems with various CD-ROM read drivers.) -.TP -.BI padsize= size -Add the given amount of trailing zeros to the next data track. This option -gets reset to padsize=0 after that next track is written. It may be set -again before the next track argument. About size specifiers, see option fs=. -.TP -.BI \-raw96r -Write CD in RAW/RAW96R mode. This mode allows to put more payload bytes -into a CD sector but obviously at the cost of error correction. It can only -be used for tracks of fixely predicted size. Some drives allow this mode but -then behave strange or even go bad for the next few attempts to burn a CD. -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]. -.br -With CD this mode is able to put several audio tracks on media without -producing audible gaps between them. -.br -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. -.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 -option tsize= or by option tao_to_sao_tsize=. -.br --sao cannot be used on appendable media. -.TP -.BI \-scanbus -Scan the system for drives. On Linux the drives at /dev/s* and at /dev/hd* -are to be scanned by two separate runs. One without dev= for /dev/s* and -one with dev=ATA for /dev/hd* devices. (Option --drives lists all available -drives in a single run.) -.br -Drives which are busy or which offer no rw-permission to the user of cdrskin -are not listed. Busy drives get reported in form of warning messages. -.br -The useful fields in a result line are: -.br -Bus,Target,Lun Number) 'Vendor' 'Mode' 'Revision' -.TP -.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. -.TP -.BI \-swab -Announce that the raw audio data source of subsequent tracks is byte swapped -versus the expectations of cdrecord. This option is suitable for audio where -the least significant byte of a 16 bit word is first (little-endian, Intel). -Most raw audio data on PC systems are available in this byte order. -Less guesswork is needed if track sources are in format MS-WAVE in a file with -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 -.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 -to appendable media which already hold data. With unformatted DVD-R[W] it is -the only mode which allows -multi. -.TP -.BI \-toc -Print the table of content (TOC) which describes the tracks recorded on disc. -The output contains all info from option -atip plus lines which begin with -"track:", the track number, the word "lba:" and a number which gives the -start address of the track. Addresses are counted in CD sectors which with -SAO or TAO data tracks hold 2048 bytes each. -.RS -.TP -Example. Retrieve an afio archive from track number 2: -.br -tracknumber=2 -.br -lba=$(cdrskin dev=/dev/cdrom -toc 2>&1 | \\ -.br -grep '^track:[ ]*[ 0-9][0-9]' | \\ -.br -tail +"$tracknumber" | head -1 | \\ -.br -awk '{ print $4}' ) -.br -dd if=/dev/cdrom bs=2048 skip="$lba" | \\ -.br -afio -t - | less -.RE -.TP -.BI tsize= size -Announces the exact size of the next track source. This is necessary with any -write mode other than -tao if the track source is not a regular disk file, but -e.g. "-" (standard input) or a named pipe. -About size specifiers, see option fs=. -.br -If the track source does not deliver the predicted amount of bytes, the -remainder of the track is padded with zeros. This is not considered an error. -If on the other hand the track source delivers more than the announced bytes -then the track on media gets truncated to the predicted size and cdrskin exits -with non-zero value. -.TP -.BI \-v -Increment verbose level by one. Startlevel is 0 with only few messages. -Level 1 prints progress report with long running operations and also causes -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: -.TP -.BI \--adjust_speed_to_drive -Curb explicitely given speed= values to the maximum which is announced by the -drive for the loaded media. By default, such an adjustment is only made with -pseudo-speeds 0 and -1 whereas speed settings > 0 are sent unchanged to the -drive which will then choose an appropriate speed on its own. -.TP -.BI \--allow_emulated_drives -Enable drive addresses of the form dev=stdio:. 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. -One should not do this chmod u+s , but it is an old cdrecord tradition. -.TP -.BI \--any_track -Allow source_addresses to begin with "-" (plus further characters) or to -contain a "=" character. -By default such arguments are seen as misspelled options. It is nevertheless -not possible to use one of the options listed with --list_ignored_options. -.TP -.BI assert_write_lba= block_number | byte_address -Abort if the write address given with this option is not the same as predicted -immediately before the write session starts. This option can ensure that a -start address which was presumed by a formatter like mkisofs -C is really used -by the drive for writing. -assert_write_lba=0 effectively demands blank media and excludes appendables. -.br -Block numbering is peculiar: If the last character of the option string is -a letter [a-zA-Z] then the usual unit scaling by "s", "k", "m", etc. applies -and the result is divided by 2048. Else the number value of the string is -taken as plain block number with block size 2048 byte. -(E.g ...=1000 or ...=1000s means block 1000, ...=1m means block -512, ...=4096b means block number 2) -.TP -.BI \--demand_a_drive -Exit with a nonzero value if no drive can be found during a bus scan. -.TP -.BI \--devices -List the device file addresses of all accessible CD drives. In order to get -listed, a drive has to offer rw-permission for the cdrskin user and it may -not be busy. The superuser should be able to see all idle drives listed and -busy drives reported as "SORRY" messages. -.br -Each available drive gets listed by a line containing the following fields: -.br -Number dev='Devicefile' rw-Permissions : 'Vendor' 'Model' -.br -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 -near to the maximum throughput of a drive. A large fs= and a small -fifo_start_at= combine a quick burn start and a large savings buffer to -compensate for temporary lack of source data. At the beginning of burning, -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 -option which ends by "=". The list is ended by an empty line. -.TP -.BI \--no_rc -Only if used as first command line argument this option prevents reading and -interpretation of eventual startup files. See section FILES below. -.TP -.BI \--prodvd_cli_compatible -Activates behavior modifications with some DVD situations which bring cdrskin -nearer to the behavior of cdrecord-ProDVD: -.br -Option -multi with unsuitable media is not an error but simply has no effect. -.br -Options blank=fast and blank=all deformat overwriteable DVD-RW media. -.br -Option blank=fast does indeed minmal blanking with DVD-RW. This may yield media -which can only do DAO but not Incremental Streaming. -.TP -.BI \--single_track -Accept only the last argument of the command line as track source address. -.TP -.BI tao_to_sao_tsize= size -Set an exact fixed size for the next track to be in effect only if the track -source cannot deliver a size prediction and no tsize= was specified and an -exact track size prediction is demanded by the write mode. -.br -This was the fallback from bad old times when cdrskin was unable to burn -in mode -tao . It came back with minimally blanked DVD-RW which allow no -Incremental Streaming (-tao) resp. with explicitly selected write mode -sao -for best DVD-ROM compatibility. -.br -If the track source delivers less bytes than announced then the missing ones -will be filled with zeros. -.TP -.BI --tell_media_space -Prepare a recording session, do not perform it but rather inquire the -maximum number of 2048 byte data blocks which may be written in -the current state of media with the prepared setup. So this option disables -recording of data. It does allow blanking, though, and will measure space -afterwards. -.br -It is not mandatory to give track sources but their nature may influence -the available capacity. So for most realistic results one may set up -the full burn session and add --tell_media_space. But if one has to expect -a cdrskin version prior to 0.3.3 no track source should be given in order -not to start an involuntary burn session. -In this case set at least -sao or -tao explicitely. -.br -The result gets printed to standard output. It is 0 or empty if no writing -is possible with the given options. -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. -With DVD-RW 32 kiB alignment is mandatory. -.br -Other media are not suitable for this option yet. -.PP -Alphabetical list of options which are only intended for very special -situations and not for normal use: -.TP -.BI \--abort_handler -Establish default signal handling not to leave a drive in busy state -but rather to shut it down and to wait until it has ended the final operations. -This option is only needed for revoking eventual --ignore_signals or ---no_abort_handler. -.TP -.BI \--allow_untested_media -Enable the use of media profiles which have been implemented but not yet -tested. Currently this applies to : -.br -Profile 0015h , DVD-R/DL Sequential (will not allow -multi). -.br -If you really test such media, then please report the outcome on -libburn-hackers@pykix.org -.TP -.BI dev_translation= -Set drive address alias. This was necessary before cdrskin-0.2.4 to manually -translate cdrecord addresses into cdrskin addresses. -.br - is a single character which may not occur in the address string -. is an address as expected to be given by the user via option -dev=. is the address to be used instead whenever is given. -More than one translation instruction can be given in one cdrskin run. -.br -E.g.: dev_translation=+ATA:1,0,0+/dev/sr1 dev_translation=+ATA:1,1,0+/dev/sr2 -.TP -.BI \--drive_abort_on_busy -Linux specific: Abort process if a busy drive is encountered. -.TP -.BI \--drive_blocking -Linux specific: Try to wait for a busy drive to become free. -This is not guaranteed to work with all drivers. Some need nonblocking i/o. -.TP -.BI \--drive_f_setlk -Linux specific: Try to get exclusive lock on drive device file via fcntl(2). -.TP -.BI \--drive_not_exclusive -Linux specific: Combine --drive_not_f_setlk and --drive_not_o_excl. -.TP -.BI \--drive_not_f_setlk -Linux specific: Do not try to get exclusive lock on drive device file via -fcntl(2). -.TP -.BI \--drive_not_o_excl -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 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. -.br -Device file family /dev/hdX on kernel >= 2.6 is not affected by this setting. -.TP -.BI \--drive_scsi_exclusive -Linux specific: -Try to exclusively reserve device files /dev/srN, /dev/scdM, /dev/sgK of drives. -This would be helpful to protect against collisions with program growisofs. -Regrettably on Linux kernel 2.4 with ide-scsi emulation this seems not to -work. Wether it becomes helpful with new Linux systems has to be evaluated. -.TP -.BI \--fifo_disable -Disable fifo despite any fs=. -.TP -.BI \--fifo_per_track -Use a separate fifo for each track. -.TP -.BI \--fill_up_media -Expand the last track of the session to occupy all remaining free space on -the media. -.br -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. -.TP -.BI grab_drive_and_wait= seconds -Open the addressed drive, wait the given number of seconds, release the drive, -and do normal work as indicated by the other options used. This option helps -to explore the program behavior when faced with busy drives. Just start a -second cdrskin with option --devices while grab_drive_and_wait= is still -active. -.TP -.BI \--ignore_signals -Try to ignore any signals rather than to abort the program. This is not a -very good idea. You might end up waiting a very long time for cdrskin -to finish. -.TP -.BI modesty_on_drive= [:min_percent=][:max_percent=] -Mode 1 keeps the program from trying to write to the burner drive while its -buffer is in danger to be filled by more than max_percent. If this filling is -exceeded then the program will wait until the filling is at most min_percent. -.br -This can ease the load on operating system and drive controller and thus help -with achieving better input bandwidth if disk and burner are not on independent -controllers (like hda and hdb). Unsufficient input bandwidth is indicated by -output "(fifo xy%)" of option -v if xy is lower than 90 for some time. -modesty_on_drive= might hamper output bandwidth and cause buffer underruns. -.br -To have max_percent larger than the burner's best actual -buffer fill has the same effect as min_percent==max_percent. Some burners -do not use their full buffer with all media types. Watch output "[buf xy%]" -of option -v to get an impression of the actual buffer usage. Some burners -are not suitable because they report buffer fill with granularity too large -in size or time. -.br -Mode 0 disables this feature. Mode -1 keeps it unchanged. Default is: -.br -modesty_on_drive=0:min_percent=65:max_percent=95 -.br -Percentages are permissible in the range of 25 to 100. -.TP -.BI \--no_abort_handler -On signals exit even if the drive is in busy state. This is not a very good -idea. You might end up with a stuck drive that refuses to hand out the media. -.TP -.BI \--no_blank_appendable -Refuse to blank appendable CD-RW or DVD-RW. This is a feature that was once -builtin with libburn. No information available for what use case it was needed. -.TP -.BI \--no_convert_fs_adr -Do only literal translations of dev=. This prevents cdrskin from test-opening -device files in order to find one that matches the given dev= specifier. -.br -Partly Linux specific: -Such opening is needed for Bus,Target,Lun addresses unless option ---old_pseudo_scsi_adr is given. It is also needed to resolve device file -addresses which are not listed with cdrskin --devices but nevertheless point -to a usable drive. (Like /dev/sg0 using the same SCSI address as /dev/sr0.) -.TP -.BI \--old_pseudo_scsi_adr -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 -.B Get an overview of drives and their addresses: -.br -cdrskin -scanbus -.br -cdrskin dev=ATA -scanbus -.br -cdrskin --devices -.SS -.B Get info about a particular drive or loaded media: -.br -cdrskin dev=0,1,0 -checkdrive -.br -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: -.br -cdrskin -v dev=/dev/sg1 blank=as_needed -eject -.SS -.B Format DVD-RW to avoid need for blanking before re-use: -.br -cdrskin -v dev=/dev/sr0 blank=format_overwrite -.SS -.B De-format DVD-RW to make it capable of multi-session again: -.br -cdrskin -v dev=/dev/sr0 blank=deformat_sequential -.SS -.B Write ISO-9660 filesystem image as only one to blank or formatted media: -.br -cdrskin -v dev=/dev/hdc speed=12 fs=8m \\ -.br -blank=as_needed -eject padsize=300k my_image.iso -.SS -.B Write compressed afio archive on-the-fly (not possible with minimally blanked DVD-RW): -.br -find . | afio -oZ - | \\ -.br -cdrskin -v dev=0,1,0 fs=32m speed=8 \\ -.br -blank=as_needed padsize=300k - -.SS -.B Write multi-session to the same CD, DVD-R[W] or DVD+R[/DL]: -.br -cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 1.iso -.br -cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 2.iso -.br -cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 3.iso -.br -cdrskin dev=/dev/hdc -v padsize=300k -tao 4.iso -.SS -.B Get multi-session info for option -C of program mkisofs: -.br -c_values=$(cdrskin dev=/dev/hdc -msinfo 2>/dev/null) -.br -mkisofs ... -C "$c_values" ... -.SS -.B Inquire free space on media for a -tao -multi run: -.br -x=$(cdrskin dev=/dev/sr0 -tao -multi \\ -.br ---tell_media_space 2>/dev/null) -.br -echo "Available: $x blocks of 2048 data bytes" -.SS -.B Write audio tracks to CD: -.br -cdrskin -v dev=ATA:1,0,0 speed=48 -sao \\ -.br -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 -.br -.B /etc/default/cdrskin -.br -.B /etc/opt/cdrskin/rc -.br -.B /etc/cdrskin/cdrskin.conf -.br -.B $HOME/.cdrskinrc -.br -.PP -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: -.br -# This is the default device -.br -dev=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: -.br -.BR cdrecord (1), -.BR wodim (1), -.BR xorriso (1) -.br -.TP -For DVD/BD burning (also tutor of libburn's DVD/BD capabilities): -.br -.BR growisofs (1) -.br -.SH AUTHOR -cdrskin was written by Thomas Schmitt . -.PP -This manual page was started by George Danchev and -is now maintained by Thomas Schmitt. - diff --git a/cdrskin/cdrskin.c b/cdrskin/cdrskin.c deleted file mode 100644 index e50d87f..0000000 --- a/cdrskin/cdrskin.c +++ /dev/null @@ -1,8292 +0,0 @@ - -/* - cdrskin.c , Copyright 2006-2008 Thomas Schmitt -Provided under GPL version 2. See future commitment below. - -A cdrecord compatible command line interface for libburn. - -This project is neither directed against original cdrecord nor does it exploit -any source code of said program. It rather tries to be an alternative method -to burn CD, DVD, or BD, which is not based on the same code as cdrecord. -See also : http://scdbackup.sourceforge.net/cdrskin_eng.html - -Interested users of cdrecord are encouraged to contribute further option -implementations as they need them. Contributions will get published under GPL -but it is essential that the authors allow a future release under LGPL and/or -BSD license. - -There is a script test/cdrecord_spy.sh which may be installed between -the cdrecord command and real cdrecord in order to learn about the options -used by your favorite cdrecord frontend. Edit said script and install it -according to the instructions given inside. - -The implementation of an option would probably consist of -- necessary structure members for structs CdrpreskiN and/or CdrskiN -- code in Cdrpreskin_setup() and Cdrskin_setup() which converts - argv[i] into CdrpreskiN/CdrskiN members (or into direct actions) -- removal of option from ignore list "ignored_partial_options" resp. - "ignored_full_options" in Cdrskin_setup() -- functions which implement the option's run time functionality -- eventually calls of those functions in Cdrskin_run() -- changes to be made within Cdrskin_burn() or Cdrskin_blank() or other - existing methods -See option blank= for an example. - ------------------------------------------------------------------------------- - -For a more comprehensive example of the advised way to write an application -of libburn see test/libburner.c . - ------------------------------------------------------------------------------- -This program is currently copyright Thomas Schmitt only. -The copyrights of several components of libburnia-project.org are willfully -tangled at toplevel to form an irrevocable commitment to true open source -spirit. -We have chosen the GPL for legal compatibility and clearly express that it -shall not hamper the use of our software by non-GPL applications which show -otherwise the due respect to the open source community. -See toplevel README and cdrskin/README for that commitment. - -For a short time, this place showed a promise to release a BSD license on -mere request. I have to retract that promise now, and replace it by the -promise to make above commitment reality in a way that any BSD conformant -usage in due open source spirit will be made possible somehow and in the -particular special case. I will not raise public protest if you fork yourself -a BSD license from an (outdated) cdrskin.c which still bears that old promise. -Note that this extended commitment is valid only for cdrskin.[ch], -cdrfifo.[ch] and cleanup.[ch], but not for libburnia-project.org as a whole. - -cdrskin is originally inspired by libburn-0.2/test/burniso.c : -(c) Derek Foreman and Ben Jansens - ------------------------------------------------------------------------------- - -Compilation within cdrskin-* : - - cd cdrskin - cc -g -I.. -DCdrskin_build_timestamP='...' \ - -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1 \ - -o cdrskin cdrskin.c cdrfifo.c cleanup.c \ - -L../libburn/.libs -lburn -lpthread - -or - - cd .. - cc -g -I. -DCdrskin_build_timestamP='...' \ - -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1 \ - -o cdrskin/cdrskin cdrskin/cdrskin.c cdrskin/cdrfifo.c cdrskin/cleanup.c \ - libburn/async.o libburn/crc.o libburn/debug.o libburn/drive.o \ - libburn/file.o libburn/init.o libburn/lec.o \ - libburn/mmc.o libburn/options.o libburn/sbc.o libburn/sector.o \ - libburn/sg.o libburn/spc.o libburn/source.o libburn/structure.o \ - libburn/toc.o libburn/util.o libburn/write.o libburn/read.o \ - libburn/libdax_audioxtr.o libburn/libdax_msgs.o \ - -lpthread - -*/ - - -/** The official program version */ -#ifndef Cdrskin_prog_versioN -#define Cdrskin_prog_versioN "0.4.6" -#endif - -/** The official libburn interface revision to use. - (May get changed further below) -*/ -#ifndef Cdrskin_libburn_majoR -#define Cdrskin_libburn_majoR 0 -#endif -#ifndef Cdrskin_libburn_minoR -#define Cdrskin_libburn_minoR 4 -#endif -#ifndef Cdrskin_libburn_micrO -#define Cdrskin_libburn_micrO 6 -#endif - - -/** The source code release timestamp */ -#include "cdrskin_timestamp.h" -#ifndef Cdrskin_timestamP -#define Cdrskin_timestamP "-none-given-" -#endif - -/** The binary build timestamp is to be set externally by the compiler */ -#ifndef Cdrskin_build_timestamP -#define Cdrskin_build_timestamP "-none-given-" -#endif - - -#ifdef Cdrskin_libburn_versioN -#undef Cdrskin_libburn_versioN -#endif - -/** use this to accomodate to the CVS version as of Feb 20, 2006 -#define Cdrskin_libburn_cvs_A60220_tS 1 -*/ -#ifdef Cdrskin_libburn_cvs_A60220_tS - -#define Cdrskin_libburn_versioN "0.2.tsA60220" -#define Cdrskin_libburn_no_burn_preset_device_opeN 1 -#ifndef Cdrskin_oldfashioned_api_usE -#define Cdrskin_oldfashioned_api_usE 1 -#endif - -#endif /* Cdrskin_libburn_cvs_A60220_tS */ - - -#ifdef Cdrskin_libburn_0_4_6 -#define Cdrskin_libburn_versioN "0.4.6" -#define Cdrskin_libburn_from_pykix_svN 1 -#endif /* Cdrskin_libburn_0_4_6 */ - -#ifdef Cdrskin_libburn_0_4_7 -#define Cdrskin_libburn_versioN "0.4.7" -#define Cdrskin_libburn_from_pykix_svN 1 - -/* Place novelty switch macros here. - Move them down to Cdrskin_libburn_from_pykix_svN on version leap -*/ - -/* there are no libburn novelties in 0.4.7 yet */ - -#endif /* Cdrskin_libburn_0_4_7 */ - -#ifndef Cdrskin_libburn_versioN -#define Cdrskin_libburn_0_4_6 -#define Cdrskin_libburn_versioN "0.4.6" -#define Cdrskin_libburn_from_pykix_svN 1 -#endif - -#ifdef Cdrskin_libburn_0_4_6 -#undef Cdrskin_libburn_majoR -#undef Cdrskin_libburn_minoR -#undef Cdrskin_libburn_micrO -#define Cdrskin_libburn_majoR 0 -#define Cdrskin_libburn_minoR 4 -#define Cdrskin_libburn_micrO 6 -#endif -#ifdef Cdrskin_libburn_0_4_7 -#undef Cdrskin_libburn_majoR -#undef Cdrskin_libburn_minoR -#undef Cdrskin_libburn_micrO -#define Cdrskin_libburn_majoR 0 -#define Cdrskin_libburn_minoR 4 -#define Cdrskin_libburn_micrO 7 -#endif - - - -#ifdef Cdrskin_libburn_from_pykix_svN -#ifndef Cdrskin_oldfashioned_api_usE - -/* 0.2.2 */ -#define Cdrskin_libburn_does_ejecT 1 -#define Cdrskin_libburn_has_drive_get_adR 1 -#define Cdrskin_progress_track_does_worK 1 -#define Cdrskin_is_erasable_on_load_does_worK 1 -#define Cdrskin_grab_abort_does_worK 1 - -/* 0.2.4 */ -#define Cdrskin_allow_libburn_taO 1 -#define Cdrskin_libburn_has_is_enumerablE 1 -#define Cdrskin_libburn_has_convert_fs_adR 1 -#define Cdrskin_libburn_has_convert_scsi_adR 1 -#define Cdrskin_libburn_has_burn_msgS 1 -#define Cdrskin_libburn_has_burn_aborT 1 -#define Cdrskin_libburn_has_cleanup_handleR 1 -#define Cdrskin_libburn_has_audioxtR 1 -#define Cdrskin_libburn_has_get_start_end_lbA 1 -#define Cdrskin_libburn_has_burn_disc_unsuitablE 1 -#define Cdrskin_libburn_has_read_atiP 1 -#define Cdrskin_libburn_has_buffer_progresS 1 - -/* 0.2.6 */ -#define Cdrskin_libburn_has_pretend_fulL 1 -#define Cdrskin_libburn_has_multI 1 -#define Cdrskin_libburn_has_buffer_min_filL 1 - -/* 0.3.0 */ -#define Cdrskin_atip_speed_is_oK 1 -#define Cdrskin_libburn_has_get_profilE 1 -#define Cdrskin_libburn_has_set_start_bytE 1 -#define Cdrskin_libburn_has_wrote_welL 1 -#define Cdrskin_libburn_has_bd_formattinG 1 -#define Cdrskin_libburn_has_burn_disc_formaT 1 - -/* 0.3.2 */ -#define Cdrskin_libburn_has_get_msc1 1 -#define Cdrskin_libburn_has_toc_entry_extensionS 1 -#define Cdrskin_libburn_has_get_multi_capS 1 - -/* 0.3.4 */ -#define Cdrskin_libburn_has_set_filluP 1 -#define Cdrskin_libburn_has_get_spacE 1 -#define Cdrskin_libburn_write_mode_ruleS 1 -#define Cdrskin_libburn_has_allow_untested_profileS 1 -#define Cdrskin_libburn_has_set_forcE 1 - -/* 0.3.6 */ -#define Cdrskin_libburn_preset_device_familY 1 -#define Cdrskin_libburn_has_track_set_sizE 1 - -/* 0.3.8 */ -#define Cdrskin_libburn_has_set_waitinG 1 -#define Cdrskin_libburn_has_get_best_speeD 1 - -/* 0.4.0 */ -#define Cdrskin_libburn_has_random_access_rW 1 -#define Cdrskin_libburn_has_get_drive_rolE 1 -#define Cdrskin_libburn_has_drive_equals_adR 1 - -/* 0.4.2 */ -/* no novel libburn features but rather organizational changes */ - -/* 0.4.4 */ -/* novel libburn features are transparent to cdrskin */ - -/* 0.4.6 */ -#define Cdrskin_libburn_has_stream_recordinG 1 - - -#ifdef Cdrskin_new_api_tesT - -/* put macros under test caveat here */ - -#endif /* Cdrskin_new_api_tesT */ - - -#endif /* ! Cdrskin_oldfashioned_api_usE */ -#endif /* Cdrskin_libburn_from_pykix_svN */ - - -/* These macros activate cdrskin workarounds for deficiencies resp. - problematic features of libburn which hopefully will change in - future. */ - -/** Work around the fact that neither /dev/sg0 (kernel 2.4 + ide-scsi) nor - /dev/hdc (kernel 2.6) get ejected by icculus.org/burn */ -#ifndef Cdrskin_libburn_does_ejecT -#define Cdrskin_burn_drive_eject_brokeN 1 -#endif - -/** Work around the fact that after loading media speed report is wrong */ -#ifndef Cdrskin_atip_speed_is_oK -#define Cdrskin_atip_speed_brokeN 1 -#endif - -/** Work around the fact that burn_drive_get_status() always reports to do - track 0 in icculus.org/burn */ -#ifndef Cdrskin_progress_track_does_worK -#define Cdrskin_progress_track_brokeN 1 -#endif - -/** Work around the fact that a drive interrupted at burn_drive_grab() never - leaves status BURN_DRIVE_GRABBING in icculus.org/burn */ -#ifndef Cdrskin_grab_abort_does_worK -#define Cdrskin_grab_abort_brokeN 1 -#endif - -/** Work around the fact that a freshly loaded tray with media reports - arbitrary media erasability in icculuc.org/burn */ -#ifndef Cdrskin_is_erasable_on_load_does_worK -#define Cdrskin_is_erasable_on_load_is_brokeN 1 -#endif - -/** http://libburnia-project.org/ticket/41 reports of big trouble without - padding any track to a full sector -*/ -#define Cdrskin_all_tracks_with_sector_paD 1 - - -/** A macro which is able to eat up a function call like printf() */ -#ifdef Cdrskin_extra_leaN -#define ClN(x) -#else -#define ClN(x) x -#endif - - -/** Verbosity level for pacifying progress messages */ -#define Cdrskin_verbose_progresS 1 - -/** Verbosity level for command recognition and execution logging */ -#define Cdrskin_verbose_cmD 2 - -/** Verbosity level for reporting of debugging messages */ -#define Cdrskin_verbose_debuG 3 - -/** Verbosity level for fifo debugging */ -#define Cdrskin_verbose_debug_fifO 4 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../libburn/libburn.h" - -#ifdef Cdrskin_libburn_has_audioxtR -#include "../libburn/libdax_audioxtr.h" -#endif - -#ifdef Cdrskin_libburn_has_cleanup_handleR -#define Cleanup_set_handlers burn_set_signal_handling -#define Cleanup_app_handler_T burn_abort_handler_t -#else -#include "cleanup.h" -#endif - - -/** The size of a string buffer for pathnames and similar texts */ -#define Cdrskin_strleN 4096 - -/** The maximum length +1 of a drive address */ -#ifndef Cdrskin_oldfashioned_api_usE -#define Cdrskin_adrleN BURN_DRIVE_ADR_LEN -#else -#define Cdrskin_adrleN 80 -#endif - - -/** If tsize= sets a value smaller than media capacity divided by this - number then there will be a warning and gracetime set at least to 15 */ -#define Cdrskin_minimum_tsize_quotienT 2048.0 - - -/* --------------------------------------------------------------------- */ - -/* Imported from scdbackup-0.8.5/src/cd_backup_planer.c */ - -/** Macro for creation of arrays of objects (or single objects) */ -#define TSOB_FELD(typ,anz) (typ *) malloc((anz)*sizeof(typ)); - - -/** Convert a text so that eventual characters special to the shell are - made literal. Note: this does not make a text terminal-safe ! - @param in_text The text to be converted - @param out_text The buffer for the result. - It should have size >= strlen(in_text)*5+2 - @param flag Unused yet - @return For convenience out_text is returned -*/ -char *Text_shellsafe(char *in_text, char *out_text, int flag) -{ - int l,i,w=0; - - /* enclose everything by hard quotes */ - l= strlen(in_text); - out_text[w++]= '\''; - for(i=0;i0) if(line[l-1]=='\r') line[--l]= 0; - if(l>0) if(line[l-1]=='\n') line[--l]= 0; - if(l>0) if(line[l-1]=='\r') line[--l]= 0; - return(ret); -} - - -/** Destroy a synthetic argument array */ -int Sfile_destroy_argv(int *argc, char ***argv, int flag) -{ - int i; - - if(*argc>0 && *argv!=NULL){ - for(i=0;i<*argc;i++){ - if((*argv)[i]!=NULL) - free((*argv)[i]); - } - free((char *) *argv); - } - *argc= 0; - *argv= NULL; - return(1); -} - - -/** Read a synthetic argument array from a list of files. - @param progname The content for argv[0] - @param filenames The paths of the filex from where to read - @param filenamecount The number of paths in filenames - @param argc Returns the number of read arguments (+1 for progname) - @param argv Returns the array of synthetic arguments - @param argidx Returns source file indice of argv[] items - @param arglno Returns source file line numbers of argv[] items - @param flag Bitfield for control purposes: - bit0= read progname as first argument from line - bit1= just release argument array argv and return - bit2= tolerate failure to open file - @return 1=ok , 0=cannot open file , -1=cannot create memory objects -*/ -int Sfile_multi_read_argv(char *progname, char **filenames, int filename_count, - int *argc, char ***argv, int **argidx, int **arglno, - int flag) -{ - int ret,i,pass,maxl=0,l,argcount=0,line_no; - char buf[Cdrskin_strleN]; - FILE *fp= NULL; - - Sfile_destroy_argv(argc,argv,0); - if(flag&2) - return(1); - if((*argidx)!=NULL) - free((char *) *argidx); - if((*arglno)!=NULL) - free((char *) *arglno); - *argidx= *arglno= NULL; - - for(pass=0;pass<2;pass++) { - if(!(flag&1)){ - argcount= 1; - if(pass==0) - maxl= strlen(progname)+1; - else { - (*argv)[0]= (char *) malloc(strlen(progname)+1); - if((*argv)[0]==NULL) - {ret= -1; goto ex;} - strcpy((*argv)[0],progname); - } - } else { - argcount= 0; - if(pass==0) - maxl= 1; - } - for(i=0; imaxl) - maxl= l; - } else { - if(argcount >= *argc) - break; - (*argv)[argcount]= (char *) malloc(l+1); - if((*argv)[argcount]==NULL) - {ret= -1; goto ex;} - strcpy((*argv)[argcount],buf); - (*argidx)[argcount]= i; - (*arglno)[argcount]= line_no; - } - argcount++; - } - fclose(fp); fp= NULL; - } - if(pass==0){ - *argc= argcount; - if(argcount>0) { - *argv= (char **) malloc(argcount*sizeof(char *)); - *argidx= (int *) malloc(argcount*sizeof(int)); - *arglno= (int *) malloc(argcount*sizeof(int)); - if(*argv==NULL || *argidx==NULL || *arglno==NULL) - {ret= -1; goto ex;} - } - for(i=0;i<*argc;i++) { - (*argv)[i]= NULL; - (*argidx)[i]= -1; - (*arglno)[i]= -1; - } - } - } - - ret= 1; -ex:; - if(fp!=NULL) - fclose(fp); - return(ret); -} - - -/** Combine environment variable HOME with given filename - @param filename Address relative to $HOME - @param fileadr Resulting combined address - @param fa_size Size of array fileadr - @param flag Unused yet - @return 1=ok , 0=no HOME variable , -1=result address too long -*/ -int Sfile_home_adr_s(char *filename, char *fileadr, int fa_size, int flag) -{ - char *home; - - strcpy(fileadr,filename); - home= getenv("HOME"); - if(home==NULL) - return(0); - if(strlen(home)+strlen(filename)+1>=fa_size) - return(-1); - strcpy(fileadr,home); - if(filename[0]!=0){ - strcat(fileadr,"/"); - strcat(fileadr,filename); - } - return(1); -} - - -#endif /* ! Cdrskin_extra_leaN */ - - -/* -------------------------- other misc functions ----------------------- */ - - -/* Learned from reading growisofs.c , - watching mkisofs, and viewing its results via od -c */ -/* @return 0=no size found , 1=*size_in_bytes is valid */ -int Scan_for_iso_size(unsigned char data[2048], double *size_in_bytes, - int flag) -{ - double sectors= 0.0; - - if(data[0]!=1) - return(0); - if(strncmp((char *) (data+1),"CD001",5)!=0) - return(0); - sectors= data[80] | (data[81]<<8) | (data[82]<<16) | (data[83]<<24); - *size_in_bytes= sectors*2048.0; - return(1); -} - - -int Set_descr_iso_size(unsigned char data[2048], double size_in_bytes, - int flag) -{ - unsigned int sectors, i; - - sectors= size_in_bytes/2048.0; - if(size_in_bytes>((double) sectors) * 2048.0) - sectors++; - for(i=0;i<4;i++) - data[87-i]= data[80+i]= (sectors >> (8*i)) & 0xff; - return(1); -} - - -int Wait_for_input(int fd, int microsec, int flag) -{ - struct timeval wt; - fd_set rds,wts,exs; - int ready; - - FD_ZERO(&rds); - FD_ZERO(&wts); - FD_ZERO(&exs); - FD_SET(fd,&rds); - FD_SET(fd,&exs); - wt.tv_sec= microsec/1000000; - wt.tv_usec= microsec%1000000; - ready= select(fd+1,&rds,&wts,&exs,&wt); - if(ready<=0) - return(0); - if(FD_ISSET(fd,&exs)) - return(-1); - if(FD_ISSET(fd,&rds)) - return(1); - return(0); -} - - -/* --------------------------------------------------------------------- */ - -/** Address translation table for users/applications which do not look - for the output of -scanbus but guess a Bus,Target,Lun on their own. -*/ - -/** The maximum number of entries in the address translation table */ -#define Cdradrtrn_leN 256 - -/** The address prefix which will prevent translation */ -#define Cdrskin_no_transl_prefiX "LITERAL_ADR:" - - -struct CdradrtrN { - char *from_address[Cdradrtrn_leN]; - char *to_address[Cdradrtrn_leN]; - int fill_counter; -}; - - -#ifndef Cdrskin_extra_leaN - -/** Create a device address translator object */ -int Cdradrtrn_new(struct CdradrtrN **trn, int flag) -{ - struct CdradrtrN *o; - int i; - - (*trn)= o= TSOB_FELD(struct CdradrtrN,1); - if(o==NULL) - return(-1); - for(i= 0;ifrom_address[i]= NULL; - o->to_address[i]= NULL; - } - o->fill_counter= 0; - return(1); -} - - -/** Release from memory a device address translator object */ -int Cdradrtrn_destroy(struct CdradrtrN **o, int flag) -{ - int i; - struct CdradrtrN *trn; - - trn= *o; - if(trn==NULL) - return(0); - for(i= 0;ifill_counter;i++) { - if(trn->from_address[i]!=NULL) - free(trn->from_address[i]); - if(trn->to_address[i]!=NULL) - free(trn->to_address[i]); - } - free((char *) trn); - *o= NULL; - return(1); -} - - -/** Add a translation pair to the table - @param trn The translator which shall learn - @param from The user side address - @param to The cdrskin side address - @param flag Bitfield for control purposes: - bit0= "from" contains from+to address, to[0] contains delimiter -*/ -int Cdradrtrn_add(struct CdradrtrN *trn, char *from, char *to, int flag) -{ - char buf[2*Cdrskin_adrleN+1],*from_pt,*to_pt; - int cnt; - - cnt= trn->fill_counter; - if(cnt>=Cdradrtrn_leN) - return(-1); - if(flag&1) { - if(strlen(from)>=sizeof(buf)) - return(0); - strcpy(buf,from); - to_pt= strchr(buf,to[0]); - if(to_pt==NULL) - return(0); - *(to_pt)= 0; - from_pt= buf; - to_pt++; - } else { - from_pt= from; - to_pt= to; - } - if(strlen(from)>=Cdrskin_adrleN || strlen(to)>=Cdrskin_adrleN) - return(0); - trn->from_address[cnt]= malloc(strlen(from_pt)+1); - trn->to_address[cnt]= malloc(strlen(to_pt)+1); - if(trn->from_address[cnt]==NULL || - trn->to_address[cnt]==NULL) - return(-2); - strcpy(trn->from_address[cnt],from_pt); - strcpy(trn->to_address[cnt],to_pt); - trn->fill_counter++; - return(1); -} - - -/** Apply eventual device address translation - @param trn The translator - @param from The address from which to translate - @param driveno With backward translation only: The libburn drive number - @param to The result of the translation - @param flag Bitfield for control purposes: - bit0= translate backward - @return <=0 error, 1=no translation found, 2=translation found, - 3=collision avoided -*/ -int Cdradrtrn_translate(struct CdradrtrN *trn, char *from, int driveno, - char to[Cdrskin_adrleN], int flag) -{ - int i,ret= 1; - char *adr; - - to[0]= 0; - adr= from; - if(flag&1) - goto backward; - - if(strncmp(adr,Cdrskin_no_transl_prefiX, - strlen(Cdrskin_no_transl_prefiX))==0) { - adr= adr+strlen(Cdrskin_no_transl_prefiX); - ret= 2; - } else { - for(i=0;ifill_counter;i++) - if(strcmp(adr,trn->from_address[i])==0) - break; - if(ifill_counter) { - adr= trn->to_address[i]; - ret= 2; - } - } - if(strlen(adr)>=Cdrskin_adrleN) - return(-1); - strcpy(to,adr); - return(ret); - -backward:; - if(strlen(from)>=Cdrskin_adrleN) - sprintf(to,"%s%d",Cdrskin_no_transl_prefiX,driveno); - else - strcpy(to,from); - for(i=0;ifill_counter;i++) - if(strcmp(from,trn->to_address[i])==0 && - strlen(trn->from_address[i])fill_counter) { - ret= 2; - strcpy(to,trn->from_address[i]); - } else { - for(i=0;ifill_counter;i++) - if(strcmp(from,trn->from_address[i])==0) - break; - if(ifill_counter) - if(strlen(from)+strlen(Cdrskin_no_transl_prefiX)boss= boss; - o->trackno= trackno; - o->source_path[0]= 0; - o->original_source_path[0]= 0; - o->source_fd= -1; - o->is_from_stdin= !!(flag&2); - o->fixed_size= 0.0; - o->tao_to_sao_tsize= 0.0; - o->padding= 0.0; - o->set_by_padsize= 0; - o->sector_pad_up= Cdrskin_all_tracks_with_sector_paD; - o->track_type= BURN_MODE1; - o->sector_size= 2048.0; - o->track_type_by_default= 1; - o->swap_audio_bytes= 0; - o->data_image_size= -1.0; - o->iso_fs_descr= NULL; - o->use_data_image_size= 0; - o->extracting_container= 0; - o->fifo_enabled= 0; - o->fifo= NULL; - o->fifo_outlet_fd= -1; - o->fifo_size= 0; - o->ff_fifo= NULL; - o->ff_idx= -1; - o->libburn_track= NULL; - - ret= Cdrskin_get_source(boss,o->source_path,&(o->fixed_size), - &(o->tao_to_sao_tsize),&(o->use_data_image_size), - &(o->padding),&(o->set_by_padsize),&(skin_track_type), - &(o->track_type_by_default),&(o->swap_audio_bytes), - 0); - if(ret<=0) - goto failed; - strcpy(o->original_source_path,o->source_path); - if(o->fixed_size>0.0) - o->extracting_container= 1; - Cdrtrack_set_track_type(o,skin_track_type,0); - -#ifndef Cdrskin_extra_leaN - ret= Cdrskin_get_fifo_par(boss, &(o->fifo_enabled),&(o->fifo_size), - &fifo_start_at,0); - if(ret<=0) - goto failed; -#endif /* ! Cdrskin_extra_leaN */ - - return(1); -failed:; - Cdrtrack_destroy(track,0); - return(-1); -} - - -/** Release from memory a track object previously created by Cdrtrack_new() */ -int Cdrtrack_destroy(struct CdrtracK **o, int flag) -{ - struct CdrtracK *track; - - track= *o; - if(track==NULL) - return(0); - -#ifndef Cdrskin_extra_leaN - Cdrfifo_destroy(&(track->fifo),0); -#endif - - if(track->libburn_track!=NULL) - burn_track_free(track->libburn_track); - if(track->iso_fs_descr!=NULL) - free((char *) track->iso_fs_descr); - free((char *) track); - *o= NULL; - return(1); -} - - -int Cdrtrack_set_track_type(struct CdrtracK *o, int track_type, int flag) -{ - if(track_type==BURN_AUDIO) { - o->track_type= BURN_AUDIO; - o->sector_size= 2352.0; - } else { - o->track_type= BURN_MODE1; - o->sector_size= 2048.0; - } - return(1); -} - - -int Cdrtrack_get_track_type(struct CdrtracK *o, int *track_type, - int *sector_size, int flag) -{ - *track_type= o->track_type; - *sector_size= o->sector_size; - return(1); -} - - -/** - @param flag Bitfield for control purposes: - bit0= size returns number of actually processed source bytes - rather than the predicted fixed_size (if available). - padding returns the difference from number of written - bytes. - bit1= size returns fixed_size, padding returns tao_to_sao_tsize -*/ -int Cdrtrack_get_size(struct CdrtracK *track, double *size, double *padding, - double *sector_size, int *use_data_image_size, int flag) -{ - - *size= track->fixed_size; - *padding= track->padding; - *use_data_image_size= track->use_data_image_size; -#ifdef Cdrskin_allow_libburn_taO - if((flag&1) && track->libburn_track!=NULL) { - off_t readcounter= 0,writecounter= 0; - - burn_track_get_counters(track->libburn_track,&readcounter,&writecounter); - *size= readcounter; - *padding= writecounter-readcounter; - } else if(flag&2) - *padding= track->tao_to_sao_tsize; - -#endif - *sector_size= track->sector_size; - return(1); -} - - -int Cdrtrack_get_iso_fs_descr(struct CdrtracK *track, - char **descr, double *size, int flag) -{ - *descr= track->iso_fs_descr; - *size= track->data_image_size; - return(*descr != NULL && *size > 0.0); -} - - -int Cdrtrack_get_source_path(struct CdrtracK *track, - char **source_path, int *source_fd, int *is_from_stdin, int flag) -{ - *source_path= track->original_source_path; - *source_fd= track->source_fd; - *is_from_stdin= track->is_from_stdin; - return(1); -} - - -int Cdrtrack_get_fifo(struct CdrtracK *track, struct CdrfifO **fifo, int flag) -{ - *fifo= track->fifo; - return(1); -} - - -/** Try whether automatic audio extraction is appropriate and eventually open - a file descriptor to the raw data. - @return -3 identified as .wav but with cdrecord-inappropriate parameters - -2 could not open track source, no use in retrying - -1 severe error - 0 not appropriate to extract, burn plain file content - 1 to be extracted, *fd is a filedescriptor delivering raw data -*/ -int Cdrtrack_extract_audio(struct CdrtracK *track, int *fd, off_t *xtr_size, - int flag) -{ - int l, ok= 0; -#ifdef Cdrskin_libburn_has_audioxtR - struct libdax_audioxtr *xtr= NULL; - char *fmt,*fmt_info; - int num_channels,sample_rate,bits_per_sample,msb_first,ret; -#endif - - *fd= -1; - - if(track->track_type!=BURN_AUDIO && !track->track_type_by_default) - return(0); - l= strlen(track->source_path); - if(l>=4) - if(strcmp(track->source_path+l-4,".wav")==0) - ok= 1; - if(l>=3) - if(strcmp(track->source_path+l-3,".au")==0) - ok= 1; - if(!ok) - return(0); - - if(track->track_type_by_default) { - Cdrtrack_set_track_type(track,BURN_AUDIO,0); - track->track_type_by_default= 2; - fprintf(stderr,"cdrskin: NOTE : Activated -audio for '%s'\n", - track->source_path); - } - -#ifdef Cdrskin_libburn_has_audioxtR - - ret= libdax_audioxtr_new(&xtr,track->source_path,0); - if(ret<=0) - return(ret); - libdax_audioxtr_get_id(xtr,&fmt,&fmt_info, - &num_channels,&sample_rate,&bits_per_sample,&msb_first,0); - if((strcmp(fmt,".wav")!=0 && strcmp(fmt,".au")!=0) || - num_channels!=2 || sample_rate!=44100 || bits_per_sample!=16) { - fprintf(stderr,"cdrskin: ( %s )\n",fmt_info); - fprintf(stderr,"cdrskin: FATAL : Inappropriate audio coding in '%s'.\n", - track->source_path); - {ret= -3; goto ex;} - } - libdax_audioxtr_get_size(xtr,xtr_size,0); - ret= libdax_audioxtr_detach_fd(xtr,fd,0); - if(ret<=0) - {ret= -1*!!ret; goto ex;} - track->swap_audio_bytes= !!msb_first; - track->extracting_container= 1; - fprintf(stderr,"cdrskin: NOTE : %.f %saudio bytes in '%s'\n", - (double) *xtr_size, (msb_first ? "" : "(-swab) "), - track->source_path); - ret= 1; -ex: - libdax_audioxtr_destroy(&xtr,0); - return(ret); - -#else /* Cdrskin_libburn_has_audioxtR */ - - return(0); - -#endif -} - - -/* @param flag bit0=set *size_used as the detected data image size -*/ -int Cdrtrack_activate_image_size(struct CdrtracK *track, double *size_used, - int flag) -{ - if(flag&1) - track->data_image_size= *size_used; - else - *size_used= track->data_image_size; - if(track->use_data_image_size!=1) - return(2); - if(*size_used<=0) - return(0); - track->fixed_size= *size_used; - track->use_data_image_size= 2; - if(track->libburn_track!=NULL) { -#ifdef Cdrskin_libburn_has_track_set_sizE - burn_track_set_size(track->libburn_track, (off_t) *size_used); -#else - fprintf(stderr, - "cdrskin: SORRY : libburn version is too old for -isosize\n"); - return(0); -#endif - } - /* man cdrecord prescribes automatic -pad with -isosize. - cdrskin obeys only if the current padding is less than that. */ - if(track->padding<15*2048) { - track->padding= 15*2048; - track->set_by_padsize= 0; - } - track->extracting_container= 1; - -#ifndef Cdrskin_extra_leaN - if(track->ff_fifo!=NULL) - Cdrfifo_set_fd_in_limit(track->ff_fifo,track->fixed_size,track->ff_idx,0); -#endif - - return(1); -} - - -int Cdrtrack_seek_isosize(struct CdrtracK *track, int fd, int flag) -{ - struct stat stbuf; - char secbuf[2048]; - int ret,got,i; - double size; - - if(fstat(fd,&stbuf)==-1) - return(0); - if((stbuf.st_mode&S_IFMT)!=S_IFREG && (stbuf.st_mode&S_IFMT)!=S_IFBLK) - return(2); - - if(track->iso_fs_descr!=NULL) - free((char *) track->iso_fs_descr); - track->iso_fs_descr= TSOB_FELD(char,16*2048); - if(track->iso_fs_descr==NULL) - return(-1); - for(i=0;i<32 && track->data_image_size<=0;i++) { - for(got= 0; got<2048;got+= ret) { - ret= read(fd, secbuf+got, 2048-got); - if(ret<=0) - return(0); - } - if(i<16) - continue; - memcpy(track->iso_fs_descr+(i-16)*2048,secbuf,2048); - if(i>16) - continue; - ret= Scan_for_iso_size((unsigned char *) secbuf, &size, 0); - if(ret<=0) - break; - track->data_image_size= size; - if(track->use_data_image_size) { - Cdrtrack_activate_image_size(track,&size,1); - track->fixed_size= size; - track->use_data_image_size= 2; - } - } - ret= lseek(fd, (off_t) 0, SEEK_SET); - if(ret!=0) { - fprintf(stderr, - "cdrskin: FATAL : Cannot lseek() to 0 after -isosize determination\n"); - if(errno!=0) - fprintf(stderr, "cdrskin: errno=%d : %s\n", errno, strerror(errno)); - return(-1); - } - return(track->data_image_size>0); -} - - -/** Deliver an open file descriptor corresponding to the source path of track. - @param flag Bitfield for control purposes: - bit0=debugging verbosity - bit1=open as source for direct write: - no audio extract, no minimum track size - @return <=0 error, 1 success -*/ -int Cdrtrack_open_source_path(struct CdrtracK *track, int *fd, int flag) -{ - int is_wav= 0, size_from_file= 0, ret; - off_t xtr_size= 0; - struct stat stbuf; -#ifdef Cdrskin_libburn_has_convert_fs_adR - char *device_adr,*raw_adr; - int no_convert_fs_adr; - int Cdrskin_get_device_adr(struct CdrskiN *skin, - char **device_adr, char **raw_adr, int *no_convert_fs_adr,int flag); - int Cdrskin_get_drive(struct CdrskiN *skin, struct burn_drive **drive, - int flag); -#ifdef Cdrskin_libburn_has_drive_equals_adR - struct burn_drive *drive; -#else - char adr[BURN_DRIVE_ADR_LEN]; -#endif -#endif /* Cdrskin_libburn_has_convert_fs_adR */ - - if(track->source_path[0]=='-' && track->source_path[1]==0) - *fd= 0; - else if(track->source_path[0]=='#' && - (track->source_path[1]>='0' && track->source_path[1]<='9')) - *fd= atoi(track->source_path+1); - else { - *fd= -1; - -#ifdef Cdrskin_libburn_has_convert_fs_adR - - Cdrskin_get_device_adr(track->boss,&device_adr,&raw_adr, - &no_convert_fs_adr,0); -/* - fprintf(stderr, - "cdrskin: DEBUG : device_adr='%s' , raw_adr='%s' , ncfs=%d\n", - device_adr, raw_adr, no_convert_fs_adr); -*/ - if(!no_convert_fs_adr) { - if(flag&1) - ClN(fprintf(stderr, - "cdrskin_debug: checking track source for identity with drive\n")); - -#ifdef Cdrskin_libburn_has_drive_equals_adR - - ret= Cdrskin_get_drive(track->boss,&drive,0); - if(ret<=0) { - fprintf(stderr, - "cdrskin: FATAL : Program error. Cannot determine libburn drive.\n"); - return(0); - } - if(burn_drive_equals_adr(drive,track->source_path,2)>0) { - - { - -#else /* Cdrskin_libburn_has_drive_equals_adR */ - - if(burn_drive_convert_fs_adr(track->source_path,adr)>0) { - -/* - fprintf(stderr,"cdrskin: DEBUG : track source '%s' -> adr='%s'\n", - track->source_path,adr); -*/ - if(strcmp(device_adr,adr)==0) { - -#endif /* ! Cdrskin_libburn_has_drive_equals_adR */ - - fprintf(stderr, - "cdrskin: FATAL : track source address leads to burner drive\n"); - fprintf(stderr, - "cdrskin: : dev='%s' -> '%s' <- track source '%s'\n", - raw_adr, device_adr, track->source_path); - return(0); - } - } - } -/* - fprintf(stderr,"cdrskin: EXPERIMENTAL : Deliberate abort\n"); - return(0); -*/ - -#endif /* Cdrskin_libburn_has_convert_fs_adR */ - - if(!(flag&2)) - is_wav= Cdrtrack_extract_audio(track,fd,&xtr_size,0); - if(is_wav==-1) - return(-1); - if(is_wav==-3) - return(0); - if(is_wav==0) - *fd= open(track->source_path,O_RDONLY); - if(*fd==-1) { - fprintf(stderr,"cdrskin: failed to open source address '%s'\n", - track->source_path); - fprintf(stderr,"cdrskin: errno=%d , \"%s\"\n",errno, - errno==0?"-no error code available-":strerror(errno)); - return(0); - } - if(track->use_data_image_size==1 && xtr_size<=0) { - ret= Cdrtrack_seek_isosize(track,*fd,0); - if(ret==-1) - return(-1); - } else if(track->fixed_size<=0) { - - /* >>> ??? is it intentional that tsize overrides .wav header ? */ - if(xtr_size>0) { - - track->fixed_size= xtr_size; - if(track->use_data_image_size==1) - track->use_data_image_size= 2; /* count this as image size found */ - size_from_file= 1; - } else { - if(fstat(*fd,&stbuf)!=-1) { - if((stbuf.st_mode&S_IFMT)==S_IFREG) { - track->fixed_size= stbuf.st_size; - size_from_file= 1; - } /* all other types are assumed of open ended size */ - } - } - } - } - -#ifdef Cdrskin_allow_libburn_taO - - if(track->fixed_size < Cdrtrack_minimum_sizE * track->sector_size - && (track->fixed_size>0 || size_from_file) && !(flag&2)) { - -#else - - if(track->fixed_size < Cdrtrack_minimum_sizE * track->sector_size && - !(flag&2)) { - -#endif - - if(track->track_type == BURN_AUDIO) { - /* >>> cdrecord: We differ in automatic padding with audio: - Audio tracks must be at least 705600 bytes and a multiple of 2352. - */ - fprintf(stderr, - "cdrskin: FATAL : Audio tracks must be at least %.f bytes\n", - Cdrtrack_minimum_sizE*track->sector_size); - return(0); - } else { - fprintf(stderr, - "cdrskin: NOTE : Enforcing minimum track size of %.f bytes\n", - Cdrtrack_minimum_sizE*track->sector_size); - track->fixed_size= Cdrtrack_minimum_sizE*track->sector_size; - } - } - track->source_fd= *fd; - return(*fd>=0); -} - - -#ifndef Cdrskin_extra_leaN - -/** Install a fifo object between data source and libburn. - Its parameters are known to track. - @param outlet_fd Returns the filedescriptor of the fifo outlet. - @param previous_fifo Object address for chaining or follow-up attachment. - @param flag Bitfield for control purposes: - bit0= Debugging verbosity - bit1= Do not create and attach a new fifo - but attach new follow-up fd pair to previous_fifo - bit2= Do not enforce fixed_size if not container extraction - @return <=0 error, 1 success -*/ -int Cdrtrack_attach_fifo(struct CdrtracK *track, int *outlet_fd, - struct CdrfifO *previous_fifo, int flag) -{ - struct CdrfifO *ff; - int source_fd,pipe_fds[2],ret; - - *outlet_fd= -1; - if(track->fifo_size<=0) - return(2); - ret= Cdrtrack_open_source_path(track,&source_fd,flag&1); - if(ret<=0) - return(ret); - if(pipe(pipe_fds)==-1) - return(0); - - Cdrfifo_destroy(&(track->fifo),0); - if(flag&2) { - ret= Cdrfifo_attach_follow_up_fds(previous_fifo,source_fd,pipe_fds[1],0); - if(ret<=0) - return(ret); - track->ff_fifo= previous_fifo; - track->ff_idx= ret-1; - } else { - - /* >>> ??? obtain track sector size and use instead of 2048 ? */ - - ret= Cdrfifo_new(&ff,source_fd,pipe_fds[1],2048,track->fifo_size,0); - if(ret<=0) - return(ret); - if(previous_fifo!=NULL) - Cdrfifo_attach_peer(previous_fifo,ff,0); - track->fifo= track->ff_fifo= ff; - track->ff_idx= -1; - } - track->fifo_outlet_fd= pipe_fds[0]; - - if((track->extracting_container || !(flag&4)) && track->fixed_size>0) - Cdrfifo_set_fd_in_limit(track->ff_fifo,track->fixed_size,track->ff_idx,0); - - if(flag&1) - printf( - "cdrskin_debug: track %d fifo replaced source_address '%s' by '#%d'\n", - track->trackno+1,track->source_path,track->fifo_outlet_fd); - sprintf(track->source_path,"#%d",track->fifo_outlet_fd); - track->source_fd= track->fifo_outlet_fd; - *outlet_fd= track->fifo_outlet_fd; - return(1); -} - - -/** Read data into the fifo until either it is full or the data source is - exhausted. - @return <=0 error, 1 success -*/ -int Cdrtrack_fill_fifo(struct CdrtracK *track, int fifo_start_at, int flag) -{ - int ret,buffer_fill,buffer_space; - double data_image_size; - - if(track->fifo==NULL || fifo_start_at==0) - return(2); - if(fifo_start_at>0 && fifo_start_atfifo_size) - printf( - "cdrskin: NOTE : Input buffer will be initially filled up to %d bytes\n", - fifo_start_at); - printf("Waiting for reader process to fill input buffer ... "); - fflush(stdout); - ret= Cdrfifo_fill(track->fifo,fifo_start_at,0); - if(ret<=0) - return(ret); - -/** Ticket 55: check fifos for input, throw error on 0-bytes from stdin - @return <=0 abort run, 1 go on with burning -*/ - if(track->is_from_stdin) { - ret= Cdrfifo_get_buffer_state(track->fifo,&buffer_fill,&buffer_space,0); - if(ret<0 || buffer_fill<=0) { - fprintf(stderr,"\ncdrskin: FATAL : (First track) fifo did not read a single byte from stdin\n"); - return(0); - } - } - ret= Cdrfifo_get_iso_fs_size(track->fifo,&data_image_size,0); - if(ret>0) - track->data_image_size= data_image_size; - if(track->iso_fs_descr!=NULL) - free((char *) track->iso_fs_descr); - Cdrfifo_adopt_iso_fs_descr(track->fifo,&(track->iso_fs_descr),0); - return(1); -} - -#endif /* ! Cdrskin_extra_leaN */ - - -/** Create a corresponding libburn track object and add it to the libburn - session. This may change the trackno index set by Cdrtrack_new(). -*/ -int Cdrtrack_add_to_session(struct CdrtracK *track, int trackno, - struct burn_session *session, int flag) -/* - bit0= debugging verbosity - bit1= apply padding hack (<<< should be unused for now) -*/ -{ - struct burn_track *tr; - struct burn_source *src= NULL; - double padding,lib_padding; - int ret,sector_pad_up; - double fixed_size; - int source_fd; - - track->trackno= trackno; - tr= burn_track_create(); - track->libburn_track= tr; - - /* Note: track->track_type may get set in here */ - if(track->source_fd==-1) { - ret= Cdrtrack_open_source_path(track,&source_fd,(flag&1)); - if(ret<=0) - goto ex; - } - - padding= 0.0; - sector_pad_up= track->sector_pad_up; - if(track->padding>0) { - if(track->set_by_padsize || track->track_type!=BURN_AUDIO) - padding= track->padding; - else - sector_pad_up= 1; - } - if(flag&2) - lib_padding= 0.0; - else - lib_padding= padding; - if(flag&1) { - if(sector_pad_up) { - ClN(fprintf(stderr,"cdrskin_debug: track %d telling burn_track_define_data() to pad up last sector\n",trackno+1)); - } - if(lib_padding>0 || !sector_pad_up) { - ClN(fprintf(stderr, - "cdrskin_debug: track %d telling burn_track_define_data() to pad %.f bytes\n", - trackno+1,lib_padding)); - } - } - burn_track_define_data(tr,0,(int) lib_padding,sector_pad_up, - track->track_type); - burn_track_set_default_size(tr, (off_t) track->tao_to_sao_tsize); - burn_track_set_byte_swap(tr, - (track->track_type==BURN_AUDIO && track->swap_audio_bytes)); - fixed_size= track->fixed_size; - if((flag&2) && track->padding>0) { - if(flag&1) - ClN(fprintf(stderr,"cdrskin_debug: padding hack : %.f + %.f = %.f\n", - track->fixed_size,track->padding, - track->fixed_size+track->padding)); - fixed_size+= track->padding; - } - src= burn_fd_source_new(track->source_fd,-1,(off_t) fixed_size); - - if(src==NULL) { - fprintf(stderr, - "cdrskin: FATAL : Could not create libburn data source object\n"); - {ret= 0; goto ex;} - } - if(burn_track_set_source(tr,src)!=BURN_SOURCE_OK) { - fprintf(stderr,"cdrskin: FATAL : libburn rejects data source object\n"); - {ret= 0; goto ex;} - } - burn_session_add_track(session,tr,BURN_POS_END); - ret= 1; -ex: - if(src!=NULL) - burn_source_free(src); - return(ret); -} - - -/** Release libburn track information after a session is done */ -int Cdrtrack_cleanup(struct CdrtracK *track, int flag) -{ - if(track->libburn_track==NULL) - return(0); - burn_track_free(track->libburn_track); - track->libburn_track= NULL; - return(1); -} - - -int Cdrtrack_ensure_padding(struct CdrtracK *track, int flag) -/* -flag: - bit0= debugging verbosity -*/ -{ - if(track->track_type!=BURN_AUDIO) - return(2); - if(flag&1) - fprintf(stderr,"cdrskin_debug: enforcing -pad on last -audio track\n"); - track->sector_pad_up= 1; - return(1); -} - - -#ifndef Cdrskin_libburn_write_mode_ruleS - -int Cdrtrack_activate_tao_tsize(struct CdrtracK *track, int flag) -{ - if(track->fixed_size<=0.0) - track->fixed_size= track->tao_to_sao_tsize; - return(track->fixed_size>0.0); -} - -#endif /* ! Cdrskin_libburn_write_mode_ruleS */ - - -int Cdrtrack_get_sectors(struct CdrtracK *track, int flag) -{ - return(burn_track_get_sectors(track->libburn_track)); -} - - -#ifndef Cdrskin_extra_leaN - -/** Try to read bytes from the track's fifo outlet and eventually discard - them. Not to be called unless the track is completely written. -*/ -int Cdrtrack_has_input_left(struct CdrtracK *track, int flag) -{ - int ready,ret; - char buf[2]; - - if(track->fifo_outlet_fd<=0) - return(0); - ready= Wait_for_input(track->fifo_outlet_fd, 0, 0); - if(ready<=0) - return(0); - ret= read(track->fifo_outlet_fd,buf,1); - if(ret>0) - return(1); - return(0); -} - -#endif /* ! Cdrskin_extra_leaN */ - - -/* --------------------------------------------------------------------- */ - -/** The list of startup file names */ -#define Cdrpreskin_rc_nuM 4 - -static char Cdrpreskin_sys_rc_nameS[Cdrpreskin_rc_nuM][80]= { - "/etc/default/cdrskin", - "/etc/opt/cdrskin/rc", - "/etc/cdrskin/cdrskin.conf", - "placeholder for $HOME/.cdrskinrc" -}; - - -/** A structure which bundles several parameters for creation of the CdrskiN - object. It finally becomes a managed subordinate of the CdrskiN object. -*/ -struct CdrpreskiN { - - /* to be transfered into skin */ - int verbosity; - char queue_severity[81]; - char print_severity[81]; - - /** Whether to wait for available standard input data before touching drives*/ - int do_waiti; - - /** Stores eventually given absolute device address before translation */ - char raw_device_adr[Cdrskin_adrleN]; - - /** Stores an eventually given translated absolute device address between - Cdrpreskin_setup() and Cdrskin_create() . - */ - char device_adr[Cdrskin_adrleN]; - - /** The eventual address translation table */ - struct CdradrtrN *adr_trn; - - /** Memorizes the abort handling mode from presetup to creation of - control object. Defined handling modes are: - 0= no abort handling - 1= try to cancel, release, exit (leave signal mode as set by caller) - 2= try to ignore all signals - 3= mode 1 in normal operation, mode 2 during abort handling - 4= mode 1 in normal operation, mode 0 during abort handling - -1= install abort handling 1 only in Cdrskin_burn() after burning started - */ - int abort_handler; - - /** Whether to allow getuid()!=geteuid() */ - int allow_setuid; - - /** Whether to allow user provided addresses like #4 */ - int allow_fd_source; - - /** Whether to support media types which are implemented but yet untested */ - int allow_untested_media; - - /** Whether to allow libburn pseudo-drives "stdio:" . - 0=forbidden, 1=seems ok, - 2=potentially forbidden (depends on uid, euid, file type) - */ - int allow_emulated_drives; - - /** Whether an option is given which needs a full bus scan */ - int no_whitelist; - - /** Whether the translated device address shall not follow softlinks, device - clones and SCSI addresses */ - int no_convert_fs_adr; - - /** Whether Bus,Target,Lun addresses shall be converted literally as old - Pseudo SCSI-Adresses. New default is to use (possibly system emulated) - real SCSI addresses via burn_drive_convert_scsi_adr() and literally - emulated and cdrecord-incompatible ATA: addresses. */ - int old_pseudo_scsi_adr; - - /** Whether bus scans shall exit!=0 if no drive was found */ - int scan_demands_drive; - - /** Whether to abort when a busy drive is encountered during bus scan */ - int abort_on_busy_drive; - - /** Linux specific : Whether to try to avoid collisions when opening drives */ - int drive_exclusive; - - /** Linux specific : Whether to obtain an exclusive drive lock via fcntl() */ - int drive_fcntl_f_setlk; - - /** Linux specific : Device file address family to use : - 0=default , 1=sr , 2=scd , 4=sg */ - int drive_scsi_dev_family; - - - /** Whether to try to wait for unwilling drives to become willing to open */ - int drive_blocking; - - /** Explicit write mode option is determined before skin processes - any track arguments */ - char write_mode_name[80]; - -#ifndef Cdrskin_extra_leaN - - /** List of startupfiles */ - char rc_filenames[Cdrpreskin_rc_nuM][Cdrskin_strleN]; - int rc_filename_count; - - /** Non-argument options from startupfiles */ - int pre_argc; - char **pre_argv; - int *pre_argidx; - int *pre_arglno; - -#endif /* ! Cdrskin_extra_leaN */ - - /* The eventual name of a program to be executed if demands_cdrecord_caps - is >0 and demands_cdrskin_caps is <=0 - */ - char fallback_program[Cdrskin_strleN]; - int demands_cdrecord_caps; - int demands_cdrskin_caps; - - int result_fd; - -}; - - -/** Create a preliminary cdrskin program run control object. It will become - part of the final control object. - @param preskin Returns pointer to resulting - @param flag Bitfield for control purposes: unused yet - @return <=0 error, 1 success -*/ -int Cdrpreskin_new(struct CdrpreskiN **preskin, int flag) -{ - struct CdrpreskiN *o; - int i; - - (*preskin)= o= TSOB_FELD(struct CdrpreskiN,1); - if(o==NULL) - return(-1); - - o->verbosity= 0; - strcpy(o->queue_severity,"NEVER"); - strcpy(o->print_severity,"SORRY"); - o->do_waiti= 0; - o->raw_device_adr[0]= 0; - o->device_adr[0]= 0; - o->adr_trn= NULL; - o->abort_handler= 3; - o->allow_setuid= 0; - o->allow_fd_source= 0; - o->allow_untested_media= 0; - o->allow_emulated_drives= 0; - o->no_whitelist= 0; - o->no_convert_fs_adr= 0; -#ifdef Cdrskin_libburn_has_convert_scsi_adR - o->old_pseudo_scsi_adr= 0; -#else - o->old_pseudo_scsi_adr= 1; -#endif - o->scan_demands_drive= 0; - o->abort_on_busy_drive= 0; - o->drive_exclusive= 1; - o->drive_fcntl_f_setlk= 1; - o->drive_scsi_dev_family= 0; - o->drive_blocking= 0; - strcpy(o->write_mode_name,"DEFAULT"); - -#ifndef Cdrskin_extra_leaN - o->rc_filename_count= Cdrpreskin_rc_nuM; - for(i=0;irc_filename_count-1;i++) - strcpy(o->rc_filenames[i],Cdrpreskin_sys_rc_nameS[i]); - o->rc_filenames[o->rc_filename_count-1][0]= 0; - o->pre_argc= 0; - o->pre_argv= NULL; - o->pre_argidx= NULL; - o->pre_arglno= NULL; -#endif /* ! Cdrskin_extra_leaN */ - - o->fallback_program[0]= 0; - o->demands_cdrecord_caps= 0; - o->demands_cdrskin_caps= 0; - o->result_fd = -1; - return(1); -} - - -int Cdrpreskin_destroy(struct CdrpreskiN **preskin, int flag) -{ - struct CdrpreskiN *o; - - o= *preskin; - if(o==NULL) - return(0); - -#ifndef Cdrskin_extra_leaN - if((o->pre_arglno)!=NULL) - free((char *) o->pre_arglno); - if((o->pre_argidx)!=NULL) - free((char *) o->pre_argidx); - if(o->pre_argc>0 && o->pre_argv!=NULL) - Sfile_destroy_argv(&(o->pre_argc),&(o->pre_argv),0); - Cdradrtrn_destroy(&(o->adr_trn),0); -#endif /* ! Cdrskin_extra_leaN */ - - free((char *) o); - *preskin= NULL; - return(1); -} - - -int Cdrpreskin_set_severities(struct CdrpreskiN *preskin, char *queue_severity, - char *print_severity, int flag) -{ - if(queue_severity!=NULL) - strcpy(preskin->queue_severity,queue_severity); - if(print_severity!=NULL) - strcpy(preskin->print_severity,print_severity); -#ifdef Cdrskin_libburn_has_burn_msgS - burn_msgs_set_severities(preskin->queue_severity, preskin->print_severity, - "cdrskin: "); -#endif - return(1); -} - - -int Cdrpreskin_initialize_lib(struct CdrpreskiN *preskin, int flag) -{ - int ret, major, minor, micro; - -/* This is the minimum requirement of cdrskin towards the libburn header - at compile time. - It gets compared against the version macros in libburn/libburn.h : - burn_header_version_major - burn_header_version_minor - burn_header_version_micro - If the header is too old then the following code shall cause failure of - cdrskin compilation rather than to allow production of a program with - unpredictable bugs or memory corruption. - The compiler message supposed to appear in this case is: - error: 'LIBBURN_MISCONFIGURATION' undeclared (first use in this function) - error: 'INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libburn_dot_h_TOO_OLD__SEE_cdrskin_dot_c' undeclared (first use in this function) - error: 'LIBBURN_MISCONFIGURATION_' undeclared (first use in this function) -*/ - -/* The indendation is an advise of man gcc to help old compilers ignoring */ - #if Cdrskin_libburn_majoR > burn_header_version_major - #define Cdrskin_libburn_dot_h_too_olD 1 - #endif - #if Cdrskin_libburn_majoR == burn_header_version_major && Cdrskin_libburn_minoR > burn_header_version_minor - #define Cdrskin_libburn_dot_h_too_olD 1 - #endif - #if Cdrskin_libburn_minoR == burn_header_version_minor && Cdrskin_libburn_micrO > burn_header_version_micro - #define Cdrskin_libburn_dot_h_too_olD 1 - #endif - -#ifdef Cdrskin_libburn_dot_h_too_olD -LIBBURN_MISCONFIGURATION = 0; -INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libburn_dot_h_TOO_OLD__SEE_cdrskin_dot_c = 0; -LIBBURN_MISCONFIGURATION_ = 0; -#endif - - ret= burn_initialize(); - if(ret==0) { - fprintf(stderr,"cdrskin: FATAL : Initialization of libburn failed\n"); - return(0); - } - - /* This is the runtime check towards eventual dynamically linked libburn. - cdrskin deliberately does not to allow the library to be older than - the header file which was seen at compile time. More liberal would be - to use here Cdrskin_libburn_* instead of burn_header_version_* . - */ - burn_version(&major, &minor, µ); - if(majorqueue_severity); - strcpy(print_severity,o->print_severity); - } - if(o->verbosity>=Cdrskin_verbose_debuG) - Cdrpreskin_set_severities(o,"DEBUG","NEVER",0); - else - Cdrpreskin_set_severities(o,"SORRY","NEVER",0); - queueing= 1; - return(1); - } - - if(queueing) - Cdrpreskin_set_severities(o,queue_severity,print_severity,0); - queueing= 0; - - for(first= 1; ; first= 0) { - ret= burn_msgs_obtain("ALL",&error_code,msg,&os_errno,msg_severity); - if(ret==0) - break; - if(ret<0) { - fprintf(stderr, - "cdrskin: NOTE : Please inform libburn-hackers@pykix.org about:\n"); - fprintf(stderr, - "cdrskin: burn_msgs_obtain() returns %d\n",ret); - break; - } - if(first) - fprintf(stderr, -"cdrskin: -------------------- Messages from Libburn ---------------------\n"); - for(i=0;msg_severity[i]!=0;i++) - filler[i]= ' '; - filler[i]= 0; - fprintf(stderr,"cdrskin: %s : %s\n",msg_severity,msg); - if(strcmp(msg_severity,"DEBUG")!=0 && os_errno!=0) - fprintf(stderr,"cdrskin: %s ( errno=%d '%s')\n", - filler,os_errno,strerror(os_errno)); - } - if(first==0) - fprintf(stderr, -"cdrskin: ----------------------------------------------------------------\n"); - -#endif /* Cdrskin_debug_libdax_msgS */ -#endif /* Cdrskin_libburn_has_burn_msgS */ - - return(1); -} - - -/** Evaluate whether the user would be allowed in any case to use device_adr - as pseudo-drive */ -int Cdrpreskin__allows_emulated_drives(char *device_adr, char reason[4096], - int flag) -{ - struct stat stbuf; - - reason[0]= 0; - if(device_adr[0]) { - if(strcmp(device_adr,"/dev/null")==0) - return(1); - strcat(reason,"File object is not /dev/null. "); - } - - if(getuid()!=geteuid()) { - strcat(reason,"UID and EUID differ"); - return(0); - } - if(getuid()!=0) - return(1); - - strcat(reason,"UID is 0. "); - /* Directory must be owned by root and write protected against any others*/ - if(lstat("/root/cdrskin_permissions",&stbuf)==-1 || !S_ISDIR(stbuf.st_mode)) { - strcat(reason, "No directory /root/cdrskin_permissions exists"); - return(0); - } - if(stbuf.st_uid!=0) { - strcat(reason, "Directory /root/cdrskin_permissions not owned by UID 0"); - return(0); - } - if(stbuf.st_mode & (S_IWGRP | S_IWOTH)) { - strcat(reason, - "Directory /root/cdrskin_permissions has w-permission for group or others"); - return(0); - } - if(stat("/root/cdrskin_permissions/allow_emulated_drives",&stbuf)==-1) { - strcat(reason, - "No file /root/cdrskin_permissions/allow_emulated_drives exists"); - return(0); - } - reason[0]= 0; - return(1); -} - - -int Cdrpreskin_consider_normal_user(int flag) -{ - fprintf(stderr, - "cdrskin: HINT : Consider to allow rw-access to the writer devices and\n"); - fprintf(stderr, - "cdrskin: HINT : to run cdrskin under your normal user identity.\n"); - return(1); -} - - -/* Start the fallback program as replacement of the cdrskin run. - @param flag bit0=do not report start command -*/ -int Cdrpreskin_fallback(struct CdrpreskiN *preskin, int argc, char **argv, - int flag) -{ - char **hargv= NULL; - int i, wp= 1; - char *ept, *upt; - - if(getuid()!=geteuid() && !preskin->allow_setuid) { - fprintf(stderr, - "cdrskin: SORRY : uid and euid differ. Will not start external fallback program.\n"); - Cdrpreskin_consider_normal_user(0); - fprintf(stderr, - "cdrskin: HINT : Option --allow_setuid disables this safety check.\n"); - goto failure; - } - if(!(flag&1)) { - fprintf(stderr,"cdrskin: --------------------------------------------------------------------\n"); - fprintf(stderr,"cdrskin: Starting fallback program:\n"); - } - hargv= TSOB_FELD(char *,argc+1); - if(hargv==NULL) - goto failure; - hargv[0]= strdup(preskin->fallback_program); - if(argv[0]==NULL) - goto failure; - if(!(flag&1)) - fprintf(stderr," %s", hargv[0]); - for(i= 1; i 0 ? strerror(errno) : "unidentified error")); - exit(15); -} - - -/** Convert a cdrecord-style device address into a libburn device address or - into a libburn drive number. It depends on the "scsibus" number of the - cdrecord-style address which kind of libburn address emerges: - bus=0 : drive number , bus=1 : /dev/sgN , bus=2 : /dev/hdX - (This call intentionally has no CdrpreskiN argument) - @param flag Bitfield for control purposes: - bit0= old_pseudo_scsi_adr - @return 1 success, 0=no recognizable format, -1=severe error, - -2 could not find scsi device, -3 address format error -*/ -int Cdrpreskin__cdrecord_to_dev(char *adr, char device_adr[Cdrskin_adrleN], - int *driveno, int flag) -{ - int comma_seen= 0,digit_seen= 0,busno= 0,k,lun_no= -1; - - *driveno= -1; - device_adr[0]= 0; - if(strlen(adr)==0) - return(0); - if(strncmp(adr,"stdio:",6)==0) - return(0); - - /* read the trailing numeric string as device address code */ - /* accepts "1" , "0,1,0" , "ATA:0,1,0" , ... */ - for(k= strlen(adr)-1;k>=0;k--) { - if(adr[k]==',' && !comma_seen) { - sscanf(adr+k+1,"%d",&lun_no); - comma_seen= 1; - digit_seen= 0; - continue; - } - if(adr[k]<'0' || adr[k]>'9') - break; - digit_seen= 1; - } - if(!digit_seen) { - k= strlen(adr)-1; - if(adr[k]==':' || (adr[k]>='A' && adr[k]<='Z')) {/* empty prefix ? */ - *driveno= 0; - return(1); - } - return(0); - } - sscanf(adr+k+1,"%d",driveno); - - digit_seen= 0; - if(k>0) if(adr[k]==',') { - for(k--;k>=0;k--) { - if(adr[k]<'0' || adr[k]>'9') - break; - digit_seen= 1; - } - if(digit_seen) { - sscanf(adr+k+1,"%d",&busno); - if(flag&1) { - /* look for symbolic bus : 1=/dev/sgN 2=/dev/hdX */ - if(busno==1) { - sprintf(device_adr,"/dev/sg%d",*driveno); - } else if(busno==2) { - sprintf(device_adr,"/dev/hd%c",'a'+(*driveno)); - } else if(busno!=0) { - fprintf(stderr, - "cdrskin: FATAL : dev=[Prefix:]Bus,Target,Lun expects Bus out of {0,1,2}\n"); - return(-3); - } - } else { - if(busno<0) { - fprintf(stderr, - "cdrskin: FATAL : dev=[Prefix:]Bus,Target,Lun expects Bus number >= 0\n"); - return(-3); - } - if(busno>=1000) { - busno-= 1000; - goto ata_bus; - } else if((strncmp(adr,"ATA",3)==0 && (adr[3]==0 || adr[3]==':')) || - (strncmp(adr,"ATAPI",5)==0 && (adr[5]==0 || adr[5]==':'))) { -ata_bus:; - if(busno>12 || (*driveno)<0 || (*driveno)>1) { - fprintf(stderr, -"cdrskin: FATAL : dev=ATA:Bus,Target,Lun expects Bus {0..12}, Target {0,1}\n"); - return(-3); - } - sprintf(device_adr,"/dev/hd%c",'a'+(2*busno)+(*driveno)); - -#ifdef Cdrskin_libburn_has_convert_scsi_adR - } else { - int ret; - - ret= burn_drive_convert_scsi_adr(busno,-1,-1,*driveno,lun_no, - device_adr); - if(ret==0) { - fprintf(stderr, - "cdrskin: FATAL : Cannot find /dev/* with Bus,Target,Lun = %d,%d,%d\n", - busno,*driveno,lun_no); - fprintf(stderr, - "cdrskin: HINT : This drive may be in use by another program currently\n"); - return(-2); - } else if(ret<0) - return(-1); - return(1); - -#endif /* Cdrskin_libburn_has_convert_scsi_adR */ - } - } - } - } - return(1); -} - - -/** Set the eventual output fd for the result of Cdrskin_msinfo() -*/ -int Cdrpreskin_set_result_fd(struct CdrpreskiN *o, int result_fd, int flag) -{ - o->result_fd= result_fd; - return(1); -} - - -#ifndef Cdrskin_extra_leaN - -/** Load content startup files into preskin cache */ -int Cdrpreskin_read_rc(struct CdrpreskiN *o, char *progname, int flag) -{ - int ret,i; - char **filenames_v; - - filenames_v= TSOB_FELD(char *, o->rc_filename_count+1); - if(filenames_v==NULL) - return(-1); - for(i=0;irc_filename_count;i++) - filenames_v[i]= o->rc_filenames[i]; - Sfile_home_adr_s(".cdrskinrc",o->rc_filenames[o->rc_filename_count-1], - Cdrskin_strleN,0); - ret= Sfile_multi_read_argv(progname,filenames_v,o->rc_filename_count, - &(o->pre_argc),&(o->pre_argv), - &(o->pre_argidx),&(o->pre_arglno),4); - free((char *) filenames_v); - return(ret); -} - -#endif /* ! Cdrskin_extra_leaN */ - - -/** Interpret those arguments which do not need libburn or which influence the - startup of libburn and/or the creation of the CdrskiN object. This is run - before libburn gets initialized and before Cdrskin_new() is called. - Options which need libburn or a CdrskiN object are processed in a different - function named Cdrskin_setup(). - @param flag Bitfield for control purposes: - bit0= do not finalize setup - bit1= do not read and interpret rc files - @return <=0 error, 1 success , 2 end program run with exit value 0 -*/ -int Cdrpreskin_setup(struct CdrpreskiN *o, int argc, char **argv, int flag) -/* -return: - <=0 error - 1 ok - 2 end program run (--help) -*/ -{ - int i,ret; - char *value_pt, reason[4096]; - -#ifndef Cdrskin_extra_leaN - if(argc>1) { - if(strcmp(argv[1],"--no_rc")==0 || strcmp(argv[1],"-version")==0 || - strcmp(argv[1],"--help")==0 || strcmp(argv[1],"-help")==0) - flag|= 2; - } - if(!(flag&2)) { - ret= Cdrpreskin_read_rc(o,argv[0],0); - if(ret<0) - return(-1); - if(o->pre_argc>1) { - ret= Cdrpreskin_setup(o,o->pre_argc,o->pre_argv,flag|1|2); - if(ret<=0) - return(ret); - /* ??? abort on ret==2 ? */ - } - } -#endif - - if(argc==1) { - fprintf(stderr,"cdrskin: SORRY : No options given. Try option --help\n"); - return(0); - } - - /* The two predefined fallback personalities are triggered by the progname */ - value_pt= strrchr(argv[0],'/'); - if(value_pt==NULL) - value_pt= argv[0]; - else - value_pt++; - if(strcmp(value_pt,"unicord")==0) - strcpy(o->fallback_program,"cdrecord"); - else if(strcmp(value_pt,"codim")==0) - strcpy(o->fallback_program,"wodim"); - - for (i= 1;iabort_handler= 3; - - } else if(strcmp(argv[i],"--allow_emulated_drives")==0) { - if(Cdrpreskin__allows_emulated_drives("",reason,0)<=0) { - fprintf(stderr,"cdrskin: WARNING : %s.\n",reason); - fprintf(stderr, - "cdrskin: WARNING : Only /dev/null will be available with \"stdio:\".\n"); - Cdrpreskin_consider_normal_user(0); - o->allow_emulated_drives= 2; - } else - o->allow_emulated_drives= 1; - - } else if(strcmp(argv[i],"--allow_setuid")==0) { - o->allow_setuid= 1; - - } else if(strcmp(argv[i],"--allow_untested_media")==0) { - o->allow_untested_media= 1; - - } else if(strcmp(argv[i],"blank=help")==0 || - strcmp(argv[i],"-blank=help")==0) { - -#ifndef Cdrskin_extra_leaN - - fprintf(stderr,"Blanking options:\n"); - fprintf(stderr,"\tall\t\tblank the entire disk\n"); - fprintf(stderr,"\tdisc\t\tblank the entire disk\n"); - fprintf(stderr,"\tdisk\t\tblank the entire disk\n"); - fprintf(stderr,"\tfast\t\tminimally blank the entire disk\n"); - fprintf(stderr,"\tminimal\t\tminimally blank the entire disk\n"); - fprintf(stderr, - "\tas_needed\tblank or format media to make it ready for (re-)use\n"); - fprintf(stderr, - "\tdeformat_sequential\t\tfully blank, even formatted DVD-RW\n"); - fprintf(stderr, - "\tdeformat_sequential_quickest\tminimally blank, even DVD-RW\n"); - fprintf(stderr, - "\tformat_if_needed\t\tmake overwriteable if needed and possible\n"); - fprintf(stderr, - "\tformat_overwrite\t\tformat a DVD-RW to \"Restricted Overwrite\"\n"); - fprintf(stderr, - "\tformat_overwrite_quickest\tto \"Restricted Overwrite intermediate\"\n"); - fprintf(stderr, - "\tformat_overwrite_full\t\tfull-size format a DVD-RW or DVD+RW\n"); - fprintf(stderr, - "\tformat_defectmgt[_max|_min|_none]\tformat DVD-RAM or BD-RE\n"); - fprintf(stderr, - "\tformat_defectmgt[_cert_on|_cert_off]\tcertification slow|quick\n"); - fprintf(stderr, - "\tformat_defectmgt_payload_\tformat DVD-RAM or BD-RE\n"); - fprintf(stderr, - "\tformat_by_index_\t\tformat by index from --list_formats\n"); - -#else /* ! Cdrskin_extra_leaN */ - - goto see_cdrskin_eng_html; - -#endif /* ! Cdrskin_extra_leaN */ - - if(argc==2) - {ret= 2; goto final_checks;} - - } else if(strcmp(argv[i],"--bragg_with_audio")==0) { - /* OBSOLETE 0.2.3 */; - - } else if(strcmp(argv[i],"--demand_a_drive")==0) { - o->scan_demands_drive= 1; - o->demands_cdrskin_caps= 1; - - } else if(strcmp(argv[i],"--devices")==0) { -#ifndef Cdrskin_extra_leaN - printf("Note: If this hangs for a while then there is a drive with\n"); - printf(" unexpected problems (e.g. ill DMA).\n"); - printf(" One may exclude such a device file by removing r- and w-\n"); - printf(" permissions for all cdrskin users.\n"); -#endif /* ! Cdrskin_extra_leaN */ - - o->no_whitelist= 1; - o->demands_cdrskin_caps= 1; - - } else if(strncmp(argv[i],"dev_translation=",16)==0) { - o->demands_cdrskin_caps= 1; - -#ifndef Cdrskin_extra_leaN - - if(o->adr_trn==NULL) { - ret= Cdradrtrn_new(&(o->adr_trn),0); - if(ret<=0) - goto no_adr_trn_mem; - } - if(argv[i][16]==0) { - fprintf(stderr, - "cdrskin: FATAL : dev_translation= : missing separator character\n"); - return(0); - } - ret= Cdradrtrn_add(o->adr_trn,argv[i]+17,argv[i]+16,1); - if(ret==-2) { -no_adr_trn_mem:; - fprintf(stderr, - "cdrskin: FATAL : address_translation= : cannot allocate memory\n"); - } else if(ret==-1) - fprintf(stderr, - "cdrskin: FATAL : address_translation= : table full (%d items)\n", - Cdradrtrn_leN); - else if(ret==0) - fprintf(stderr, - "cdrskin: FATAL : address_translation= : no address separator '%c' found\n", - argv[i][17]); - if(ret<=0) - return(0); - -#else /* ! Cdrskin_extra_leaN */ - - fprintf(stderr, - "cdrskin: FATAL : dev_translation= is not available in lean version\n"); - return(0); - -#endif /* Cdrskin_extra_leaN */ - - - } else if(strncmp(argv[i],"-dev=",5)==0) { - value_pt= argv[i]+5; - goto set_dev; - } else if(strncmp(argv[i],"dev=",4)==0) { - value_pt= argv[i]+4; -set_dev:; - if(strcmp(value_pt,"help")==0) { - -#ifndef Cdrskin_extra_leaN - - printf("\nSupported SCSI transports for this platform:\n"); - fflush(stdout); - if(o->old_pseudo_scsi_adr) { - fprintf(stderr,"\nTransport name:\t\tlibburn OLD_PSEUDO\n"); - fprintf(stderr, - "Transport descr.:\tBus0=DriveNum , Bus1=/dev/sgN , Bus2=/dev/hdX\n"); - } else { - fprintf(stderr,"\nTransport name:\t\tlibburn SCSI\n"); - fprintf(stderr, - "Transport descr.:\tSCSI Bus,Id,Lun as of operating system\n"); - } - fprintf(stderr,"Transp. layer ind.:\t\n"); - fprintf(stderr,"Target specifier:\tbus,target,lun\n"); - fprintf(stderr,"Target example:\t\t1,2,0\n"); - fprintf(stderr,"SCSI Bus scanning:\tsupported\n"); - fprintf(stderr,"Open via UNIX device:\tsupported\n"); - if(!o->old_pseudo_scsi_adr) { - fprintf(stderr,"\nTransport name:\t\tlibburn HD\n"); - fprintf(stderr, - "Transport descr.:\tLinux specific alias for /dev/hdX\n"); - fprintf(stderr,"Transp. layer ind.:\tATA:\n"); - fprintf(stderr,"Target specifier:\tbus,target,lun\n"); - fprintf(stderr,"Target example:\t\tATA:1,0,0\n"); - fprintf(stderr,"SCSI Bus scanning:\tsupported\n"); - fprintf(stderr,"Open via UNIX device:\tsupported\n"); - } - if(o->allow_emulated_drives) { - fprintf(stderr,"\nTransport name:\t\tlibburn on standard i/o\n"); - if(o->allow_emulated_drives==2) - fprintf(stderr, "Transport descr.:\troot or setuid may only write into /dev/null\n"); - else - fprintf(stderr, "Transport descr.:\twrite into file objects\n"); - fprintf(stderr,"Transp. layer ind.:\tstdio:\n"); - fprintf(stderr,"Target specifier:\tpath\n"); - fprintf(stderr,"Target example:\t\tstdio:/tmp/pseudo_drive\n"); - fprintf(stderr,"SCSI Bus scanning:\tnot supported\n"); - fprintf(stderr,"Open via UNIX device:\tnot supported\n"); - } else { - if(Cdrpreskin__allows_emulated_drives("",reason,0)>0) - printf("\ncdrskin: NOTE : Option --allow_emulated_drives would allow dev=stdio:\n"); - } - -#else /* ! Cdrskin_extra_leaN */ - - goto see_cdrskin_eng_html; - -#endif /* Cdrskin_extra_leaN */ - - {ret= 2; goto final_checks;} - } - if(strlen(value_pt)>=sizeof(o->raw_device_adr)) - goto dev_too_long; - strcpy(o->raw_device_adr,value_pt); - - } else if(strcmp(argv[i],"--drive_abort_on_busy")==0) { - o->abort_on_busy_drive= 1; - - } else if(strcmp(argv[i],"--drive_blocking")==0) { - o->drive_blocking= 1; - - } else if(strcmp(argv[i],"--drive_f_setlk")==0) { - o->drive_fcntl_f_setlk= 1; - - } else if(strcmp(argv[i],"--drive_not_exclusive")==0) { - o->drive_exclusive= 0; - o->drive_fcntl_f_setlk= 0; - - } else if(strcmp(argv[i],"--drive_not_f_setlk")==0) { - o->drive_fcntl_f_setlk= 0; - - } else if(strcmp(argv[i],"--drive_not_o_excl")==0) { - o->drive_exclusive= 0; - - } else if(strncmp(argv[i],"drive_scsi_dev_family=",22)==0) { - value_pt= argv[i]+22; - if(strcmp(value_pt,"sr")==0) - o->drive_scsi_dev_family= 1; - else if(strcmp(value_pt,"scd")==0) - o->drive_scsi_dev_family= 2; - else if(strcmp(value_pt,"sg")==0) - o->drive_scsi_dev_family= 4; - else - o->drive_scsi_dev_family= 0; - } else if(strcmp(argv[i],"--drive_scsi_exclusive")==0) { - o->drive_exclusive= 2; - o->demands_cdrskin_caps= 1; - - } else if(strcmp(argv[i],"driveropts=help")==0 || - strcmp(argv[i],"-driveropts=help")==0) { - -#ifndef Cdrskin_extra_leaN - - fprintf(stderr,"Driver options:\n"); - fprintf(stderr,"burnfree\tPrepare writer to use BURN-Free technology\n"); - fprintf(stderr,"noburnfree\tDisable using BURN-Free technology\n"); - -#else /* ! Cdrskin_extra_leaN */ - - goto see_cdrskin_eng_html; - -#endif /* Cdrskin_extra_leaN */ - - if(argc==2 || (i==2 && argc==3 && strncmp(argv[1],"dev=",4)==0)) - {ret= 2; goto final_checks;} - - } else if(strcmp(argv[i],"--help")==0) { - -#ifndef Cdrskin_extra_leaN - - printf("\n"); - printf("Usage: %s [options|source_addresses]\n", argv[0]); - printf("Burns preformatted data to CD or DVD via libburn.\n"); - printf("For the cdrecord compatible options which control the work of\n"); - printf( - "blanking and burning see output of option -help rather than --help.\n"); - printf("Non-cdrecord options:\n"); - printf(" --abort_handler do not leave the drive in busy state\n"); -#ifdef Cdrskin_libburn_has_get_best_speeD - printf( - " --adjust_speed_to_drive set only speeds offered by drive and media\n"); -#endif - printf(" --allow_emulated_drives dev=stdio: on file objects\n"); - printf( - " --allow_setuid disable setuid warning (setuid is insecure !)\n"); - printf( - " --allow_untested_media enable implemented untested media types\n"); - printf( - " --any_track allow source_addresses to match '^-.' or '='\n"); - printf( - " assert_write_lba= abort if not next write address == lba\n"); - printf( - " direct_write_amount= write random access to media like DVD+RW\n"); - printf(" --demand_a_drive exit !=0 on bus scans with empty result\n"); - printf(" --devices list accessible devices (tells /dev/...)\n"); - printf( - " dev_translation= set input address alias\n"); - printf(" e.g.: dev_translation=+ATA:1,0,0+/dev/sg1\n"); - printf(" --drive_abort_on_busy abort process if busy drive is found\n"); - printf(" (might be triggered by a busy hard disk)\n"); - printf(" --drive_blocking try to wait for busy drive to become free\n"); - printf(" (might be stalled by a busy hard disk)\n"); - printf(" --drive_f_setlk obtain exclusive lock via fcntl.\n"); - printf(" --drive_not_exclusive combined not_o_excl and not_f_setlk.\n"); - printf(" --drive_not_f_setlk do not obtain exclusive lock via fcntl.\n"); - printf(" --drive_not_o_excl do not ask kernel to prevent opening\n"); - printf(" busy drives. Effect is kernel dependend.\n"); - printf( - " drive_scsi_dev_family= select Linux device\n"); - printf(" file family to be used for (pseudo-)SCSI.\n"); - printf( - " --drive_scsi_exclusive try to exclusively reserve device files\n"); - printf(" /dev/srN, /dev/scdM, /dev/stK of drive.\n"); -#ifdef Cdrskin_burn_drive_eject_brokeN - printf( - " eject_device= set the device address for command eject\n"); -#endif - printf( - " fallback_program= use external program for exotic CD jobs\n"); - printf(" --fifo_disable disable fifo despite any fs=...\n"); - printf(" --fifo_per_track use a separate fifo for each track\n"); - printf( - " fifo_start_at= do not wait for full fifo but start burning\n"); - printf( - " as soon as the given number of bytes is read\n"); -#ifdef Cdrskin_libburn_has_set_filluP - printf(" --fill_up_media cause the last track to have maximum size\n"); -#endif - printf( - " grab_drive_and_wait= grab drive, wait given number of\n"); - printf( - " seconds, release drive, and do normal work\n"); - printf( - " --grow_overwriteable_iso emulate multi-session on media like DVD+RW\n"); - printf( - " --ignore_signals try to ignore any signals rather than to abort\n"); - printf(" --list_formats list format descriptors for loaded media.\n"); - printf(" --list_ignored_options list all ignored cdrecord options.\n"); -#ifdef Cdrskin_libburn_has_set_waitinG - printf(" modesty_on_drive= no writing into full drive buffer\n"); -#endif - printf(" --no_abort_handler exit even if the drive is in busy state\n"); - printf(" --no_blank_appendable refuse to blank appendable CD-RW\n"); - printf(" --no_convert_fs_adr only literal translations of dev=\n"); - printf( - " --no_rc as first argument: do not read startup files\n"); - printf(" --old_pseudo_scsi_adr use and report literal Bus,Target,Lun\n"); - printf(" rather than real SCSI and pseudo ATA.\n"); - printf(" --prodvd_cli_compatible react on some DVD types more like\n"); - printf(" cdrecord-ProDVD with blank= and -multi\n"); - printf( - " --single_track accept only last argument as source_address\n"); - -#ifdef Cdrskin_libburn_has_stream_recordinG - printf( - " stream_recording=\"on\"|\"off\" \"on\" requests to prefer speed\n"); - printf( - " over write error management.\n"); -#endif - -#ifdef Cdrskin_allow_libburn_taO - printf( - " tao_to_sao_tsize= use num as fixed track size if in a\n"); - printf( - " non-TAO mode track data are read from \"-\"\n"); - printf( - " and no tsize= was specified.\n"); -#else - printf( - " tao_to_sao_tsize= substitute -tao by -sao and eventually\n"); - printf(" augment input from \"-\" by tsize=\n"); - printf(" (set tao_to_sao_tsize=0 to disable it)\n"); -#endif - -#ifdef Cdrskin_libburn_has_get_spacE - printf( - " --tell_media_space prints maximum number of writeable data blocks\n"); -#endif - - printf( - " write_start_address= write to given byte address (DVD+RW)\n"); - printf( - "Preconfigured arguments are read from the following startup files\n"); - printf( - "if they exist and are readable. The sequence is as listed here:\n"); - printf(" /etc/default/cdrskin /etc/opt/cdrskin/rc\n"); - printf(" /etc/cdrskin/cdrskin.conf $HOME/.cdrskinrc\n"); - printf("Each file line is a single argument. No whitespace.\n"); - printf( - "By default any argument that does not match grep '^-.' or '=' is\n"); - printf( - "used as track source. If it is \"-\" then stdin is used.\n"); - printf("cdrskin : http://scdbackup.sourceforge.net/cdrskin_eng.html\n"); - printf(" mailto:scdbackup@gmx.net (Thomas Schmitt)\n"); - printf("libburn : http://libburnia-project.org\n"); - printf("cdrecord : ftp://ftp.berlios.de/pub/cdrecord/\n"); - printf("My respect to the authors of cdrecord and libburn.\n"); - printf("scdbackup: http://scdbackup.sourceforge.net/main_eng.html\n"); - printf("\n"); - -#else /* ! Cdrskin_extra_leaN */ - -see_cdrskin_eng_html:; - printf("This is a capability reduced lean version without help texts.\n"); - printf("See http://scdbackup.sourceforge.net/cdrskin_eng.html\n"); - -#endif /* Cdrskin_extra_leaN */ - - - {ret= 2; goto final_checks;} - } else if(strcmp(argv[i],"-help")==0) { - -#ifndef Cdrskin_extra_leaN - - fprintf(stderr,"Usage: %s [options|source_addresses]\n",argv[0]); - fprintf(stderr,"Note: This is not cdrecord. See cdrskin start message on stdout. See --help.\n"); - fprintf(stderr,"Options:\n"); - fprintf(stderr,"\t-version\tprint version information and exit\n"); - fprintf(stderr, - "\tdev=target\tpseudo-SCSI target to use as CD-Recorder\n"); - fprintf(stderr, - "\tgracetime=#\tset the grace time before starting to write to #.\n"); - fprintf(stderr,"\t-v\t\tincrement verbose level by one\n"); - fprintf(stderr, - "\tdriveropts=opt\topt= one of {burnfree,noburnfree,help}\n"); - fprintf(stderr, - "\t-checkdrive\tcheck if a driver for the drive is present\n"); - fprintf(stderr,"\t-inq\t\tdo an inquiry for the drive and exit\n"); - fprintf(stderr,"\t-scanbus\tscan the SCSI bus and exit\n"); - fprintf(stderr,"\tspeed=#\t\tset speed of drive\n"); - fprintf(stderr,"\tblank=type\tblank a CD-RW disc (see blank=help)\n"); - fprintf(stderr,"\t-format\t\tformat a CD-RW/DVD-RW/DVD+RW disc\n"); - fprintf(stderr, - "\tfs=#\t\tSet fifo size to # (0 to disable, default is 4 MB)\n"); - fprintf(stderr, - "\t-load\t\tload the disk and exit (works only with tray loader)\n"); - fprintf(stderr, - "\t-lock\t\tload and lock the disk and exit (works only with tray loader)\n"); - fprintf(stderr, - "\t-eject\t\teject the disk after doing the work\n"); - fprintf(stderr,"\t-dummy\t\tdo everything with laser turned off\n"); -#ifdef Cdrskin_libburn_has_multI - fprintf(stderr, - "\t-msinfo\t\tretrieve multi-session info for mkisofs >= 1.10\n"); - fprintf(stderr,"\tmsifile=path\trun -msinfo and copy output to file\n"); -#endif - fprintf(stderr,"\t-toc\t\tretrieve and print TOC/PMA data\n"); - fprintf(stderr, - "\t-atip\t\tretrieve media state, print \"Is *erasable\"\n"); -#ifdef Cdrskin_libburn_has_set_waitinG - fprintf(stderr, - "\tminbuf=percent\tset lower limit for drive buffer modesty\n"); -#endif -#ifdef Cdrskin_libburn_has_multI - fprintf(stderr, - "\t-multi\t\tgenerate a TOC that allows multi session\n"); -#endif - fprintf(stderr, - "\t-waiti\t\twait until input is available before opening SCSI\n"); - fprintf(stderr, - "\t-immed\t\tTry to use the SCSI IMMED flag with certain long lasting commands\n"); - fprintf(stderr, - "\t-force\t\tforce to continue on some errors to allow blanking\n"); -#ifdef Cdrskin_allow_libburn_taO - fprintf(stderr,"\t-tao\t\tWrite disk in TAO mode.\n"); -#endif - fprintf(stderr,"\t-dao\t\tWrite disk in SAO mode.\n"); - fprintf(stderr,"\t-sao\t\tWrite disk in SAO mode.\n"); - fprintf(stderr,"\t-raw96r\t\tWrite disk in RAW/RAW96R mode\n"); - fprintf(stderr,"\ttsize=#\t\tannounces exact size of source data\n"); - fprintf(stderr,"\tpadsize=#\tAmount of padding\n"); - fprintf(stderr,"\t-audio\t\tSubsequent tracks are CD-DA audio tracks\n"); - fprintf(stderr, - "\t-data\t\tSubsequent tracks are CD-ROM data mode 1 (default)\n"); - fprintf(stderr, - "\t-isosize\tUse iso9660 file system size for next data track\n"); - fprintf(stderr,"\t-pad\t\tpadsize=30k\n"); - fprintf(stderr, - "\t-nopad\t\tDo not pad (default, but applies only to data tracks)\n"); - fprintf(stderr, - "\t-swab\t\tAudio data source is byte-swapped (little-endian/Intel)\n"); - fprintf(stderr,"\t-help\t\tprint this text to stderr and exit\n"); - fprintf(stderr, - "Without option -data, .wav and .au files are extracted and burned as -audio.\n"); - fprintf(stderr, - "By default any argument that does not match grep '^-.' or '=' is used\n"); - fprintf(stderr, - "as track source address. Address \"-\" means stdin.\n"); - fprintf(stderr, - "cdrskin will ensure that an announced tsize= is written even if\n"); - fprintf(stderr, - "the source delivers fewer bytes. But 0 bytes from stdin with fifo\n"); - fprintf(stderr, - "enabled will lead to abort and no burn attempt at all.\n"); - -#else /* ! Cdrskin_extra_leaN */ - - fprintf(stderr,"Note: This is not cdrecord. See cdrskin start message on stdout.\n"); - fprintf(stderr, - "(writer profile: -atip retrieve, blank=type, -eject after work)\n"); - goto see_cdrskin_eng_html; - -#endif /* Cdrskin_extra_leaN */ - - {ret= 2; goto final_checks;} - - } else if(strcmp(argv[i],"--ignore_signals")==0) { - o->abort_handler= 2; - - } else if(strncmp(argv[i],"fallback_program=",17)==0) { - strcpy(o->fallback_program,argv[i]+17); - - } else if(strcmp(argv[i],"--no_abort_handler")==0) { - o->abort_handler= 0; - - } else if(strcmp(argv[i],"--no_convert_fs_adr")==0) { - o->no_convert_fs_adr= 1; - - } else if(strcmp(argv[i],"--old_pseudo_scsi_adr")==0) { - o->old_pseudo_scsi_adr= 1; - o->demands_cdrskin_caps= 1; - - } else if(strcmp(argv[i],"--no_rc")==0) { - if(i!=1) - fprintf(stderr, - "cdrskin: NOTE : option --no_rc would only work as first argument.\n"); - - } else if(strcmp(argv[i],"-raw96r")==0) { - strcpy(o->write_mode_name,"RAW/RAW96R"); - - } else if(strcmp(argv[i],"-sao")==0 || strcmp(argv[i],"-dao")==0) { - strcpy(o->write_mode_name,"SAO"); - - } else if(strcmp(argv[i],"-scanbus")==0) { - o->no_whitelist= 1; - - } else if(strcmp(argv[i],"-tao")==0) { - strcpy(o->write_mode_name,"TAO"); - - } else if(strcmp(argv[i],"-v")==0 || strcmp(argv[i],"-verbose")==0) { - (o->verbosity)++; - ClN(printf("cdrskin: verbosity level : %d\n",o->verbosity)); -set_severities:; - if(o->verbosity>=Cdrskin_verbose_debuG) - Cdrpreskin_set_severities(o,"NEVER","DEBUG",0); - } else if(strcmp(argv[i],"-vv")==0 || strcmp(argv[i],"-vvv")==0 || - strcmp(argv[i],"-vvvv")==0) { - (o->verbosity)+= strlen(argv[i])-1; - goto set_severities; - - } else if(strcmp(argv[i],"-version")==0) { - int major, minor, micro; - - printf( -"Cdrecord 2.01-Emulation Copyright (C) 2006-2008, see libburnia-project.org\n"); - printf("libburn interface : %d.%d.%d\n", - burn_header_version_major, burn_header_version_minor, - burn_header_version_micro); - burn_version(&major, &minor, µ); - printf("libburn in use : %d.%d.%d\n", major, minor, micro); - -#ifndef Cdrskin_extra_leaN - printf("cdrskin version : %s\n",Cdrskin_prog_versioN); -#else - printf("cdrskin version : %s.lean (capability reduced lean version)\n", - Cdrskin_prog_versioN); -#endif - - printf("Version timestamp : %s\n",Cdrskin_timestamP); - printf("Build timestamp : %s\n",Cdrskin_build_timestamP); - if(o->fallback_program[0]) { - char *hargv[2]; - - printf("Fallback program : %s\n",o->fallback_program); - printf("Fallback version :\n"); - hargv[0]= argv[0]; - hargv[1]= "-version"; - Cdrpreskin_fallback(o,2,hargv,1); /* dirty never come back */ - } - {ret= 2; goto ex;} - - } else if(strcmp(argv[i],"-waiti")==0) { - o->do_waiti= 1; - - } - - } - ret= 1; -final_checks:; - if(flag&1) - goto ex; - - if(o->do_waiti) { - fprintf(stderr, - "cdrskin: Option -waiti pauses program until input appears at stdin\n"); - printf("Waiting for data on stdin...\n"); - for(ret= 0; ret==0; ) - ret= Wait_for_input(0,1000000,0); - if(ret<0 || feof(stdin)) - fprintf(stderr, - "cdrskin: NOTE : stdin produces exception rather than data\n"); - fprintf(stderr,"cdrskin: Option -waiti pausing is done.\n"); - } - -#ifndef Cdrskin_libburn_no_burn_preset_device_opeN - burn_preset_device_open(o->drive_exclusive -#ifdef Cdrskin_libburn_preset_device_familY - | (o->drive_scsi_dev_family<<2) - | ((!!o->drive_fcntl_f_setlk)<<5) -#endif - , - o->drive_blocking, - o->abort_on_busy_drive); -#endif /* ! Cdrskin_libburn_no_burn_preset_device_opeN */ - - if(strlen(o->raw_device_adr)>0 && !o->no_whitelist) { - int driveno,hret; - char *adr,buf[Cdrskin_adrleN]; - - if(strcmp(o->raw_device_adr,"stdio:-")==0) { - fprintf(stderr, - "cdrskin: SORRY : Cannot accept drive address \"stdio:-\".\n"); - fprintf(stderr, - "cdrskin: HINT : Use \"stdio:/dev/fd/1\" if you really want to write to stdout.\n"); - {ret= 0; goto ex;} - } - adr= o->raw_device_adr; - -#ifndef Cdrskin_extra_leaN - if(o->adr_trn!=NULL) { - hret= Cdradrtrn_translate(o->adr_trn,adr,-1,buf,0); - if(hret<=0) { - fprintf(stderr, - "cdrskin: FATAL : address translation failed (address too long ?) \n"); - {ret= 0; goto ex;} - } - adr= buf; - } -#endif /* ! Cdrskin_extra_leaN */ - - if(adr[0]=='/') { - if(strlen(adr)>=sizeof(o->device_adr)) { -dev_too_long:; - fprintf(stderr, - "cdrskin: FATAL : dev=... too long (max. %d characters)\n", - (int) sizeof(o->device_adr)-1); - {ret= 0; goto ex;} - } - strcpy(o->device_adr,adr); - } else { - ret= Cdrpreskin__cdrecord_to_dev(adr,o->device_adr,&driveno, - !!o->old_pseudo_scsi_adr); - if(ret==-2 || ret==-3) - {ret= 0; goto ex;} - if(ret<0) - goto ex; - if(ret==0) { - strcpy(o->device_adr,adr); - ret= 1; - } - } - -#ifdef Cdrskin_libburn_has_convert_fs_adR - - if(strlen(o->device_adr)>0 && !o->no_convert_fs_adr) { - int lret; - char link_adr[Cdrskin_strleN+1]; - - strcpy(link_adr,o->device_adr); - lret = burn_drive_convert_fs_adr(link_adr,o->device_adr); - if(lret<0) { - fprintf(stderr, - "cdrskin: NOTE : Please inform libburn-hackers@pykix.org about:\n"); - fprintf(stderr, - "cdrskin: burn_drive_convert_fs_adr() returned %d\n",lret); - } - } - -#endif /* Cdrskin_libburn_has_convert_fs_adR */ - - } - -#ifdef Cdrskin_libburn_has_allow_untested_profileS - burn_allow_untested_profiles(!!o->allow_untested_media); -#endif - - /* A60927 : note to myself : no "ret= 1;" here. It breaks --help , -version */ - -ex:; - /* Eventually replace current stdout by dup(1) from start of program */ - if(strcmp(o->device_adr,"stdio:/dev/fd/1")==0 && o->result_fd >= 0) - sprintf(o->device_adr,"stdio:/dev/fd/%d",o->result_fd); - -#ifndef Cdrskin_extra_leaN - if(ret<=0 || !(flag&1)) - Cdradrtrn_destroy(&(o->adr_trn),0); -#endif - - return(ret); -} - - -/* --------------------------------------------------------------------- */ - - - -/** The maximum number of tracks */ -#define Cdrskin_track_maX 99 - - -/** Work around the fact that libburn leaves the track input fds open - after the track is done. This can hide a few overflow bytes buffered - by the fifo-to-libburn pipe which would cause a broken-pipe error - if libburn would close that outlet. - This macro enables a coarse workaround which tries to read bytes from - the track inlets after burning has ended. Probably not a good idea if - libburn would close the inlet fds. -*/ -#define Cdrskin_libburn_leaves_inlet_opeN 1 - - -/** List of furter wishes towards libburn: - - write mode which does not demand a track size in advance - - obtain minimum drive speed (for cdrskin -atip) - - obtain MMC profile of inserted media (for cdrskin -v -atip) - - a possibility to implement cdrskin -multi - - a possibilty to implement cdrskin -reset -*/ - - -/** <<< Hopefully obsolete: - Limit to prevent int rollovers within libburn as long as not everything is - changed to 64 bit off_t : 2 GB minus 800 MB for eventual computations. -#define Cdrskin_tracksize_maX 1308622848 -*/ -#define Cdrskin_tracksize_maX 1024.0*1024.0*1024.0*1024.0 - - -/* Some constants obtained by hearsay and experiments */ - -/** The CD payload speed factor for reporting progress: 1x = 150 kB/s */ -static double Cdrskin_cd_speed_factoR= 150.0*1024.0; -/** The DVD payload speed factor for reporting progress: 1x */ -static double Cdrskin_dvd_speed_factoR= 1385000; -/** The BD payload speed factor for reporting progress: 1x */ -static double Cdrskin_bd_speed_factoR= 4495625; - -/** The effective payload speed factor for reporting progress */ -static double Cdrskin_speed_factoR= 150.0*1024.0; - -/** The speed conversion factors consumer x-speed to libburn speed as used with - burn_drive_set_speed() burn_drive_get_write_speed() -*/ -static double Cdrskin_libburn_cd_speed_factoR= 176.4; -static double Cdrskin_libburn_dvd_speed_factoR= 1385.0; -static double Cdrskin_libburn_bd_speed_factoR= 4495.625; - -/* The effective speed conversion factor for burn_drive_set_speed() */ -static double Cdrskin_libburn_speed_factoR= 176.4; - -/** Add-on for burn_drive_set_speed() to accomodate to the slightley oversized - speed ideas of my LG DVDRAM GSA-4082B. LITE-ON LTR-48125S tolerates it. -*/ -static double Cdrskin_libburn_cd_speed_addoN= 40.0; -static double Cdrskin_libburn_dvd_speed_addoN= 1.0; /*poor accuracy with 2.4x*/ -static double Cdrskin_libburn_bd_speed_addoN= 1.0; -static double Cdrskin_libburn_speed_addoN = 40.0; - - -/** The program run control object. Defaults: see Cdrskin_new(). */ -struct CdrskiN { - - /** Settings already interpreted by Cdrpreskin_setup */ - struct CdrpreskiN *preskin; - - /** Job: what to do, plus some parameters. */ - int verbosity; - double x_speed; - int adjust_speed_to_drive; - int gracetime; - int dummy_mode; - int force_is_set; - int stream_recording_is_set; - int single_track; - int prodvd_cli_compatible; - - int do_devices; - - int do_scanbus; - - int do_load; - - int do_checkdrive; - - int do_msinfo; - char msifile[Cdrskin_strleN]; - - int do_atip; - int do_list_formats; - - int do_blank; - int blank_fast; - int no_blank_appendable; - int blank_format_type; /* bit0-7: job type - 0=blank - 1=format_overwrite for DVD+RW, DVD-RW - bit8-15: bit0-7 of burn_disc_format(flag) - bit8 = write zeros after formatting - bit9 = insist in size 0 - bit10= format to maximum available size - bit11= - reserved - - bit12= - reserved - - bit13= - reserved - - bit14= - reserved - - bit15= format by index - 2=deformat_sequential (blank_fast might matter) - 3=format (= format_overwrite restricted to DVD+RW) - 4=format_defectmgt for DVD-RAM, BD-RE - bit8-15: bit0-7 of burn_disc_format(flag) - bit8 = write zeros after formatting - bit9+10: size mode - 0 = use parameter size as far as it makes sense - 1 = (identical to size mode 0) - 2 = without bit7: format to maximum size - with bit7 : take size from indexed format - descriptor - 3 = without bit7: format to default size - with bit7 : take size from indexed format - descriptor - bit11= - reserved - - bit12= - reserved - - bit13= try to disable defect management - bit14= - reserved - - bit15= format by index - 5=format_by_index - gets mapped to 4 with DVD-RAM and BD-RE else to 1, - bit15 should be set and bit16-23 should contain - a usable index number - 6=format_if_needed - gets mapped to default variants of specialized - formats if the media state requires formatting - before writing - 7=if_needed - gets mapped to 6 for DVD-RAM and BD-RE, - to 0 with all other non-blanks - - bit8-15: bit0-7 of burn_disc_format(flag) - depending on job type - */ - int blank_format_index; /* bit8-15 of burn_disc_format(flag) */ - double blank_format_size; /* to be used with burn_disc_format() */ - int blank_format_no_certify; - - int do_direct_write; - int do_burn; - int tell_media_space; /* actually do not burn but tell the available space */ - int burnfree; - /** The write mode (like SAO or RAW96/R). See libburn. - Controled by preskin->write_mode_name */ - enum burn_write_types write_type; - int block_type; - int multi; - int modesty_on_drive; - int min_buffer_percent; - int max_buffer_percent; - - double write_start_address; - double direct_write_amount; - int assert_write_lba; - - int do_eject; - char eject_device[Cdrskin_strleN]; - - - /** The current data source and its eventual parameters. - source_path may be either "-" for stdin, "#N" for open filedescriptor N - or the address of a readable file. - */ - char source_path[Cdrskin_strleN]; - double fixed_size; - double smallest_tsize; - int has_open_ended_track; - double padding; - int set_by_padsize; - int fill_up_media; - - /** track_type may be set to BURN_MODE1, BURN_AUDIO, etc. */ - int track_type; - int track_type_by_default; /* 0= explicit, 1=not set, 2=by file extension */ - int swap_audio_bytes; - - /** The list of tracks with their data sources and parameters */ - struct CdrtracK *tracklist[Cdrskin_track_maX]; - int track_counter; - /** a guess about what track might be processing right now */ - int supposed_track_idx; - - int fifo_enabled; - /** Optional fifo between input fd and libburn. It uses a pipe(2) to transfer - data to libburn. This fifo may be actually the start of a chain of fifos - which are to be processed simultaneously. - The fifo object knows the real input fd and the fd[1] of the pipe. - This is just a reference pointer. The fifos are managed by the tracks - which either line up their fifos or share the fifo of the first track. - */ - struct CdrfifO *fifo; - /** fd[0] of the fifo pipe. This is from where libburn reads its data. */ - int fifo_outlet_fd; - int fifo_size; - int fifo_start_at; - int fifo_per_track; - - - /** User defined address translation */ - struct CdradrtrN *adr_trn; - - - /** The drives known to libburn after scan */ - struct burn_drive_info *drives; - unsigned int n_drives; - /** The drive selected for operation by CdrskiN */ - int driveno; - /** The persistent drive address of that drive */ - char device_adr[Cdrskin_adrleN]; - - - /** Progress state info: whether libburn is actually processing payload data*/ - int is_writing; - /** Previously detected drive state */ - enum burn_drive_status previous_drive_status; - - /** abort parameters */ - int abort_max_wait; - - /** Engagement info for eventual abort */ - int lib_is_initialized; - pid_t control_pid; /* pid of the thread that calls libburn */ - int drive_is_grabbed; - int drive_is_busy; /* Whether drive was told to do something cancel-worthy */ - struct burn_drive *grabbed_drive; - -#ifndef Cdrskin_extra_leaN - /** Abort test facility */ - double abort_after_bytecount; -#endif /* ! Cdrskin_extra_leaN */ - - - /** Some intermediate option info which is stored until setup finalization */ - double tao_to_sao_tsize; - int stdin_source_used; - - /* Info about media capabilities */ - int media_does_multi; - int media_is_overwriteable; - - /* For option -isosize and --grow_overwriteable_iso */ - int use_data_image_size; - - /* For growisofs stunt : - 0=disabled, - 1=do stunt, fabricate toc, allow multi, - 2=overwriteable_iso_head is valid - 3=initial session (mostly to appease -multi on overwriteables) - */ - int grow_overwriteable_iso; - /* New image head buffer for --grow_overwriteable_iso */ - char overwriteable_iso_head[32*2048]; /* block 0 to 31 of target */ - -}; - -int Cdrskin_destroy(struct CdrskiN **o, int flag); -int Cdrskin_grab_drive(struct CdrskiN *skin, int flag); -int Cdrskin_release_drive(struct CdrskiN *skin, int flag); -int Cdrskin_report_disc_status(struct CdrskiN *skin, enum burn_disc_status s, - int flag); - -/** Create a cdrskin program run control object. - @param skin Returns pointer to resulting - @param flag Bitfield for control purposes: - bit0= library is already initialized - @return <=0 error, 1 success -*/ -int Cdrskin_new(struct CdrskiN **skin, struct CdrpreskiN *preskin, int flag) -{ - struct CdrskiN *o; - int ret,i; - - (*skin)= o= TSOB_FELD(struct CdrskiN,1); - if(o==NULL) - return(-1); - o->preskin= preskin; - o->verbosity= preskin->verbosity; - o->x_speed= -1.0; - o->adjust_speed_to_drive= 0; - o->gracetime= 0; - o->dummy_mode= 0; - o->force_is_set= 0; - o->stream_recording_is_set= 0; - o->single_track= 0; - o->prodvd_cli_compatible= 0; - o->do_devices= 0; - o->do_scanbus= 0; - o->do_load= 0; - o->do_checkdrive= 0; - o->do_msinfo= 0; - o->msifile[0]= 0; - o->do_atip= 0; - o->do_list_formats= 0; - o->do_blank= 0; - o->blank_fast= 0; - o->no_blank_appendable= 0; - o->blank_format_type= 0; - o->blank_format_index= -1; - o->blank_format_size= 0.0; - o->blank_format_no_certify= 0; - o->do_direct_write= 0; - o->do_burn= 0; - o->tell_media_space= 0; - o->write_type= BURN_WRITE_SAO; - o->block_type= BURN_BLOCK_SAO; - o->multi= 0; - o->modesty_on_drive= 0; - o->min_buffer_percent= 65; - o->max_buffer_percent= 95; - o->write_start_address= -1.0; - o->direct_write_amount= -1.0; - o->assert_write_lba= -1; - o->burnfree= 1; - o->do_eject= 0; - o->eject_device[0]= 0; - o->source_path[0]= 0; - o->fixed_size= 0.0; - o->smallest_tsize= -1.0; - o->has_open_ended_track= 0; - o->padding= 0.0; - o->set_by_padsize= 0; - o->fill_up_media= 0; - o->track_type= BURN_MODE1; - o->swap_audio_bytes= 1; /* cdrecord default is big-endian (msb_first) */ - o->track_type_by_default= 1; - for(i=0;itracklist[i]= NULL; - o->track_counter= 0; - o->supposed_track_idx= -1; - o->fifo_enabled= 1; - o->fifo= NULL; - o->fifo_outlet_fd= -1; - o->fifo_size= 4*1024*1024; - o->fifo_start_at= -1; - o->fifo_per_track= 0; - o->adr_trn= NULL; - o->drives= NULL; - o->n_drives= 0; - o->driveno= 0; - o->device_adr[0]= 0; - o->is_writing= 0; - o->previous_drive_status = BURN_DRIVE_IDLE; - o->abort_max_wait= 74*60; - o->lib_is_initialized= (flag&1); - o->control_pid= getpid(); - o->drive_is_grabbed= 0; - o->drive_is_busy= 0; - o->grabbed_drive= NULL; -#ifndef Cdrskin_extra_leaN - o->abort_after_bytecount= -1.0; -#endif /* ! Cdrskin_extra_leaN */ - o->tao_to_sao_tsize= 0.0; - o->stdin_source_used= 0; - o->use_data_image_size= 0; - o->media_does_multi= 0; - o->media_is_overwriteable= 0; - o->grow_overwriteable_iso= 0; - memset(o->overwriteable_iso_head,0,sizeof(o->overwriteable_iso_head)); - -#ifndef Cdrskin_extra_leaN - ret= Cdradrtrn_new(&(o->adr_trn),0); - if(ret<=0) - goto failed; -#endif /* ! Cdrskin_extra_leaN */ - - return(1); -failed:; - Cdrskin_destroy(skin,0); - return(-1); -} - - -/** Release from memory a cdrskin object */ -int Cdrskin_destroy(struct CdrskiN **o, int flag) -{ - struct CdrskiN *skin; - int i; - - skin= *o; - if(skin==NULL) - return(0); - if(skin->drive_is_grabbed) - Cdrskin_release_drive(skin,0); - for(i=0;itrack_counter;i++) - Cdrtrack_destroy(&(skin->tracklist[i]),0); - -#ifndef Cdrskin_extra_leaN - Cdradrtrn_destroy(&(skin->adr_trn),0); -#endif /* ! Cdrskin_extra_leaN */ - - Cdrpreskin_destroy(&(skin->preskin),0); - if(skin->drives!=NULL) - burn_drive_info_free(skin->drives); - free((char *) skin); - *o= NULL; - return(1); -} - - -/** Return the addresses of the drive. device_adr is the libburn persistent - address of the drive, raw_adr is the address as given by the user. -*/ -int Cdrskin_get_device_adr(struct CdrskiN *skin, - char **device_adr, char **raw_adr, int *no_convert_fs_adr, int flag) -{ - burn_drive_get_adr(&skin->drives[skin->driveno],skin->device_adr); - *device_adr= skin->device_adr; - *raw_adr= skin->preskin->raw_device_adr; - *no_convert_fs_adr= skin->preskin->no_convert_fs_adr; - return(1); -} - - -int Cdrskin_get_drive(struct CdrskiN *skin, struct burn_drive **drive,int flag) -{ - if(skin->driveno<0 || skin->driveno >= skin->n_drives) - return(0); - *drive= skin->drives[skin->driveno].drive; - return ((*drive) != NULL); -} - - -/** Return information about current track source */ -int Cdrskin_get_source(struct CdrskiN *skin, char *source_path, - double *fixed_size, double *tao_to_sao_tsize, - int *use_data_image_size, - double *padding, int *set_by_padsize, - int *track_type, int *track_type_by_default, - int *swap_audio_bytes, int flag) -{ - strcpy(source_path,skin->source_path); - *fixed_size= skin->fixed_size; - *tao_to_sao_tsize = skin->tao_to_sao_tsize; - *use_data_image_size= skin->use_data_image_size; - *padding= skin->padding; - *set_by_padsize= skin->set_by_padsize; - *track_type= skin->track_type; - *track_type_by_default= skin->track_type_by_default; - *swap_audio_bytes= skin->swap_audio_bytes; - return(1); -} - - -#ifndef Cdrskin_extra_leaN - -/** Return information about current fifo setting */ -int Cdrskin_get_fifo_par(struct CdrskiN *skin, int *fifo_enabled, - int *fifo_size, int *fifo_start_at, int flag) -{ - *fifo_enabled= skin->fifo_enabled; - *fifo_size= skin->fifo_size; - *fifo_start_at= skin->fifo_start_at; - return(1); -} - - -/** Create and install fifo objects between track data sources and libburn. - The sources and parameters are known to skin. - @return <=0 error, 1 success -*/ -int Cdrskin_attach_fifo(struct CdrskiN *skin, int flag) -{ - struct CdrfifO *ff= NULL; - int ret,i,hflag; - - skin->fifo= NULL; - for(i=0;itrack_counter;i++) { - hflag= (skin->verbosity>=Cdrskin_verbose_debuG); - if(i==skin->track_counter-1) - hflag|= 4; - if(skin->verbosity>=Cdrskin_verbose_cmD) { - if(skin->fifo_per_track) - printf("cdrskin: track %d establishing fifo of %d bytes\n", - i+1,skin->fifo_size); - else if(i==0) - printf("cdrskin: establishing fifo of %d bytes\n",skin->fifo_size); - else { - if(skin->verbosity>=Cdrskin_verbose_debuG) - ClN(fprintf(stderr,"cdrskin_debug: attaching track %d to fifo\n",i+1)); - hflag|= 2; - } - } - ret= Cdrtrack_attach_fifo(skin->tracklist[i],&(skin->fifo_outlet_fd),ff, - hflag); - if(ret<=0) { - fprintf(stderr,"cdrskin: FATAL : failed to attach fifo.\n"); - return(0); - } - if(i==0 || skin->fifo_per_track) - Cdrtrack_get_fifo(skin->tracklist[i],&ff,0); - if(i==0) - skin->fifo= ff; - } - return(1); -} - - -/** Read data into the track fifos until either #1 is full or its data source - is exhausted. - @return <=0 error, 1 success -*/ -int Cdrskin_fill_fifo(struct CdrskiN *skin, int flag) -{ - int ret; - - ret= Cdrtrack_fill_fifo(skin->tracklist[0],skin->fifo_start_at,0); - if(ret<=0) - return(ret); - printf("input buffer ready.\n"); - fflush(stdout); - return(1); -} - -#endif /* ! Cdrskin_extra_leaN */ - - -/** Inform libburn about the consumer x-speed factor of skin */ -int Cdrskin_adjust_speed(struct CdrskiN *skin, int flag) -{ - int k_speed, modesty= 0; - - if(skin->x_speed<0) - k_speed= 0; /* libburn.h promises 0 to be max speed. */ - else if(skin->x_speed==0) { /* cdrecord specifies 0 as minimum speed. */ -#ifdef Cdrskin_libburn_has_get_best_speeD - k_speed= -1; -#else - k_speed= Cdrskin_libburn_speed_factoR+Cdrskin_libburn_speed_addoN; -#endif - } else - k_speed= skin->x_speed*Cdrskin_libburn_speed_factoR + - Cdrskin_libburn_speed_addoN; - - if(skin->verbosity>=Cdrskin_verbose_debuG) - ClN(fprintf(stderr,"cdrskin_debug: k_speed= %d\n",k_speed)); - -#ifdef Cdrskin_libburn_has_get_best_speeD - if(skin->adjust_speed_to_drive && !skin->force_is_set) { - struct burn_speed_descriptor *best_descr; - burn_drive_get_best_speed(skin->drives[skin->driveno].drive,k_speed, - &best_descr,0); - if(best_descr!=NULL) { - k_speed= best_descr->write_speed; - skin->x_speed = ((double) k_speed) / Cdrskin_libburn_speed_factoR; - } - } -#endif /* Cdrskin_libburn_has_get_best_speeD */ - - burn_drive_set_speed(skin->drives[skin->driveno].drive,k_speed,k_speed); - -#ifdef Cdrskin_libburn_has_set_waitinG - modesty= skin->modesty_on_drive; - burn_drive_set_buffer_waiting(skin->drives[skin->driveno].drive, - modesty, -1, -1, -1, - skin->min_buffer_percent, - skin->max_buffer_percent); -#endif - return(1); -} - - -int Cdrskin_determine_media_caps(struct CdrskiN *skin, int flag) -{ -#ifdef Cdrskin_libburn_has_get_multi_capS - int ret; - struct burn_multi_caps *caps = NULL; - - skin->media_is_overwriteable= skin->media_does_multi= 0; - ret= burn_disc_get_multi_caps(skin->grabbed_drive,BURN_WRITE_NONE,&caps,0); - if(ret<=0) - return(0); - skin->media_is_overwriteable= !!caps->start_adr; - skin->media_does_multi= !!caps->multi_session; - return(1); -#else /* Cdrskin_libburn_has_get_multi_capS */ - return(-1); -#endif -} - - -/** Obtain access to a libburn drive for writing or information retrieval. - If libburn is not restricted to a single persistent address then the - unused drives are dropped. This might be done by shutting down and - restartiing libburn with the wanted drive only. Thus, after this call, - libburn is supposed to have open only the reserved drive. - All other drives should be free for other use. - Warning: Do not store struct burn_drive pointer over this call. - Any such pointer might be invalid afterwards. - @param flag Bitfield for control purposes: - bit0= bus is unscanned, device is known, - use burn_drive_scan_and_grab() - bit1= do not load drive tray - bit2= do not issue error message on failure - bit3= demand and evtl. report media, return 0 if none to see - bit4= grab drive with unsuitable media even if fallback program - @return <=0 error, 1 success -*/ -int Cdrskin_grab_drive(struct CdrskiN *skin, int flag) -{ - int ret,i,profile_number; - struct burn_drive *drive; - char profile_name[80]; - enum burn_disc_status s; -#ifdef Cdrskin_grab_abort_brokeN - int restore_handler= 0; -#endif - - i= 0;/* as long as its use is conditional, so gcc -Wall does not complain */ - - if(skin->drive_is_grabbed) - Cdrskin_release_drive(skin,0); - - if(flag&1) { - skin->driveno= 0; - drive= NULL; - skin->grabbed_drive= drive; - } else { - drive= skin->drives[skin->driveno].drive; - skin->grabbed_drive= drive; - } - -#ifdef Cdrskin_grab_abort_brokeN - - /* There seems to be no way to get a drive out of status BURN_DRIVE_GRABBING - So try to block out signals if there is a signal handler installed */ - if(skin->preskin->abort_handler==1 || - skin->preskin->abort_handler==3 || - skin->preskin->abort_handler==4) { - Cleanup_set_handlers(NULL,NULL,2); - restore_handler= 1; - } - -#endif /* ! Cdrskin_grab_abort_brokeN */ - -#ifndef Cdrskin_oldfashioned_api_usE - - - if(flag&1) { - ret= burn_drive_scan_and_grab(&(skin->drives),skin->preskin->device_adr, - !(flag&2)); - if(ret<=0) { - if(!(flag&4)) - fprintf(stderr,"cdrskin: FATAL : unable to open drive '%s'\n", - skin->preskin->device_adr); - goto ex; - } - skin->driveno= 0; - drive= skin->drives[skin->driveno].drive; - skin->grabbed_drive= drive; - } else { - if(strlen(skin->preskin->device_adr)<=0) { - - if(skin->verbosity>=Cdrskin_verbose_debuG) - ClN(fprintf(stderr, - "cdrskin_debug: Cdrskin_grab_drive() dropping unwanted drives (%d)\n", - skin->n_drives-1)); - for(i=0;in_drives;i++) { - if(i==skin->driveno) - continue; - if(skin->verbosity>=Cdrskin_verbose_debuG) - ClN(fprintf(stderr, - "cdrskin_debug: Cdrskin_grab_drive() dropped drive number %d\n",i)); - ret= burn_drive_info_forget(&(skin->drives[i]), 0); - if(ret==1 || ret==2) - continue; - fprintf(stderr, - "cdrskin: NOTE : Please inform libburn-hackers@pykix.org about:\n"); - fprintf(stderr, - "cdrskin: burn_drive_info_forget() returns %d\n",ret); - } - - } - -#else - - { - -#endif /* Cdrskin_oldfashioned_api_usE */ - - ret= burn_drive_grab(drive,!(flag&2)); - if(ret==0) { - if(!(flag&4)) - fprintf(stderr,"cdrskin: FATAL : unable to open drive %d\n", - skin->driveno); - goto ex; - } - -#ifdef Cdrskin_is_erasable_on_load_is_brokeN - /* RIP-14.5 + LITE-ON 48125S produce a false status if tray was unloaded */ - /* Therefore the first grab was just for loading */ - skin->drive_is_grabbed= 1; /* message to eventual abort handler */ - burn_drive_release(drive,0); - skin->drive_is_grabbed= 0; - - /* now grab the drive for real */ - ret= burn_drive_grab(drive,!(flag&2)); - if(ret==0) { - if(!(flag&4)) - fprintf(stderr,"cdrskin: FATAL : unable to open drive %d\n", - skin->driveno); - goto ex; - } -#endif /* ! Cdrskin_is_erasable_on_load_is_brokeN */ - - } - skin->drive_is_grabbed= 1; - - s= burn_disc_get_status(drive); - if((flag&8)) { - if(skin->verbosity>=Cdrskin_verbose_progresS) - Cdrskin_report_disc_status(skin,s,1); - if(s==BURN_DISC_EMPTY) { - Cdrskin_release_drive(skin,0); - fprintf(stderr,"cdrskin: SORRY : No media found in drive\n"); - ret= 0; goto ex; - } - } - - Cdrskin_speed_factoR= Cdrskin_cd_speed_factoR; - Cdrskin_libburn_speed_factoR= Cdrskin_libburn_cd_speed_factoR; - Cdrskin_libburn_speed_addoN= Cdrskin_libburn_cd_speed_addoN; -#ifdef Cdrskin_libburn_has_get_profilE - ret= burn_disc_get_profile(drive,&profile_number,profile_name); - if(ret>0) { - if(strstr(profile_name,"DVD")==profile_name || - strstr(profile_name,"stdio")==profile_name ) { - Cdrskin_speed_factoR= Cdrskin_dvd_speed_factoR; - Cdrskin_libburn_speed_factoR= Cdrskin_libburn_dvd_speed_factoR; - Cdrskin_libburn_speed_addoN= Cdrskin_libburn_dvd_speed_addoN; - } else if(strstr(profile_name,"BD")==profile_name) { - Cdrskin_speed_factoR= Cdrskin_bd_speed_factoR; - Cdrskin_libburn_speed_factoR= Cdrskin_libburn_bd_speed_factoR; - Cdrskin_libburn_speed_addoN= Cdrskin_libburn_bd_speed_addoN; - } - } -#endif /* Cdrskin_libburn_has_get_profilE */ - if(skin->preskin->fallback_program[0] && s==BURN_DISC_UNSUITABLE && - skin->preskin->demands_cdrskin_caps<=0 && !(flag&16)) { - skin->preskin->demands_cdrecord_caps= 1; - fprintf(stderr, - "cdrskin: NOTE : Will delegate job to fallback program '%s'.\n", - skin->preskin->fallback_program); - Cdrskin_release_drive(skin,0); - ret= 0; goto ex; - } - - Cdrskin_determine_media_caps(skin,0); - - ret= 1; -ex:; - -#ifdef Cdrskin_grab_abort_brokeN - if(restore_handler) { - int Cdrskin_abort_handler(struct CdrskiN *, int, int); - Cleanup_set_handlers(skin,(Cleanup_app_handler_T) Cdrskin_abort_handler,4); - } -#endif /* Cdrskin_grab_abort_brokeN */ - - if(ret<=0) { - skin->drive_is_grabbed= 0; - skin->grabbed_drive= NULL; - } - return(ret); -} - - -/** Release grabbed libburn drive - @param flag Bitfield for control purposes: - bit0= eject - bit1= leave tray locked (eventually overrides bit0) -*/ -int Cdrskin_release_drive(struct CdrskiN *skin, int flag) -{ - if((!skin->drive_is_grabbed) || skin->grabbed_drive==NULL) { - fprintf(stderr,"cdrskin: CAUGHT : release of non-grabbed drive.\n"); - return(0); - } - if(flag&2) - burn_drive_leave_locked(skin->grabbed_drive,0); - else - burn_drive_release(skin->grabbed_drive,(flag&1)); - skin->drive_is_grabbed= 0; - skin->grabbed_drive= NULL; - return(1); -} - - -/** Clean up resources in abort situations. To be called by Cleanup subsystem - but hardly ever by the application. The program must exit afterwards. -*/ -int Cdrskin_abort_handler(struct CdrskiN *skin, int signum, int flag) -{ - -#ifdef Cdrskin_libburn_has_burn_aborT - - int ret; - -#else - - int wait_grain= 100000,first_status= 1; - double start_time,last_time,current_time; - -#endif /* ! Cdrskin_libburn_has_burn_aborT */ - - struct burn_progress p; - enum burn_drive_status drive_status= BURN_DRIVE_GRABBING; - - if(getpid()!=skin->control_pid) { - if(skin->verbosity>=Cdrskin_verbose_debuG) - ClN(fprintf(stderr, - "\ncdrskin_debug: ABORT : [%d] Thread rejected: pid=%d, signum=%d\n", - skin->control_pid,getpid(),signum)); - -#ifdef Not_yeT - /* >>> find more abstract and system independent way to determine - signals which make no sense with a return */ - if(signum==11) { - Cleanup_set_handlers(NULL,NULL,1); /* allow abort */ - return(0); /* let exit */ - } -#endif - usleep(1000000); - - return(-2); /* do only process the control thread */ - } - if(skin->preskin->abort_handler==3) - Cleanup_set_handlers(NULL,NULL,2); /* ignore all signals */ - else if(skin->preskin->abort_handler==4) - Cleanup_set_handlers(NULL,NULL,1); /* allow abort */ - fprintf(stderr, - "\ncdrskin: ABORT : Handling started. Please do not press CTRL+C now.\n"); - if(skin->preskin->abort_handler==3) - fprintf(stderr,"cdrskin: ABORT : Trying to ignore any further signals\n"); - -#ifndef Cdrskin_extra_leaN - if(skin->fifo!=NULL) - Cdrfifo_close_all(skin->fifo,0); -#endif - -#ifdef Cdrskin_libburn_has_burn_aborT - - /* Only for user info */ - if(skin->grabbed_drive!=NULL) - drive_status= burn_drive_get_status(skin->grabbed_drive,&p); - if(drive_status!=BURN_DRIVE_IDLE) { - fprintf(stderr,"cdrskin: ABORT : Abort processing depends on speed and buffer size\n"); - fprintf(stderr,"cdrskin: ABORT : Usually it is done with 4x speed after about a MINUTE\n"); - fprintf(stderr,"cdrskin: URGE : But wait at least the normal burning time before any kill -9\n"); - } - - ret= burn_abort(skin->abort_max_wait, burn_abort_pacifier, "cdrskin: "); - if(ret<=0) { - fprintf(stderr, - "\ncdrskin: ABORT : Cannot cancel burn session and release drive.\n"); - return(0); - } - fprintf(stderr,"\n"); - -#else /* Cdrskin_libburn_has_burn_aborT */ - - if(skin->grabbed_drive!=NULL) { - drive_status= burn_drive_get_status(skin->grabbed_drive,&p); - if(drive_status!=BURN_DRIVE_IDLE && !skin->drive_is_grabbed) - skin->drive_is_grabbed= 2; - if(drive_status!=BURN_DRIVE_IDLE && !skin->drive_is_busy) - skin->drive_is_busy= 2; - if(skin->verbosity>=Cdrskin_verbose_debuG) - ClN(fprintf(stderr,"cdrskin_debug: ABORT : Drive status: %d\n", - (int) drive_status)); - } - if(skin->verbosity>=Cdrskin_verbose_debuG) - ClN(fprintf(stderr, - "cdrskin_debug: ABORT : drive_is_grabbed=%d , drive_is_busy=%d (%X)\n", - skin->drive_is_grabbed,skin->drive_is_busy, - (unsigned int) skin->grabbed_drive)); - - if(skin->drive_is_grabbed) { - if(skin->drive_is_busy && skin->grabbed_drive!=NULL) { - if(drive_status==BURN_DRIVE_WRITING || drive_status==BURN_DRIVE_READING) { - fprintf(stderr,"cdrskin: ABORT : Trying to cancel drive operation.\n"); - burn_drive_cancel(skin->grabbed_drive); - } else if(drive_status==BURN_DRIVE_GRABBING) { - -#ifndef Cdrskin_oldfashioned_api_usE - int ret; - - fprintf(stderr, - "cdrskin: ABORT : Trying to close drive in process of grabbing\n"); - - /* >>> ??? rather inquire driveno from - skin->grabbed_drive->global_index ? */; - - ret= burn_drive_info_forget(&(skin->drives[skin->driveno]),1); - if(ret<=0) - fprintf(stderr, - "cdrskin: ABORT : Attempt to close drive failed (ret= %d)\n",ret); - else { - skin->drive_is_grabbed= 0; - skin->grabbed_drive= NULL; - goto try_to_finish_lib; - } - -#else - /* >>> what to do in this state ? */; -#endif /* Cdrskin_oldfashioned_api_usE */ - - } else if(drive_status!=BURN_DRIVE_IDLE) { - fprintf(stderr, - "cdrskin: ABORT : Will wait for current operation to end\n"); - } - if(drive_status!=BURN_DRIVE_IDLE) { - fprintf(stderr,"cdrskin: ABORT : Abort processing depends on speed and buffer size\n"); - fprintf(stderr,"cdrskin: ABORT : Usually it is done with 4x speed after about a MINUTE\n"); - fprintf(stderr,"cdrskin: URGE : But wait at least the normal burning time before any kill -9\n"); - } - last_time= start_time= Sfile_microtime(0); - while(1) { - drive_status= burn_drive_get_status(skin->grabbed_drive,&p); - if(drive_status==BURN_DRIVE_IDLE) - break; - usleep(wait_grain); - current_time= Sfile_microtime(0); - if(current_time-last_time>=1.0) { - if(first_status) - fprintf(stderr,"\n"); - first_status= 0; - fprintf(stderr,"\rcdrskin: ABORT : Status %d. Waiting for status %d since %d seconds (%d max)", - (int) drive_status, (int) BURN_DRIVE_IDLE, - (int) (current_time-start_time),skin->abort_max_wait); - last_time= current_time; - } - if(current_time-start_time>=skin->abort_max_wait) { - fprintf(stderr, - "\ncdrskin: ABORT : Cannot cancel burn session and release drive.\n"); - return(0); - } - } - fprintf(stderr,"\ncdrskin: ABORT : Status %d.\n",(int) drive_status); - } - fprintf(stderr,"cdrskin: ABORT : Trying to release drive.\n"); - Cdrskin_release_drive(skin,0); - } - -#ifndef Cdrskin_oldfashioned_api_usE -try_to_finish_lib:; -#endif - - if(skin->lib_is_initialized) { - fprintf(stderr,"cdrskin: ABORT : Trying to finish libburn.\n"); - burn_finish(); - } - -#endif /* ! Cdrskin_libburn_has_burn_aborT */ - - fprintf(stderr, - "cdrskin: ABORT : Drive is released and library is shut down now.\n"); - fprintf(stderr, - "cdrskin: ABORT : Program done. Even if you do not see a shell prompt.\n"); - return(1); -} - - -/** Convert a libburn device address into a libburn drive number - @return <=0 error, 1 success -*/ -int Cdrskin_driveno_of_location(struct CdrskiN *skin, char *devicename, - int *driveno, int flag) -{ - int i,ret; - char adr[Cdrskin_adrleN]; - - for(i=0;in_drives;i++) { - -#ifdef Cdrskin_libburn_has_drive_get_adR - ret= burn_drive_get_adr(&(skin->drives[i]), adr); - if(ret<=0) - continue; -#else - ret= 1; /* to please gcc -Wall */ - strcpy(adr,skin->drives[i].location); -#endif - - if(strcmp(adr,devicename)==0) { - *driveno= i; - return(1); - } - } - return(0); -} - - -/** Convert a cdrskin address into a libburn drive number - @return <=0 error, 1 success -*/ -int Cdrskin_dev_to_driveno(struct CdrskiN *skin, char *in_adr, int *driveno, - int flag) -{ - int ret; - char *adr,translated_adr[Cdrskin_adrleN],synthetic_adr[Cdrskin_adrleN]; - - adr= in_adr; - -#ifndef Cdrskin_extra_leaN - /* user defined address translation */ - ret= Cdradrtrn_translate(skin->adr_trn,adr,-1,translated_adr,0); - if(ret<=0) { - fprintf(stderr, - "cdrskin: FATAL : address translation failed (address too long ?) \n"); - return(0); - } - if(skin->verbosity>=Cdrskin_verbose_cmD && strcmp(adr,translated_adr)!=0) - printf("cdrskin: dev_translation=... : dev='%s' to dev='%s'\n", - adr,translated_adr); - adr= translated_adr; -#endif /* ! Cdrskin_extra_leaN */ - - if(strncmp(adr, "stdio:", 6)==0) { - if(skin->n_drives<=0) - goto wrong_devno; - *driveno= 0; - return(1); - } else if(adr[0]=='/') { - ret= Cdrskin_driveno_of_location(skin,adr,driveno,0); - if(ret<=0) { -location_not_found:; - fprintf(stderr, - "cdrskin: FATAL : cannot find '%s' among accessible drive devices.\n", - adr); - fprintf(stderr, - "cdrskin: HINT : use option --devices for a list of drive devices.\n"); - return(0); - } - return(1); - } - ret= Cdrpreskin__cdrecord_to_dev(adr,synthetic_adr,driveno, - !!skin->preskin->old_pseudo_scsi_adr); - if(ret<=0) { -wrong_devno:; - if(skin->n_drives<=0) { - fprintf(stderr,"cdrskin: FATAL : No accessible drives.\n"); - } else { - fprintf(stderr, - "cdrskin: FATAL : Address does not lead to an accessible drive: %s\n", - in_adr); - fprintf(stderr, - "cdrskin: HINT : dev= expects /dev/xyz, Bus,Target,0 or a number [0,%d]\n", - skin->n_drives-1); - } - return(0); - } - if(strlen(synthetic_adr)>0) { - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf("cdrskin: converted address '%s' to '%s'\n",adr,synthetic_adr)); - ret= Cdrskin_driveno_of_location(skin,synthetic_adr,driveno,0); - if(ret<=0) { - fprintf(stderr, - "cdrskin: failure while using address converted from '%s'\n",adr); - adr= synthetic_adr; - goto location_not_found; - } - } - if((*driveno)>=skin->n_drives || (*driveno)<0) { - ClN(fprintf(stderr,"cdrskin: obtained drive number %d from '%s'\n", - *driveno,adr)); - goto wrong_devno; - } - return(1); -} - - -/** Convert a libburn drive number into a cdrecord-style address which - represents a device address if possible and the drive number else. - @param flag Bitfield for control purposes: - bit0= do not apply user defined address translation - @return <0 error, - pseudo transport groups: - 0 volatile drive number, - 1 /dev/sgN, 2 /dev/hdX, 3 stdio, - 1000000+busno = non-pseudo SCSI bus - 2000000+busno = pseudo-ATA|ATAPI SCSI bus (currently busno==2) -*/ -int Cdrskin_driveno_to_btldev(struct CdrskiN *skin, int driveno, - char btldev[Cdrskin_adrleN], int flag) -{ - int k,ret,still_untranslated= 1,hret,k_start; - char *loc= NULL,buf[Cdrskin_adrleN],adr[Cdrskin_adrleN]; - - if(driveno<0 || driveno>skin->n_drives) - goto fallback; - -#ifdef Cdrskin_libburn_has_drive_get_adR - ret= burn_drive_get_adr(&(skin->drives[driveno]), adr); - if(ret<=0) - goto fallback; - loc= adr; -#else - adr[0]= 0; /* to please gcc -Wall */ - loc= skin->drives[driveno].location; - if(loc==NULL) - goto fallback; -#endif - -#ifdef Cdrskin_libburn_has_get_drive_rolE - ret= burn_drive_get_drive_role(skin->drives[driveno].drive); - if(ret!=1) { - sprintf(btldev,"stdio:%s",adr); - {ret= 2; goto adr_translation;} - } -#endif - -#ifdef Cdrskin_libburn_has_convert_scsi_adR - if(!skin->preskin->old_pseudo_scsi_adr) { - int host_no= -1,channel_no= -1,target_no= -1,lun_no= -1, bus_no= -1; - - ret= burn_drive_obtain_scsi_adr(loc,&bus_no,&host_no,&channel_no, - &target_no,&lun_no); - if(ret<=0) { - if(strncmp(loc,"/dev/hd",7)==0) - if(loc[7]>='a' && loc[7]<='z') - if(loc[8]==0) { - bus_no= (loc[7]-'a')/2; - sprintf(btldev,"%d,%d,0",bus_no,(loc[7]-'a')%2); - {ret= 2000000 + bus_no; goto adr_translation;} - } - goto fallback; - } else { - sprintf(btldev,"%d,%d,%d",bus_no,target_no,lun_no); - ret= 1000000+bus_no; - goto adr_translation; - } - } -#endif - - k_start= 0; - if(strncmp(loc,"/dev/sg",7)==0 || strncmp(loc,"/dev/sr",7)==0) - k_start= 7; - if(strncmp(loc,"/dev/scd",8)==0) - k_start= 8; - if(k_start>0) { - for(k= k_start;loc[k]!=0;k++) - if(loc[k]<'0' || loc[k]>'9') - break; - if(loc[k]==0 && k>k_start) { - sprintf(btldev,"1,%s,0",loc+k_start); - {ret= 1; goto adr_translation;} - } - } - if(strncmp(loc,"/dev/hd",7)==0) - if(loc[7]>='a' && loc[7]<='z') - if(loc[8]==0) { - sprintf(btldev,"2,%d,0",loc[7]-'a'); - {ret= 2; goto adr_translation;} - } -fallback:; - if(skin->preskin->old_pseudo_scsi_adr) { - sprintf(btldev,"0,%d,0",driveno); - } else { - if(loc!=NULL) - strcpy(btldev,loc); - else - sprintf(btldev,"%d",driveno); - } - ret= 0; - -adr_translation:; -#ifndef Cdrskin_extra_leaN - /* user defined address translation */ - if(!(flag&1)) { - if(ret>0) { - /* try whether a translation points to loc */ - hret= Cdradrtrn_translate(skin->adr_trn,loc,driveno,buf,1); - if(hret==2) { - still_untranslated= 0; - strcpy(btldev,buf); - } - } - if(still_untranslated) { - Cdradrtrn_translate(skin->adr_trn,btldev,driveno,buf,1); - strcpy(btldev,buf); - } - } -#endif /* ! Cdrskin_extra_leaN */ - - return(ret); -} - - -/** Read and buffer the start of an existing ISO-9660 image from - overwriteable target media. -*/ -int Cdrskin_overwriteable_iso_size(struct CdrskiN *skin, int *size, int flag) -{ -#ifdef Cdrskin_libburn_has_random_access_rW - int ret; - off_t data_count= 0; - double size_in_bytes; - char *buf; - - buf= skin->overwriteable_iso_head; - if(!skin->media_is_overwriteable) - {ret= 0; goto ex;} - /* Read first 64 kB */ - ret= burn_read_data(skin->grabbed_drive,(off_t) 0,buf,32*2048,&data_count,0); - if(ret<=0) - {ret= 0; goto ex;} - ret= Scan_for_iso_size((unsigned char *) (buf+16*2048), &size_in_bytes,0); - if(ret<=0) { - if(skin->verbosity>=Cdrskin_verbose_debuG) - ClN(fprintf(stderr,"cdrskin_debug: No detectable ISO-9660 size on media\n")); - {ret= 0; goto ex;} - } - if(skin->verbosity>=Cdrskin_verbose_debuG) - ClN(fprintf(stderr,"cdrskin_debug: detected ISO-9660 size : %.f (%fs)\n", - size_in_bytes, size_in_bytes/2048.0)); - if(size_in_bytes/2048.0>2147483647-1-16) { - fprintf(stderr, - "cdrskin: FATAL : ISO-9660 filesystem in terabyte size detected\n"); - {ret= 0; goto ex;} - } - *size= size_in_bytes/2048.0; - if(size_in_bytes-((double) *size)*2048.0>0.0) - (*size)++; - if((*size)%16) - *size+= 16-((*size)%16); - if(skin->grow_overwriteable_iso==1) - skin->grow_overwriteable_iso= 2; - ret= 1; -ex:; - return(ret); - -#else /* Cdrskin_libburn_has_random_access_rW */ - return(-1); -#endif -} - - -int Cdrskin_invalidate_iso_head(struct CdrskiN *skin, int flag) -{ - int ret; - int size; - - fprintf(stderr, - "cdrskin: blank=... : invalidating ISO-9660 head on overwriteable media\n"); - ret= Cdrskin_overwriteable_iso_size(skin,&size,0); - if(ret<=0) { - fprintf(stderr, - "cdrskin: NOTE : Not an ISO-9660 file system. Left unaltered.\n"); - return(2); - } - skin->overwriteable_iso_head[16*2048]= - skin->overwriteable_iso_head[16*2048+3]= - skin->overwriteable_iso_head[16*2048+4]= 'x'; - ret= burn_random_access_write(skin->grabbed_drive,(off_t) 16*2048, - skin->overwriteable_iso_head+16*2048, - (off_t) 16*2048,1); - return(ret); -} - - -/** Report media status s to the user - @param flag Bitfield for control purposes: - bit0= permission to check for overwriteable ISO image - bit1= do not report media profile - bit2= do not report but only check for pseudo appendable - @return 1=ok, 2=ok, is pseudo appendable, <=0 error -*/ -int Cdrskin_report_disc_status(struct CdrskiN *skin, enum burn_disc_status s, - int flag) -{ - int ret, iso_size, pseudo_appendable= 0; - - if(flag&1) { - if(skin->media_is_overwriteable && skin->grow_overwriteable_iso>0) { - if(skin->grow_overwriteable_iso==2) - ret= 1; - else - ret= Cdrskin_overwriteable_iso_size(skin,&iso_size,0); - if(ret>0) { - s= BURN_DISC_APPENDABLE; - pseudo_appendable= 1; - } - } - } - if(flag&4) - return(1+pseudo_appendable); - - printf("cdrskin: status %d ",s); - if(s==BURN_DISC_FULL) { - printf("burn_disc_full \"There is a disc with data on it in the drive\"\n"); - } else if(s==BURN_DISC_BLANK) { - printf("burn_disc_blank \"The drive holds a blank disc\"\n"); - } else if(s==BURN_DISC_APPENDABLE) { - printf( - "BURN_DISC_APPENDABLE \"There is an incomplete disc in the drive\"\n"); - } else if(s==BURN_DISC_EMPTY) { - printf("BURN_DISC_EMPTY \"There is no disc at all in the drive\"\n"); - } else if(s==BURN_DISC_UNREADY) { - printf("BURN_DISC_UNREADY \"The current status is not yet known\"\n"); - -#ifdef Cdrskin_libburn_has_burn_disc_unsuitablE - - } else if(s==BURN_DISC_UNGRABBED) { - printf("BURN_DISC_UNGRABBED \"API usage error: drive not grabbed\"\n"); - } else if(s==BURN_DISC_UNSUITABLE) { - printf("BURN_DISC_UNSUITABLE \"Media is not suitable\"\n"); - -#endif /* Cdrskin_libburn_has_burn_disc_unsuitablE */ - - } else - printf("-unknown status code-\n"); - - if(flag&2) - return(1+pseudo_appendable); - -#ifdef Cdrskin_libburn_has_get_profilE - if((s==BURN_DISC_FULL || s==BURN_DISC_APPENDABLE || s==BURN_DISC_BLANK || - s==BURN_DISC_UNSUITABLE) && skin->driveno>=0) { - char profile_name[80]; - int profile_number; - - printf("Current: "); - ret= burn_disc_get_profile(skin->drives[skin->driveno].drive, - &profile_number,profile_name); - if(ret>0 && profile_name[0]!=0) - printf("%s\n", profile_name); - else if(ret>0) - printf("UNSUITABLE MEDIA (Profile %4.4Xh)\n",profile_number); - else - printf("-unidentified-\n"); - } else if(s==BURN_DISC_EMPTY) { - printf("Current: none\n"); - } -#endif - - return(1+pseudo_appendable); -} - - -/** Perform operations -scanbus or --devices - @param flag Bitfield for control purposes: - bit0= perform --devices rather than -scanbus - @return <=0 error, 1 success -*/ -int Cdrskin_scanbus(struct CdrskiN *skin, int flag) -{ - int ret,i,busno,first_on_bus,pseudo_transport_group= 0,skipped_devices= 0; - int busmax= 16; - char shellsafe[5*Cdrskin_strleN+2],perms[40],btldev[Cdrskin_adrleN]; - char adr[Cdrskin_adrleN],*raw_dev,*drives_shown= NULL; - struct stat stbuf; - - drives_shown= malloc(skin->n_drives+1); - if(drives_shown==NULL) - {ret= -1; goto ex;} - for(i=0;in_drives;i++) - drives_shown[i]= 0; - if(flag&1) { - printf("cdrskin: Overview of accessible drives (%d found) :\n", - skin->n_drives); - printf("-----------------------------------------------------------------------------\n"); - for(i=0;in_drives;i++) { - -#ifdef Cdrskin_libburn_has_drive_get_adR - ret= burn_drive_get_adr(&(skin->drives[i]), adr); - if(ret<=0) { - /* >>> one should massively complain */; - continue; - } -#else - strcpy(adr,skin->drives[i].location); -#endif - - if(stat(adr,&stbuf)==-1) { - sprintf(perms,"errno=%d",errno); - } else { - strcpy(perms,"------"); - if(stbuf.st_mode&S_IRUSR) perms[0]= 'r'; - if(stbuf.st_mode&S_IWUSR) perms[1]= 'w'; - if(stbuf.st_mode&S_IRGRP) perms[2]= 'r'; - if(stbuf.st_mode&S_IWGRP) perms[3]= 'w'; - if(stbuf.st_mode&S_IROTH) perms[4]= 'r'; - if(stbuf.st_mode&S_IWOTH) perms[5]= 'w'; - } - if(strlen(adr)>=Cdrskin_strleN) - Text_shellsafe("failure:oversized string",shellsafe,0); - else - Text_shellsafe(adr,shellsafe,0); - printf("%d dev=%s %s : '%s' '%s'\n", - i,shellsafe,perms,skin->drives[i].vendor,skin->drives[i].product); - } - printf("-----------------------------------------------------------------------------\n"); - } else { - if(!skin->preskin->old_pseudo_scsi_adr) { - pseudo_transport_group= 1000000; - raw_dev= skin->preskin->raw_device_adr; - if(strncmp(raw_dev,"ATA",3)==0 && (raw_dev[3]==0 || raw_dev[3]==':')) - pseudo_transport_group= 2000000; - if(strncmp(raw_dev,"ATAPI",5)==0 && (raw_dev[5]==0 || raw_dev[5]==':')) - pseudo_transport_group= 2000000; - if(pseudo_transport_group==2000000) { - fprintf(stderr,"scsidev: 'ATA'\ndevname: 'ATA'\n"); - fprintf(stderr,"scsibus: -2 target: -2 lun: -2\n"); - } - } - /* >>> fprintf(stderr,"Linux sg driver version: 3.1.25\n"); */ - printf("Using libburn version '%s'.\n", Cdrskin_libburn_versioN); - if(pseudo_transport_group!=1000000) - if(skin->preskin->old_pseudo_scsi_adr) - printf("cdrskin: NOTE : The printed addresses are not cdrecord compatible !\n"); - - for(busno= 0;busno<=busmax;busno++) { - first_on_bus= 1; - for(i=0;in_drives;i++) { - ret= Cdrskin_driveno_to_btldev(skin,i,btldev,1); - if(busno==busmax && drives_shown[i]==0) { - if(ret/1000000 != pseudo_transport_group) { - skipped_devices++; - if(skin->verbosity>=Cdrskin_verbose_debuG) - ClN(fprintf(stderr,"cdrskin_debug: skipping drive '%s%s'\n", - ((ret/1000000)==2?"ATA:":""), btldev)); - continue; - } - } else if(ret != pseudo_transport_group + busno) - continue; - if(first_on_bus) - printf("scsibus%d:\n",busno); - first_on_bus= 0; - printf("\t%s\t %d) '%-8s' '%-16s' '%-4s' Removable CD-ROM\n", - btldev,i,skin->drives[i].vendor,skin->drives[i].product, - skin->drives[i].revision); - drives_shown[i]= 1; - } - } - } - if(skipped_devices>0) { - if(skipped_devices>1) - printf("cdrskin: NOTE : There were %d drives not shown.\n", - skipped_devices); - else - printf("cdrskin: NOTE : There was 1 drive not shown.\n"); - printf("cdrskin: HINT : To surely see all drives try option: --devices\n"); - if(pseudo_transport_group!=2000000) - printf("cdrskin: HINT : or try options: dev=ATA -scanbus\n"); - } - ret= 1; -ex:; - if(drives_shown!=NULL) - free((char *) drives_shown); - return(ret); -} - - -/** Perform -checkdrive . - @param flag Bitfield for control purposes: - bit0= do not print message about pseudo-checkdrive - @return <=0 error, 1 success -*/ -int Cdrskin_checkdrive(struct CdrskiN *skin, char *profile_name, int flag) -{ - struct burn_drive_info *drive_info; - int ret; - char btldev[Cdrskin_adrleN]; - - if(!(flag&1)) { - if(flag&2) - ClN(printf("cdrskin: pseudo-inquiry on drive %d\n",skin->driveno)); - else - ClN(printf("cdrskin: pseudo-checkdrive on drive %d\n",skin->driveno)); - } - if(skin->driveno>=skin->n_drives || skin->driveno<0) { - fprintf(stderr,"cdrskin: FATAL : there is no drive #%d\n",skin->driveno); - {ret= 0; goto ex;} - } - drive_info= &(skin->drives[skin->driveno]); - ret= Cdrskin_driveno_to_btldev(skin,skin->driveno,btldev,0); - if(ret>=0) - fprintf(stderr,"scsidev: '%s'\n",btldev); - printf("Device type : "); -#ifdef Cdrskin_libburn_has_get_drive_rolE - ret= burn_drive_get_drive_role(drive_info->drive); - if(ret==0) - printf("%s\n","Emulated (null-drive)"); - else if(ret==2) - printf("%s\n","Emulated (stdio-drive, 2k random read-write)"); - else if(ret==3) - printf("%s\n","Emulated (stdio-drive, sequential write-only)"); - else if(ret!=1) - printf("%s\n","Emulated (stdio-drive)"); - else -#endif - printf("%s\n","Removable CD-ROM"); - printf("Vendor_info : '%s'\n",drive_info->vendor); - printf("Identifikation : '%s'\n",drive_info->product); - printf("Revision : '%s'\n",drive_info->revision); - - if(flag&2) - {ret= 1; goto ex;} - - printf("Driver flags : %s\n","BURNFREE"); -#ifdef Cdrskin_allow_libburn_taO - - printf("Supported modes:"); - if((drive_info->tao_block_types & (BURN_BLOCK_MODE1)) - == (BURN_BLOCK_MODE1)) - printf(" TAO"); - if(drive_info->sao_block_types & BURN_BLOCK_SAO) - printf(" SAO"); - if((drive_info->raw_block_types & BURN_BLOCK_RAW96R) && - strstr(profile_name,"DVD")!=profile_name && - strstr(profile_name,"BD")!=profile_name) - printf(" RAW/RAW96R"); - printf("\n"); - -#else - printf("Supported modes: %s\n","SAO RAW/R96R"); -#endif - ret= 1; -ex:; - return(ret); -} - - -/** Predict address block number where the next write will go to - @param flag Bitfield for control purposes: - bit0= do not return nwa from eventual write_start_address - @return <=0 error, 1 nwa from drive , 2 nwa from write_start_address -*/ -int Cdrskin_obtain_nwa(struct CdrskiN *skin, int *nwa, int flag) -{ - int ret,lba; - struct burn_drive *drive; - struct burn_write_opts *o= NULL; - - if(skin->write_start_address>=0 && !(flag&1)) { - /* (There is no sense in combining random addressing with audio) */ - *nwa= skin->write_start_address/2048; - return(2); - } - - /* Set write opts in order to provoke MODE SELECT. LG GSA-4082B needs it. */ - drive= skin->drives[skin->driveno].drive; - o= burn_write_opts_new(drive); - if(o!=NULL) { - burn_write_opts_set_perform_opc(o, 0); - burn_write_opts_set_write_type(o,skin->write_type,skin->block_type); - burn_write_opts_set_underrun_proof(o,skin->burnfree); - } -#ifdef Cdrskin_libburn_has_multI - ret= burn_disc_track_lba_nwa(drive,o,0,&lba,nwa); -#else - ret= 0; - lba= 0;/* silence gcc warning */ -#endif - if(o!=NULL) - burn_write_opts_free(o); - return(ret); -} - - -/** Perform -toc under control of Cdrskin_atip(). - @param flag Bitfield for control purposes: - bit0= do not list sessions separately (do it cdrecord style) - @return <=0 error, 1 success -*/ -int Cdrskin_toc(struct CdrskiN *skin, int flag) -{ - int num_sessions= 0,num_tracks= 0,lba= 0,track_count= 0,total_tracks= 0; - int session_no, track_no, pmin, psec, pframe, ret; - struct burn_drive *drive; - struct burn_disc *disc= NULL; - struct burn_session **sessions; - struct burn_track **tracks; - struct burn_toc_entry toc_entry; - - drive= skin->drives[skin->driveno].drive; - - disc= burn_drive_get_disc(drive); - if(disc==NULL) { - if(skin->grow_overwriteable_iso>0) { - ret= Cdrskin_overwriteable_iso_size(skin,&lba,0); - if(ret>0) { - printf( -"first: 1 last 1 (fabricated from ISO-9660 image on overwriteable media)\n"); - printf( -"track: 1 lba: 0 ( 0) 00:02:00 adr: 1 control: 4 mode: 1\n"); - burn_lba_to_msf(lba, &pmin, &psec, &pframe); - printf("track:lout lba: %9d (%9d) %2.2d:%2.2d:%2.2d", - lba,4*lba,pmin,psec,pframe); - printf(" adr: 1 control: 4 mode: -1\n"); - return(1); - } - } - goto cannot_read; - } - sessions= burn_disc_get_sessions(disc,&num_sessions); - if(flag&1) { - for(session_no= 0; session_no>> From where does cdrecord take "mode" ? */ - - /* This is not the "mode" as printed by cdrecord : - printf(" mode: %d\n",burn_track_get_mode(tracks[track_no])); - */ - /* own guess: cdrecord says "1" on data and "0" on audio : */ - printf(" mode: %d\n",((toc_entry.control&7)<4?0:1)); - - } - if((flag&1) && session_nodriveno)); - ret= Cdrskin_grab_drive(skin,0); - if(ret<=0) - return(ret); - drive= skin->drives[skin->driveno].drive; - s= burn_disc_get_status(drive); - Cdrskin_report_disc_status(skin,s,1|2); - if(s==BURN_DISC_APPENDABLE && skin->no_blank_appendable) { - is_not_really_erasable= 1; - } else if(s==BURN_DISC_EMPTY) { - if(skin->verbosity>=Cdrskin_verbose_progresS) - printf("Current: none\n"); - ret= 0; goto ex; - } - - -#ifdef Cdrskin_atip_speed_brokeN - - /* <<< terrible stunt to get correct media speed info */ - if(skin->verbosity>=Cdrskin_verbose_debuG) - ClN(fprintf(stderr, - "cdrskin_debug: redoing startup for speed inquiry stabilization\n")); - - -#ifndef Cdrskin_oldfashioned_api_usE - - if(strlen(skin->preskin->device_adr)<=0) - burn_drive_get_adr(&(skin->drives[skin->driveno]), - skin->preskin->device_adr); - - Cdrskin_release_drive(skin,0); - burn_finish(); - if(!burn_initialize()) { - fflush(stdout); - fprintf(stderr,"cdrskin : FATAL : Re-initialization of libburn failed\n"); - {ret= 0; goto ex;} - } -#ifdef Cdrskin_libburn_has_allow_untested_profileS - burn_allow_untested_profiles(!!skin->preskin->allow_untested_media); -#endif - ret= Cdrskin_grab_drive(skin,1); /* uses burn_drive_scan_and_grab() */ - if(ret<=0) - return(ret); - drive= skin->drives[skin->driveno].drive; - -#else /* ! Cdrskin_oldfashioned_api_usE */ - - Cdrskin_release_drive(skin,0); - burn_finish(); - if(!burn_initialize()) { - fflush(stdout); - fprintf(stderr,"cdrskin : FATAL : Re-initialization of libburn failed\n"); - {ret= 0; goto ex;} - } -#ifdef Cdrskin_libburn_has_allow_untested_profileS - burn_allow_untested_profiles(!!skin->preskin->allow_untested_media); -#endif - if(strlen(skin->preskin->device_adr)>0) - burn_drive_add_whitelist(skin->preskin->device_adr); - while(!burn_drive_scan(&(skin->drives),&(skin->n_drives))) - usleep(1002); - ret= Cdrskin_grab_drive(skin,0); - if(ret<=0) - return(ret); - drive= skin->drives[skin->driveno].drive; - -#endif /* Cdrskin_oldfashioned_api_usE */ - -#endif /* Cdrskin_atip_speed_brokeN */ - - profile_name[0]= 0; -#ifdef Cdrskin_libburn_has_get_profilE - ret= burn_disc_get_profile(drive,&profile_number,profile_name); - if(ret<=0) { - profile_number= 0; - strcpy(profile_name, "-unidentified-"); - } -#endif /* Cdrskin_libburn_has_get_profilE */ - - ret= Cdrskin_checkdrive(skin,profile_name,1); - if(ret<=0) - return(ret); - -#ifdef Cdrskin_libburn_has_read_atiP - if(burn_disc_get_status(drive) != BURN_DISC_UNSUITABLE) { - ret= burn_disc_read_atip(drive); - if(ret>0) { - ret= burn_drive_get_min_write_speed(drive); - x_speed_min= ((double) ret)/Cdrskin_libburn_speed_factoR; - } - } -#endif - -#ifdef Cdrskin_libburn_has_burn_disc_unsuitablE - if(burn_disc_get_status(drive) == BURN_DISC_UNSUITABLE) { - if(skin->verbosity>=Cdrskin_verbose_progresS) { -#ifdef Cdrskin_libburn_has_get_profilE - if(profile_name[0]) - printf("Current: %s\n",profile_name); - else - printf("Current: UNSUITABLE MEDIA (Profile %4.4Xh)\n",profile_number); -#else - printf("Current: UNSUITABLE MEDIA\n"); -#endif - } - {ret= 0; goto ex;} - } -#endif /* Cdrskin_libburn_has_burn_disc_unsuitablE */ - - ret= burn_drive_get_write_speed(drive); - x_speed_max= ((double) ret)/Cdrskin_libburn_speed_factoR; - if(x_speed_min<0) - x_speed_min= x_speed_max; - printf("cdrskin: burn_drive_get_write_speed = %d (%.1fx)\n",ret,x_speed_max); - if(skin->verbosity>=Cdrskin_verbose_progresS) { - if(profile_name[0]) - printf("Current: %s\n",profile_name); - else if(burn_disc_erasable(drive)) - printf("Current: CD-RW\n"); - else - printf("Current: CD-R\n"); - } - if(strstr(profile_name,"DVD")==profile_name) { - /* These are dummy messages for project scdbackup, so its media recognition - gets a hint that the media is suitable and not in need of blanking. - scdbackup will learn to interpret cdrskin's DVD messages but the - current stable version needs to believe it is talking to its own - growisofs_wrapper. So this is an emulation of an emulator. - */ - printf("book type: %s (emulated booktype)\n", profile_name); - if(profile_number==0x13) /* DVD-RW */ - printf("cdrskin: message for sdvdbackup: \"(growisofs mode Restricted Overwrite)\"\n"); - } else if(strstr(profile_name,"BD")==profile_name) { - printf("Mounted Media: %2.2Xh, %s\n", profile_number, profile_name); - } else { - printf("ATIP info from disk:\n"); - if(burn_disc_erasable(drive)) { - if(is_not_really_erasable) - printf(" Is erasable (but not while in this incomplete state)\n"); - else - printf(" Is erasable\n"); - } else { - printf(" Is not erasable\n"); - } - -#ifdef Cdrskin_libburn_has_get_start_end_lbA - { int start_lba,end_lba,min,sec,fr; - ret= burn_drive_get_start_end_lba(drive,&start_lba,&end_lba,0); - if(ret>0) { - burn_lba_to_msf(start_lba,&min,&sec,&fr); - printf(" ATIP start of lead in: %d (%-2.2d:%-2.2d/%-2.2d)\n", - start_lba,min,sec,fr); - burn_lba_to_msf(end_lba,&min,&sec,&fr); - printf(" ATIP start of lead out: %d (%-2.2d:%-2.2d/%-2.2d)\n", - end_lba,min,sec,fr); - } - } -#endif /* Cdrskin_libburn_has_get_start_end_lbA */ - - printf(" 1T speed low: %.f 1T speed high: %.f\n",x_speed_min,x_speed_max); - } - - ret= 1; - if(flag&1) - Cdrskin_toc(skin,1);/*cdrecord seems to ignore -toc errors if -atip is ok */ -ex:; - Cdrskin_release_drive(skin,0); - - /* A61227 : - A kindof race condition with -atip on filled CD-RW and following grabs - under SuSE 9.3. Waiting seems to help. I suspect the media demon. */ - usleep(200000); - - return(ret); -} - - -/** Perform --list_formats - @param flag Bitfield for control purposes: - @return <=0 error, 1 success -*/ -int Cdrskin_list_formats(struct CdrskiN *skin, int flag) -{ - struct burn_drive *drive; - int ret, i, status, num_formats, profile_no, type; - off_t size; - unsigned dummy; - char status_text[80], profile_name[90]; - -#ifdef Cdrskin_libburn_has_burn_disc_formaT - - ret= Cdrskin_grab_drive(skin,0); - if(ret<=0) - return(ret); - drive= skin->drives[skin->driveno].drive; - - ret = burn_disc_get_formats(drive, &status, &size, &dummy, - &num_formats); - if(ret <= 0) { - fprintf(stderr, "cdrskin: SORRY: Cannot obtain format list info\n"); - ret= 2; goto ex; - } - ret= burn_disc_get_profile(drive, &profile_no, profile_name); - printf("Media current: "); - if(profile_no > 0 && ret > 0) { - if(profile_name[0]) - printf("%s\n", profile_name); - else - printf("%4.4Xh\n", profile_no); - } else - printf("is not recognizable\n"); - - if(status == BURN_FORMAT_IS_UNFORMATTED) - sprintf(status_text, "unformatted, up to %.1f MiB", - ((double) size) / 1024.0 / 1024.0); - else if(status == BURN_FORMAT_IS_FORMATTED) { - if(profile_no==0x12 || profile_no==0x13 || profile_no==0x1a || - profile_no==0x43) - sprintf(status_text, "formatted, with %.1f MiB", - ((double) size) / 1024.0 / 1024.0); - else - sprintf(status_text, "written, with %.1f MiB", - ((double) size) / 1024.0 / 1024.0); - } else if(status == BURN_FORMAT_IS_UNKNOWN) { - if (profile_no > 0) - sprintf(status_text, "intermediate or unknown"); - else - sprintf(status_text, "no media or unknown media"); - } else - sprintf(status_text, "illegal status according to MMC-5"); - printf("Format status: %s\n", status_text); - - for (i = 0; i < num_formats; i++) { - ret= burn_disc_get_format_descr(drive, i, &type, &size, &dummy); - if (ret <= 0) - continue; - printf("Format idx %-2d: %2.2Xh , %.fs , %.1f MiB\n", - i, type, ((double) size) / 2048.0, ((double) size) / 1024.0/1024.0); - } - ret= 1; -ex:; - Cdrskin_release_drive(skin,0); - return(ret); - -#else /* Cdrskin_libburn_has_burn_disc_formaT */ - - fprintf(stderr, - "cdrskin: SORRY: libburn is too old to obtain format list info\n"); - return(2); - -#endif /* Cdrskin_libburn_has_burn_disc_formaT */ -} - - -#ifndef Cdrskin_extra_leaN - -/* A70324: proposal by Eduard Bloch */ -int Cdrskin_warn_of_mini_tsize(struct CdrskiN *skin, int flag) -{ - off_t media_space= 0; - enum burn_disc_status s; - struct burn_drive *drive; - -#ifdef Cdrskin_libburn_has_get_spacE - if(skin->multi || skin->has_open_ended_track || skin->smallest_tsize<0) - return(1); - drive= skin->drives[skin->driveno].drive; - s= burn_disc_get_status(drive); - if(s!=BURN_DISC_BLANK) - return(1); - media_space= burn_disc_available_space(drive, NULL); - if(media_space<=0 || - skin->smallest_tsize >= media_space / Cdrskin_minimum_tsize_quotienT) - return(1); - fprintf(stderr,"\n"); - fprintf(stderr,"\n"); - fprintf(stderr, - "cdrskin: WARNING: Very small track size set by option tsize=\n"); - fprintf(stderr, - "cdrskin: Track size %.1f MB <-> media capacity %.1f MB\n", - skin->smallest_tsize/1024.0/1024.0, - ((double) media_space)/1024.0/1024.0); - fprintf(stderr,"\n"); - fprintf(stderr, - "cdrskin: Will wait at least 15 seconds until real burning starts\n"); - fprintf(stderr,"\n"); - if(skin->gracetime<15) - skin->gracetime= 15; - -#endif /* Cdrskin_libburn_has_get_spacE */ - return(1); -} - - -/** Emulate the gracetime= behavior of cdrecord - @param flag Bitfield for control purposes: - bit0= do not print message about pseudo-checkdrive -*/ -int Cdrskin_wait_before_action(struct CdrskiN *skin, int flag) -/* flag: bit0= BLANK rather than write mode - bit1= FORMAT rather than write mode -*/ -{ - int i; - - Cdrskin_warn_of_mini_tsize(skin,0); - - if(skin->verbosity>=Cdrskin_verbose_progresS) { - char speed_text[80]; - if(skin->x_speed<0) - strcpy(speed_text,"MAX"); - else if(skin->x_speed==0) - strcpy(speed_text,"MIN"); - else - sprintf(speed_text,"%.f",skin->x_speed); - printf( - "Starting to write CD/DVD at speed %s in %s %s mode for %s session.\n", - speed_text,(skin->dummy_mode?"dummy":"real"), - (flag&2?"FORMAT":(flag&1?"BLANK":skin->preskin->write_mode_name)), - (skin->multi?"multi":"single")); - printf("Last chance to quit, starting real write in %3d seconds.", - skin->gracetime); - fflush(stdout); - } - for(i= skin->gracetime-1;i>=0;i--) { - usleep(1000000); - if(skin->verbosity>=Cdrskin_verbose_progresS) { - printf("\b\b\b\b\b\b\b\b\b\b\b\b\b %3d seconds.",i); - fflush(stdout); - } - } - if(skin->verbosity>=Cdrskin_verbose_progresS) - {printf(" Operation starts.\n");fflush(stdout);} - return(1); -} - -#endif /* Cdrskin_extra_leaN */ - - -/** Perform blank=[all|fast] - @return <=0 error, 1 success -*/ -int Cdrskin_blank(struct CdrskiN *skin, int flag) -{ - enum burn_disc_status s; - struct burn_progress p; - struct burn_drive *drive; - int ret,loop_counter= 0,hint_force= 0,do_format= 0, profile_number= -1; - int wrote_well= 1, format_flag= 0, status, num_formats; - off_t size; - unsigned dummy; - double start_time; - char *verb= "blank", *presperf="blanking", *fmt_text= "..."; - char profile_name[80]; - static char fmtp[][40]= { - "...", "format_overwrite", "deformat_sequential", - "(-format)", "format_defectmgt", "format_by_index", - "format_if_needed", "as_needed"}; - static int fmtp_max= 7; - - start_time= Sfile_microtime(0); /* will be refreshed later */ - ret= Cdrskin_grab_drive(skin,0); - if(ret<=0) - return(ret); - drive= skin->drives[skin->driveno].drive; - s= burn_disc_get_status(drive); - profile_name[0]= 0; -#ifdef Cdrskin_libburn_has_get_profilE - if(skin->grabbed_drive) - burn_disc_get_profile(skin->grabbed_drive,&profile_number,profile_name); -#endif - - ret= Cdrskin_report_disc_status(skin,s, - 1|(4*!(skin->verbosity>=Cdrskin_verbose_progresS))); - if(ret==2) - s= BURN_DISC_APPENDABLE; - do_format= skin->blank_format_type & 0xff; - -#ifdef Cdrskin_libburn_has_pretend_fulL - if(s==BURN_DISC_UNSUITABLE) { - if(skin->force_is_set) { - ClN(fprintf(stderr,"cdrskin: NOTE : -force blank=... : Treating unsuitable media as burn_disc_full\n")); - ret= burn_disc_pretend_full(drive); - s= burn_disc_get_status(drive); - } else - hint_force= 1; - } -#endif /* Cdrskin_libburn_has_pretend_fulL */ - - if(do_format) - if(do_format>=0 && do_format<=fmtp_max) - fmt_text= fmtp[do_format]; - if(do_format==5) { /* format_by_index */ - if(profile_number == 0x12 || profile_number == 0x43) - do_format= 4; - else - do_format= 1; - } else if(do_format==6 || do_format==7) { /* format_if_needed , if_needed */ - /* Find out whether format is needed at all. - Eventuelly set up a suitable formatting run - */ - if(profile_number == 0x14 && do_format==6) { /* sequential DVD-RW */ - do_format= 1; - skin->blank_format_type= 1|(1<<8); - skin->blank_format_size= 128*1024*1024; - } else if(profile_number == 0x12 || - profile_number == 0x43) { /* DVD-RAM , BD-RE */; -#ifdef Cdrskin_libburn_has_burn_disc_formaT - ret= burn_disc_get_formats(drive, &status, &size, &dummy, &num_formats); - if(ret>0 && status!=BURN_FORMAT_IS_FORMATTED) { - do_format= 4; - skin->blank_format_type= 4|(3<<9); /* default payload size */ - skin->blank_format_size= 0; - } -#endif - } else if(do_format==7) { /* try to blank what is not blank yet */ - if(s!=BURN_DISC_BLANK) { - do_format= 0; - skin->blank_fast= 1; - } - } - if(do_format==6 || do_format==7) { - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(fprintf(stderr, - "cdrskin: NOTE : blank=%s : no need for action detected\n", fmt_text)); - {ret= 2; goto ex;} - } - } - - if(do_format == 1 || do_format == 3 || do_format == 4) { - verb= "format"; - presperf= "formatting"; - } - if(do_format==2) { - /* Forceful blanking to Sequential Recording for DVD-R[W] and CD-RW */ - - if(!(profile_number == 0x14 || profile_number == 0x13 || - profile_number == 0x0a)) { - if(skin->grow_overwriteable_iso>0 && skin->media_is_overwriteable) - goto pseudo_blank_ov; - else - goto unsupported_format_type; - } - - } else if(do_format==1 || do_format==3) { - /* Formatting to become overwriteable for DVD-RW and DVD+RW */ - - if(do_format==3 && profile_number != 0x1a) { - fprintf(stderr, "cdrskin: SORRY : -format does DVD+RW only\n"); - if(profile_number==0x14) - fprintf(stderr, - "cdrskin: HINT : blank=format_overwrite would format this media\n"); - {ret= 0; goto ex;} - } - - if(profile_number == 0x14) { /* DVD-RW sequential */ - /* ok */; - } else if(profile_number == 0x13) { /* DVD-RW restricted overwrite */ - if(!(skin->force_is_set || ((skin->blank_format_type>>8)&4))) { - fprintf(stderr, - "cdrskin: NOTE : blank=format_... : media is already formatted\n"); - fprintf(stderr, - "cdrskin: HINT : If you really want to re-format, add option -force\n"); - {ret= 2; goto ex;} - } - } else if(profile_number == 0x1a) { /* DVD+RW */ - if(!((skin->blank_format_type>>8)&4)) { - fprintf(stderr, - "cdrskin: NOTE : blank=format_... : DVD+RW do not need this\n"); - fprintf(stderr, - "cdrskin: HINT : For de-icing use option blank=format_overwrite_full\n"); - {ret= 2; goto ex;} - } - } else { - fprintf(stderr, - "cdrskin: SORRY : blank=%s for now does DVD-RW and DVD+RW only\n", - fmt_text); - {ret= 0; goto ex;} - } - if(s==BURN_DISC_UNSUITABLE) - fprintf(stderr, - "cdrskin: NOTE : blank=%s accepted not yet suitable media\n", - fmt_text); - - } else if(do_format==4) { - /* Formatting and influencing defect management of DVD-RAM , BD-RE */ - if(!(profile_number == 0x12 || profile_number == 0x43)) { - fprintf(stderr, - "cdrskin: SORRY : blank=%s for now does DVD-RAM and BD-RE only\n", - fmt_text); - {ret= 0; goto ex;} - } - if(s==BURN_DISC_UNSUITABLE) - fprintf(stderr, - "cdrskin: NOTE : blank=%s accepted not yet suitable media\n", - fmt_text); - - } else if(do_format==0) { - /* Classical blanking of erasable media */ - - if(skin->grow_overwriteable_iso>0 && skin->media_is_overwriteable) { -pseudo_blank_ov:; - if(skin->dummy_mode) { - fprintf(stderr, - "cdrskin: would have begun to pseudo-blank disc if not in -dummy mode\n"); - goto blanking_done; - } - skin->grow_overwriteable_iso= 3; - ret= Cdrskin_invalidate_iso_head(skin, 0); - if(ret<=0) - goto ex; - goto blanking_done; - } else if(s!=BURN_DISC_FULL && - (s!=BURN_DISC_APPENDABLE || skin->no_blank_appendable) && - (profile_number!=0x13 || !skin->prodvd_cli_compatible) && - (s!=BURN_DISC_BLANK || !skin->force_is_set)) { - Cdrskin_release_drive(skin,0); - if(s==BURN_DISC_BLANK) { - fprintf(stderr, - "cdrskin: NOTE : blank=... : media was already blank (and still is)\n"); - {ret= 2; goto ex;} - } else if(s==BURN_DISC_APPENDABLE) { - fprintf(stderr, - "cdrskin: FATAL : blank=... : media is still appendable\n"); - } else { - fprintf(stderr, - "cdrskin: FATAL : blank=... : no blankworthy disc found\n"); - if(hint_force) - fprintf(stderr, - "cdrskin: HINT : If you are certain to have a CD-RW, try option -force\n"); - } - {ret= 0; goto ex;} - } - if(!burn_disc_erasable(drive)) { - fprintf(stderr,"cdrskin: FATAL : blank=... : media is not erasable\n"); - {ret= 0; goto ex;} - } - if((profile_number == 0x14 || profile_number == 0x13) && - !skin->prodvd_cli_compatible) - skin->blank_fast= 0; /* only with deformat_sequential_quickest */ - - } else { -unsupported_format_type:; - fprintf(stderr, - "cdrskin: SORRY : blank=%s is unsupported with media type %s\n", - fmt_text, profile_name); - {ret= 0; goto ex;} - } - - if(skin->dummy_mode) { - fprintf(stderr, - "cdrskin: would have begun to %s disc if not in -dummy mode\n", - verb); - goto blanking_done; - } - fprintf(stderr,"cdrskin: beginning to %s disc\n",verb); - Cdrskin_adjust_speed(skin,0); - -#ifndef Cdrskin_extra_leaN - Cdrskin_wait_before_action(skin, - 1+(do_format==1 || do_format==3 || do_format==4)); -#endif /* ! Cdrskin_extra_leaN */ - - skin->drive_is_busy= 1; - if(do_format==0 || do_format==2) { - burn_disc_erase(drive,skin->blank_fast); - -#ifdef Cdrskin_libburn_has_burn_disc_formaT - } else if(do_format==1 || do_format==3 || do_format==4) { - format_flag= (skin->blank_format_type>>8)&(1|2|4|32|128); - if(skin->force_is_set) - format_flag|= 16; - if(format_flag&128) - format_flag|= (skin->blank_format_index&255)<<8; - if(skin->blank_format_no_certify) - format_flag|= 64; - burn_disc_format(drive,(off_t) skin->blank_format_size,format_flag); -#endif - - } else { - fprintf(stderr,"cdrskin: SORRY : Format type %d not implemented yet.\n", - do_format); - ret= 0; goto ex; - } - - loop_counter= 0; - start_time= Sfile_microtime(0); - while(burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) { - if(loop_counter>0) - if(skin->verbosity>=Cdrskin_verbose_progresS) { - double percent= 50.0; - - if(p.sectors>0) /* i want a display of 1 to 99 percent */ - percent= 1.0+((double) p.sector+1.0)/((double) p.sectors)*98.0; - fprintf(stderr, - "\rcdrskin: %s ( done %.1f%% , %lu seconds elapsed ) ", - presperf,percent,(unsigned long) (Sfile_microtime(0)-start_time)); - } - sleep(1); - loop_counter++; - } -blanking_done:; -#ifdef Cdrskin_libburn_has_wrote_welL - wrote_well = burn_drive_wrote_well(drive); -#endif - if(wrote_well && skin->verbosity>=Cdrskin_verbose_progresS) { - fprintf(stderr, - "\rcdrskin: %s done \n", - presperf); - printf("%s time: %.3fs\n", - (do_format==1 || do_format==3 || do_format==4 ? - "Formatting":"Blanking"), - Sfile_microtime(0)-start_time); - } - fflush(stdout); - if(!wrote_well) - fprintf(stderr, - "\rcdrskin: %s failed \n", - presperf); - ret= !!(wrote_well); -ex:; - skin->drive_is_busy= 0; - if(skin->drive_is_grabbed) - Cdrskin_release_drive(skin,0); - return(ret); -} - - -/** Report burn progress. This is done partially in cdrecord style. - Actual reporting happens only if write progress hit the next MB or if in - non-write-progress states a second has elapsed since the last report. - After an actual report a new statistics interval begins. - @param drive_status As obtained from burn_drive_get_status() - @param p Progress information from burn_drive_get_status() - @param start_time Timestamp of burn start in seconds - @param last_time Timestamp of report interval start in seconds - @param total_count Returns the total number of bytes written so far - @param total_count Returns the number of bytes written during interval - @param flag Bitfield for control purposes: - bit0= report in growisofs style rather than cdrecord style - @return <=0 error, 1 seems to be writing payload, 2 doing something else -*/ -int Cdrskin_burn_pacifier(struct CdrskiN *skin, - enum burn_drive_status drive_status, - struct burn_progress *p, - double start_time, double *last_time, - double *total_count, double *last_count, - int *min_buffer_fill, int flag) -/* - bit0= growisofs style -*/ -{ - double bytes_to_write,written_bytes= 0.0,written_total_bytes= 0.0,buffer_size; - double fixed_size,padding,sector_size,speed_factor; - double measured_total_speed,measured_speed; - double elapsed_time,elapsed_total_time,current_time; - double estim_time,estim_minutes,estim_seconds,percent; - int ret,fifo_percent,fill,space,advance_interval=0,new_mb,old_mb,time_to_tell; - int fs,bs,old_track_idx,buffer_fill,formatting= 0,use_data_image_size; - char fifo_text[80],mb_text[40]; - char *debug_mark= ""; /* use this to prepend a marker text for experiments */ - - /* for debugging */ - static double last_fifo_in= 0.0,last_fifo_out= 0.0,curr_fifo_in,curr_fifo_out; - - current_time= Sfile_microtime(0); - elapsed_total_time= current_time-start_time; - elapsed_time= current_time-*last_time; - time_to_tell= (elapsed_time>=1.0)&&(elapsed_total_time>=1.0); - written_total_bytes= *last_count; /* to be overwritten by p.sector */ - -#ifdef Cdrskin_libburn_has_bd_formattinG - if(drive_status==BURN_DRIVE_FORMATTING) - formatting= 1; -#endif - - if(drive_status==BURN_DRIVE_WRITING) { - ; - } else if(drive_status==BURN_DRIVE_WRITING_LEADIN - -#ifdef Cdrskin_allow_libburn_taO - || drive_status==BURN_DRIVE_WRITING_PREGAP -#endif - || formatting) { - if(time_to_tell || skin->is_writing) { - if(skin->verbosity>=Cdrskin_verbose_progresS) { - if(skin->is_writing) - fprintf(stderr,"\n"); - fprintf(stderr, - "\rcdrskin: %s (burning since %.f seconds) ", - (formatting?"formatting":"working pre-track"), elapsed_total_time); - } - skin->is_writing= 0; - advance_interval= 1; - } - {ret= 2; goto ex;} - } else if(drive_status==BURN_DRIVE_WRITING_LEADOUT - -#ifdef Cdrskin_allow_libburn_taO - || drive_status==BURN_DRIVE_CLOSING_TRACK - || drive_status==BURN_DRIVE_CLOSING_SESSION -#endif - - ) { - -#ifdef Cdrskin_allow_libburn_taO - if(drive_status==BURN_DRIVE_CLOSING_SESSION && - skin->previous_drive_status!=drive_status) - {printf("\nFixating...\n"); fflush(stdout);} -#endif - - if(time_to_tell || skin->is_writing) { - if(skin->verbosity>=Cdrskin_verbose_progresS) { - if(skin->is_writing) - fprintf(stderr,"\n"); - fprintf(stderr, - "\rcdrskin: working post-track (burning since %.f seconds) ", - elapsed_total_time); - } - skin->is_writing= 0; - advance_interval= 1; - } - {ret= 2; goto ex;} - } else - goto thank_you_for_patience; - - old_track_idx= skin->supposed_track_idx; -#ifdef Cdrskin_progress_track_brokeN - /* with libburn.0.2 there is always reported 0 as p->track */ - if(written_bytes<0) { /* track hop ? */ - if(skin->supposed_track_idx+1track_counter) - skin->supposed_track_idx++; - } - /* >>> ask eventual fifo about writing fd */; - if(p->track>0) - skin->supposed_track_idx= p->track; -#else /* Cdrskin_progress_track_brokeN */ - skin->supposed_track_idx= p->track; -#endif /* ! Cdrskin_progress_track_brokeN */ - - if(old_track_idx>=0 && old_track_idxsupposed_track_idx) { - Cdrtrack_get_size(skin->tracklist[old_track_idx],&fixed_size,&padding, - §or_size,&use_data_image_size,1); - if(skin->verbosity>=Cdrskin_verbose_progresS) - printf("\n"); - printf("%sTrack %-2.2d: Total bytes read/written: %.f/%.f (%.f sectors).\n", - debug_mark,old_track_idx+1,fixed_size,fixed_size+padding, - (fixed_size+padding)/sector_size); - } - - sector_size= 2048.0; - if(skin->supposed_track_idx>=0 && - skin->supposed_track_idxtrack_counter) - Cdrtrack_get_size(skin->tracklist[skin->supposed_track_idx],&fixed_size, - &padding,§or_size,&use_data_image_size,0); - - bytes_to_write= ((double) p->sectors)*sector_size; - written_total_bytes= ((double) p->sector)*sector_size; - written_bytes= written_total_bytes-*last_count; - if(written_total_bytes<1024*1024) { -thank_you_for_patience:; - if(time_to_tell || (skin->is_writing && elapsed_total_time>=1.0)) { - if(skin->verbosity>=Cdrskin_verbose_progresS) { - if(skin->is_writing) - fprintf(stderr,"\n"); - fprintf(stderr, - "\rcdrskin: thank you for being patient since %.f seconds ", - elapsed_total_time); - } - advance_interval= 1; - } - skin->is_writing= 0; - {ret= 2; goto ex;} - } - new_mb= written_total_bytes/(1024*1024); - old_mb= (*last_count)/(1024*1024); - if(new_mb==old_mb && !(written_total_bytes>=skin->fixed_size && - skin->fixed_size>0 && time_to_tell)) - {ret= 1; goto ex;} - - -#ifndef Cdrskin_extra_leaN - - percent= 0.0; - if(bytes_to_write>0) - percent= written_total_bytes/bytes_to_write*100.0; - measured_total_speed= 0.0; - measured_speed= 0.0; - estim_time= -1.0; - estim_minutes= -1.0; - estim_seconds= -1.0; - if(elapsed_total_time>0.0) { - measured_total_speed= written_total_bytes/elapsed_total_time; - estim_time= (bytes_to_write-written_bytes)/measured_total_speed; - if(estim_time>0.0 && estim_time<86400.0) { - estim_minutes= ((int) estim_time)/60; - estim_seconds= estim_time-estim_minutes*60.0; - if(estim_seconds<0.0) - estim_seconds= 0.0; - } - } - if(written_bytes==written_total_bytes && elapsed_total_time>0) { - measured_speed= measured_total_speed; - } else if(elapsed_time>0.0) - measured_speed= written_bytes/elapsed_time; - else if(written_bytes>0.0) - measured_speed= 99.91*Cdrskin_speed_factoR; - - if(measured_speed<=0.0 && written_total_bytes>=skin->fixed_size && - skin->fixed_size>0) { - if(!skin->is_writing) - goto thank_you_for_patience; - skin->is_writing= 0; - measured_speed= measured_total_speed; - } else - skin->is_writing= 1; - if(skin->supposed_track_idx<0) - skin->supposed_track_idx= 0; - if(*last_count<=0.0) - printf("%-78.78s\r",""); - if(skin->verbosity>=Cdrskin_verbose_progresS) { - if(flag&1) { - printf("%.f/%.f (%2.1f%%) @%1.1f, remaining %.f:%2.2d\n", - written_total_bytes,bytes_to_write,percent, - measured_speed/Cdrskin_speed_factoR, - estim_minutes,(int) estim_seconds); - } else { - fill= 0; - fifo_percent= 50; - fifo_text[0]= 0; - curr_fifo_in= last_fifo_in; - curr_fifo_out= last_fifo_out; - if(skin->fifo!=NULL) { - ret= Cdrfifo_get_buffer_state(skin->fifo,&fill,&space,0); - buffer_size= fill+space; - if(ret==2 || ret==0) { - fifo_percent= 100; - } else if(ret>0 && buffer_size>0.0) { - /* obtain minimum fill of pacifier interval */ - Cdrfifo_next_interval(skin->fifo,&fill,0); - fifo_percent= 100.0*((double) fill)/buffer_size; - if(fifo_percent<100 && fill>0) - fifo_percent++; - } - if(skin->verbosity>=Cdrskin_verbose_debuG) { - Cdrfifo_get_counters(skin->fifo,&curr_fifo_in,&curr_fifo_out,0); - Cdrfifo_get_sizes(skin->fifo,&bs,&fs,0); - } - if(skin->fifo_size>0) { - sprintf(fifo_text,"(fifo %3d%%) ",fifo_percent); - if(skin->verbosity>=Cdrskin_verbose_debug_fifO) { - fprintf(stderr, - "\ncdrskin_debug: fifo >= %9d / %d : %8.f in, %8.f out\n", - fill,(int) buffer_size, - curr_fifo_in-last_fifo_in,curr_fifo_out-last_fifo_out); - last_fifo_in= curr_fifo_in; - last_fifo_out= curr_fifo_out; - } - } - } - if(skin->supposed_track_idx >= 0 && - skin->supposed_track_idx < skin->track_counter) { - /* fixed_size,padding are fetched above via Cdrtrack_get_size() */; - } else if(skin->fixed_size!=0) { - fixed_size= skin->fixed_size; - padding= skin->padding; - } - if(fixed_size || (skin->fill_up_media && - skin->supposed_track_idx==skin->track_counter-1)) { - sprintf(mb_text,"%4d of %4d",(int) (written_total_bytes/1024.0/1024.0), - (int) ((double) Cdrtrack_get_sectors( - skin->tracklist[skin->supposed_track_idx],0)* - sector_size/1024.0/1024.0)); - } else - sprintf(mb_text,"%4d",(int) (written_total_bytes/1024.0/1024.0)); - speed_factor= Cdrskin_speed_factoR*sector_size/2048; - - buffer_fill= 50; -#ifdef Cdrskin_libburn_has_buffer_progresS - if(p->buffer_capacity>0) - buffer_fill= (double) (p->buffer_capacity - p->buffer_available)*100.0 - / (double) p->buffer_capacity; - -#endif /* Cdrskin_libburn_has_buffer_progresS */ - if(buffer_fill<*min_buffer_fill) - *min_buffer_fill= buffer_fill; - - printf("\r%sTrack %-2.2d: %s MB written %s[buf %3d%%] %4.1fx.", - debug_mark,skin->supposed_track_idx+1,mb_text,fifo_text, - buffer_fill,measured_speed/speed_factor); - fflush(stdout); - } - if(skin->is_writing==0) { - printf("\n"); - goto thank_you_for_patience; - } - } - -#else /* ! Cdrskin_extra_leaN */ - - if(skin->supposed_track_idx<0) - skin->supposed_track_idx= 0; - if(written_bytes<=0.0 && written_total_bytes>=skin->fixed_size && - skin->fixed_size>0) { - if(!skin->is_writing) - goto thank_you_for_patience; - skin->is_writing= 0; - } else { - if(!skin->is_writing) - printf("\n"); - skin->is_writing= 1; - } - printf("\rTrack %-2.2d: %3d MB written ", - skin->supposed_track_idx+1,(int) (written_total_bytes/1024.0/1024.0)); - fflush(stdout); - if(skin->is_writing==0) - printf("\n"); - -#endif /* Cdrskin_extra_leaN */ - - - advance_interval= 1; - ret= 1; -ex:; - if(advance_interval) { - if(written_total_bytes>0) - *last_count= written_total_bytes; - else - *last_count= 0.0; - if(*last_count>*total_count) - *total_count= *last_count; - *last_time= current_time; - } - skin->previous_drive_status= drive_status; - return(ret); -} - - -#ifdef Cdrskin_libburn_write_mode_ruleS - -/** After everything else about burn_write_opts and burn_disc is set up, this - call determines the effective write mode and checks whether the drive - promises to support it. -*/ -int Cdrskin_activate_write_mode(struct CdrskiN *skin, - struct burn_write_opts *opts, - struct burn_disc *disc, - int flag) -{ - int profile_number= -1, current_is_cd= 1, ret, was_still_default= 0; - char profile_name[80], reasons[BURN_REASONS_LEN]; - enum burn_disc_status s= BURN_DISC_UNGRABBED; - enum burn_write_types wt; - - profile_name[0]= 0; - if(skin->grabbed_drive) { - burn_disc_get_profile(skin->grabbed_drive,&profile_number,profile_name); - s= burn_disc_get_status(skin->grabbed_drive); - } - if(profile_number!=0x09 && profile_number!=0x0a) - current_is_cd= 0; - if(strcmp(skin->preskin->write_mode_name,"DEFAULT")==0) { - was_still_default= 1; - wt= burn_write_opts_auto_write_type(opts, disc, reasons, 0); - if(wt==BURN_WRITE_NONE) { - if(strncmp(reasons,"MEDIA: ",7)==0) - ret= -1; - else - ret= 0; - goto report_failure; - } - skin->write_type= wt; - if(wt==BURN_WRITE_RAW) - strcpy(skin->preskin->write_mode_name,"RAW/RAW96R"); - else if(wt==BURN_WRITE_TAO) - strcpy(skin->preskin->write_mode_name,"TAO"); - else if(wt==BURN_WRITE_SAO) - strcpy(skin->preskin->write_mode_name,"SAO"); - else - sprintf(skin->preskin->write_mode_name,"LIBBURN/%d", (int) wt); - } - if(strcmp(skin->preskin->write_mode_name,"RAW/RAW96R")==0) { - skin->write_type= BURN_WRITE_RAW; - skin->block_type= BURN_BLOCK_RAW96R; - } else if(strcmp(skin->preskin->write_mode_name,"TAO")==0) { - skin->write_type= BURN_WRITE_TAO; - skin->block_type= BURN_BLOCK_MODE1; - } else if(strncmp(skin->preskin->write_mode_name,"LIBBURN/",8)==0) { - skin->block_type= BURN_BLOCK_MODE1; - } else { - strcpy(skin->preskin->write_mode_name,"SAO"); - skin->write_type= BURN_WRITE_SAO; - skin->block_type= BURN_BLOCK_SAO; - } - if(!was_still_default) - burn_write_opts_set_write_type(opts,skin->write_type,skin->block_type); - ret = burn_precheck_write(opts,disc,reasons,0); - if(ret<=0) { -report_failure:; - if(ret!=-1) - fprintf(stderr,"cdrskin: Reason: %s\n",reasons); - fprintf(stderr,"cdrskin: Media : %s%s\n", - s==BURN_DISC_BLANK?"blank ": - s==BURN_DISC_APPENDABLE?"appendable ": - s==BURN_DISC_FULL?"** closed ** ":"", - profile_name[0]?profile_name: - s==BURN_DISC_EMPTY?"no media":"unknown media"); - return(0); - } - if(skin->verbosity>=Cdrskin_verbose_cmD) - printf("cdrskin: Write type : %s\n", skin->preskin->write_mode_name); - return(1); -} - -#else /* Cdrskin_libburn_write_mode_ruleS */ - -/** Determines the effective write mode and checks whether the drive promises - to support it. - @param s state of target media, obtained from burn_disc_get_status(), - submit BURN_DISC_BLANK if no real state is available -*/ -int Cdrskin_activate_write_mode(struct CdrskiN *skin, enum burn_disc_status s, - int flag) -{ - int ok, was_still_default= 0, block_type_demand,track_type,sector_size, i; - int profile_number= -1, track_type_1= 0, mixed_mode= 0, unpredicted_size= 0; - int might_do_tao= 0, might_do_sao= 1, allows_multi= 1, ret, current_is_cd= 1; - int use_data_image_size, current_is_overwriteable= 0; - struct burn_drive_info *drive_info = NULL; - char profile_name[80]; - double fixed_size= 0.0, tao_to_sao_tsize= 0.0, dummy; -#ifdef Cdrskin_libburn_has_get_multi_capS - struct burn_multi_caps *caps = NULL; -#endif - - profile_name[0]= 0; -#ifdef Cdrskin_libburn_has_get_profilE - if(skin->grabbed_drive) - burn_disc_get_profile(skin->grabbed_drive,&profile_number,profile_name); - if(profile_number!=0x09 && profile_number!=0x0a) - current_is_cd= 0; -#endif - -#ifdef Cdrskin_allow_libburn_taO - might_do_tao= 1; -#endif -#ifdef Cdrskin_libburn_has_get_multi_capS - ret = burn_disc_get_multi_caps(skin->grabbed_drive,BURN_WRITE_NONE,&caps,0); - if (ret<0) { - fprintf(stderr, - "cdrskin: FATAL : Cannot obtain write mode capabilities of drive\n"); - return(0); - } else if(ret==0) { - fprintf(stderr, - "cdrskin: SORRY : Cannot find any suitable write mode for this media\n"); - burn_disc_free_multi_caps(&caps); - return(0); - } - might_do_tao= caps->might_do_tao; - might_do_sao= caps->might_do_sao; - burn_disc_free_multi_caps(&caps); -#endif - - for(i=0;itrack_counter;i++) { - Cdrtrack_get_track_type(skin->tracklist[i],&track_type,§or_size,0); - if(i==0) - track_type_1= track_type; - else if(track_type_1!=track_type) - mixed_mode= 1; - Cdrtrack_get_size(skin->tracklist[i],&fixed_size, - &tao_to_sao_tsize,&dummy,&use_data_image_size,2); - - /* <<< until CD-SAO does fill-up: filluped last CD track length undefined */ - if(fixed_size<=0 && - !(current_is_cd==0 && skin->fill_up_media && i==skin->track_counter-1)) - unpredicted_size= 1+(tao_to_sao_tsize<=0); - } - - if(strcmp(skin->preskin->write_mode_name,"DEFAULT")==0) { - was_still_default= 1; - - if((s==BURN_DISC_APPENDABLE || mixed_mode || - (current_is_cd && skin->fill_up_media) ) && might_do_tao) { - strcpy(skin->preskin->write_mode_name,"TAO"); - was_still_default= 2; /* prevents trying of SAO if drive dislikes TAO*/ - } else if(unpredicted_size && might_do_tao) { - strcpy(skin->preskin->write_mode_name,"TAO"); - if(unpredicted_size>1) - was_still_default= 2; /* prevents trying of SAO */ - } else if(s==BURN_DISC_BLANK && skin->track_counter==1 && - skin->fill_up_media && might_do_sao && !current_is_cd) { - /* to avoid problems on my NEC with blank DVD-RW and TAO fill_up_media */ - strcpy(skin->preskin->write_mode_name,"SAO"); - } else if((profile_number==0x1a || profile_number==0x13 || - profile_number==0x12 || - profile_number==0x11 || profile_number==0x14 || - profile_number==0x15 || - profile_number==0x1b || profile_number==0x2b) - && might_do_tao) { - /* DVD+RW, DVD-RW Restricted Overwrite, DVD-RAM, - DVD-R[W][/DL] Sequential Recording, DVD+R[/DL] */ - strcpy(skin->preskin->write_mode_name,"TAO"); - } else { - strcpy(skin->preskin->write_mode_name,"SAO"); - } - } - if(strcmp(skin->preskin->write_mode_name,"RAW/RAW96R")==0) { - skin->write_type= BURN_WRITE_RAW; - skin->block_type= BURN_BLOCK_RAW96R; - -#ifdef Cdrskin_allow_libburn_taO - } else if(strcmp(skin->preskin->write_mode_name,"TAO")==0) { - skin->write_type= BURN_WRITE_TAO; - skin->block_type= BURN_BLOCK_MODE1; -#endif /* Cdrskin_allow_libburn_taO */ - - } else { - strcpy(skin->preskin->write_mode_name,"SAO"); - skin->write_type= BURN_WRITE_SAO; - skin->block_type= BURN_BLOCK_SAO; - } - - /* check whether desired type combination is available with drive */ - if(skin->driveno<0 || skin->driveno>skin->n_drives) { - if(skin->verbosity>=Cdrskin_verbose_debuG) - ClN(printf("cdrskin_debug: WARNING : No drive selected with Cdrskin_activate_write_mode\n")); - goto it_is_done; - } - drive_info= skin->drives+skin->driveno; - - /* <<< this should become a libburn API function.The knowledge about TAO audio - track block type is quite inappropriate here. It refers to a habit of - spc_select_write_params() (and MMC-1 table 61). But the knowledge about - the tracklist is rather cdrskin realm. (ponder ...) - */ -check_with_drive:; - ok= 0; - if(strstr(profile_name,"DVD")==profile_name) { - - /* >>> drive_info does not reflect DVD capabilities yet */ - - ok= 0; - if(skin->write_type==BURN_WRITE_SAO && might_do_sao) - ok= 1; - if(skin->write_type==BURN_WRITE_TAO && might_do_tao) - ok= 1; - } else if(skin->write_type==BURN_WRITE_RAW) - ok= !!(drive_info->raw_block_types & BURN_BLOCK_RAW96R); - else if(skin->write_type==BURN_WRITE_SAO && !mixed_mode) - ok= !!(drive_info->sao_block_types & BURN_BLOCK_SAO); - else if(skin->write_type==BURN_WRITE_TAO) { - block_type_demand= 0; - for(i=0;itrack_counter;i++) { - Cdrtrack_get_track_type(skin->tracklist[i],&track_type,§or_size,0); - if(track_type==BURN_AUDIO) - block_type_demand|= BURN_BLOCK_RAW0; - else - block_type_demand|= BURN_BLOCK_MODE1; - } - ok= ((drive_info->tao_block_types & block_type_demand)==block_type_demand); - } - - if(skin->write_type==BURN_WRITE_SAO && mixed_mode) { - fprintf(stderr, - "cdrskin: FATAL : Cannot write mix of data and audio in SAO mode\n"); - if(might_do_tao) - fprintf(stderr, - "cdrskin: HINT : Try with option -tao resp. without -sao\n"); - return(0); - } - if(skin->write_type==BURN_WRITE_SAO && unpredicted_size>1) { - fprintf(stderr, - "cdrskin: FATAL : At least one track has no predictable size.\n"); - fprintf(stderr, - "cdrskin: HINT : Use tsize= or tao_to_sao_tsize= to announce the track size\n"); - if(might_do_tao) - fprintf(stderr, - "cdrskin: HINT : or try with option -tao resp. without -sao\n"); - return(0); - } - if(!ok) { - fprintf(stderr, - "cdrskin: %s : Drive indicated refusal for write mode %s.\n", - (skin->force_is_set || was_still_default==1?"WARNING":"FATAL"), - skin->preskin->write_mode_name); - if(! skin->force_is_set) { - if(was_still_default==1) { - was_still_default= 2; /* do not try more than once */ - if((skin->write_type==BURN_WRITE_RAW || - skin->write_type==BURN_WRITE_SAO) && might_do_tao) { - skin->write_type= BURN_WRITE_TAO; - skin->block_type= BURN_BLOCK_MODE1; - strcpy(skin->preskin->write_mode_name,"TAO"); - goto check_with_drive; - } else if (might_do_sao) { - skin->write_type= BURN_WRITE_SAO; - skin->block_type= BURN_BLOCK_SAO; - strcpy(skin->preskin->write_mode_name,"SAO"); - goto check_with_drive; - } - } - fprintf(stderr,"cdrskin: HINT : If you are certain that the drive will do, try option -force\n"); - return(0); - } - } - -#ifdef Cdrskin_libburn_has_get_multi_capS - ret = burn_disc_get_multi_caps(skin->grabbed_drive,skin->write_type,&caps,0); - if (ret>0) { - current_is_overwriteable= caps->start_adr; - allows_multi= caps->multi_session || current_is_overwriteable; - } - burn_disc_free_multi_caps(&caps); -#endif - if(skin->multi) { - if(!allows_multi) { - if(skin->prodvd_cli_compatible) { - skin->multi= 0; - if(skin->verbosity>=Cdrskin_verbose_progresS) - fprintf(stderr, "cdrskin: NOTE : Ignored option -multi.\n"); - } else { - fprintf(stderr, - "cdrskin: SORRY : Cannot keep this media appendable after write by -multi\n"); - return(0); - } else if(current_is_overwriteable) { - skin->multi= 0; - if(!skin->use_data_image_size) - if(skin->verbosity>=Cdrskin_verbose_progresS) - fprintf(stderr, "cdrskin: NOTE : -multi cannot leave a recognizeable end mark on this media.\n"); - } - } - -it_is_done:; - if(skin->write_type==BURN_WRITE_SAO && unpredicted_size==1) - for(i= 0; itrack_counter; i++) { - Cdrtrack_get_size(skin->tracklist[i],&fixed_size, - &tao_to_sao_tsize,&dummy,2); - if(fixed_size<=0.0 && tao_to_sao_tsize>0.0) { - printf( - "cdrskin: NOTE : augmenting non-tao write mode by tao_to_sao_tsize\n"); - printf("cdrskin: NOTE : fixed size : %.f\n",tao_to_sao_tsize); - Cdrtrack_activate_tao_tsize(skin->tracklist[i],0); - } - } - if(skin->verbosity>=Cdrskin_verbose_cmD) - printf("cdrskin: write type : %s\n", skin->preskin->write_mode_name); - return(1); -} - -#endif /* ! Cdrskin_libburn_write_mode_ruleS */ - - -#ifndef Cdrskin_extra_leaN - -int Cdrskin_announce_tracks(struct CdrskiN *skin, int flag) -{ - int i,mb,use_data_image_size; - double size,padding,sector_size= 2048.0; - double sectors; - - if(skin->verbosity>=Cdrskin_verbose_progresS) { - for(i=0;itrack_counter;i++) { - Cdrtrack_get_size(skin->tracklist[i],&size,&padding,§or_size, - &use_data_image_size,0); - if(size<=0) { - printf("Track %-2.2d: %s unknown length", - i+1,(sector_size==2048?"data ":"audio")); - } else { - mb= size/1024.0/1024.0; - printf("Track %-2.2d: %s %4d MB ", - i+1,(sector_size==2048?"data ":"audio"),mb); - } - if(padding>0) - printf(" padsize: %.f KB\n",padding/1024.0); - else - printf("\n"); - } - if(skin->fixed_size<=0) { - printf("Total size: 0 MB (00:00.00) = 0 sectors\n"); - printf("Lout start: 0 MB (00:02/00) = 0 sectors\n"); - } else { - /* >>> This is quite a fake. Need to learn about 12:35.25 and "Lout" - ??? Is there a way to obtain the toc in advance (print_cue()) ? */ - double seconds; - int min,sec,frac; - - mb= skin->fixed_size/1024.0/1024.0; - seconds= skin->fixed_size/150.0/1024.0+2.0; - min= seconds/60.0; - sec= seconds-min*60; - frac= (seconds-min*60-sec)*100; - if(frac>99) - frac= 99; - sectors= (int) (skin->fixed_size/sector_size); - if(sectors*sector_size != skin->fixed_size) - sectors++; - printf("Total size: %5d MB (%-2.2d:%-2.2d.%-2.2d) = %d sectors\n", - mb,min,sec,frac,(int) sectors); - seconds+= 2; - min= seconds/60.0; - sec= seconds-min*60; - frac= (seconds-min*60-sec)*100; - if(frac>99) - frac= 99; - printf("Lout start: %5d MB (%-2.2d:%-2.2d/%-2.2d) = %d sectors\n", - mb,min,sec,frac,(int) sectors); - } - } - return(1); -} - -#endif /* ! Cdrskin_extra_leaN */ - - -#ifdef Cdrskin_libburn_has_random_access_rW - -int Cdrskin_direct_write(struct CdrskiN *skin, int flag) -{ - off_t byte_address, data_count, chunksize, i, alignment, fill; - int ret, max_chunksize= 64*1024, source_fd= -1, is_from_stdin, eof_sensed= 0; - char *buf= NULL, *source_path, amount_text[81]; - struct burn_multi_caps *caps= NULL; - - ret= Cdrskin_grab_drive(skin,0); - if(ret<=0) - goto ex; - - ret= burn_disc_get_multi_caps(skin->grabbed_drive,BURN_WRITE_NONE,&caps,0); - if(ret<=0) - goto ex; - if(caps->start_adr==0) { - fprintf(stderr, - "cdrskin: SORRY : Direct writing is not supported by drive and media\n"); - {ret= 0; goto ex;} - } - alignment= caps->start_alignment; - if(alignment>0 && (((off_t) skin->direct_write_amount) % alignment)!=0) { - fprintf(stderr, - "cdrskin: SORRY : direct_write_amount=%.f not aligned to blocks of %dk\n", - skin->direct_write_amount,(int) alignment/1024); - {ret= 0; goto ex;} - } - - if(skin->track_counter<=0) { - fprintf(stderr, - "cdrskin: SORRY : No track source given for direct writing\n"); - {ret= 0; goto ex;} - } - Cdrtrack_get_source_path(skin->tracklist[0], - &source_path,&source_fd,&is_from_stdin,0); - if(source_fd==-1) { - ret= Cdrtrack_open_source_path(skin->tracklist[0],&source_fd, - 2|(skin->verbosity>=Cdrskin_verbose_debuG)); - if(ret<=0) - goto ex; - } - buf= malloc(max_chunksize); - if(buf==NULL) { - fprintf(stderr, - "cdrskin: FATAL : Cannot allocate %d bytes of read buffer.\n", - max_chunksize); - {ret= -1; goto ex;} - } - byte_address= skin->write_start_address; - if(byte_address<0) - byte_address= 0; - data_count= skin->direct_write_amount; - if(data_count>0) - sprintf(amount_text,"%.fk",(double) (data_count/1024)); - else - strcpy(amount_text,"0=open_ended"); - fprintf(stderr,"Beginning direct write (start=%.fk,amount=%s) ...\n", - (double) (byte_address/1024),amount_text); - for(i= 0; i 0 ? alignment : 2048); - else - chunksize= data_count-i; - if(chunksize>max_chunksize) - chunksize= max_chunksize; - - /* read buffer from first track */ - for(fill= 0; fill0) - fprintf(stderr,"cdrskin: %s (errno=%d)\n", strerror(errno), errno); - ret= 0; goto ex; - } else if(ret==0) { - eof_sensed= 1; - if(data_count==0) { - memset(buf+fill,0,(size_t) (chunksize-fill)); - break; - } else { - fprintf(stderr, - "cdrskin: FATAL : Premature EOF while reading from '%s'\n", - source_path); - ret= 0; goto ex; - } - } - } - ret= burn_random_access_write(skin->grabbed_drive,byte_address, - buf,chunksize,0); - if(ret<=0) - goto ex; - if(eof_sensed) - break; - byte_address+= chunksize; - fprintf(stderr,"\r%9.fk written ",((double) (i+chunksize))/1024.0); - } - fprintf(stderr,"\r%9.fk written \n",((double) i)/1024.0); - /* flush drive buffer */ - fprintf(stderr,"syncing cache ...\n"); - ret = burn_random_access_write(skin->grabbed_drive,byte_address,buf,0,1); - if(ret<=0) - goto ex; - ret= 1; -ex:; - if(caps!=NULL) - burn_disc_free_multi_caps(&caps); - if(skin->drive_is_grabbed) - Cdrskin_release_drive(skin,0); - if(buf!=NULL) - free(buf); - if(ret>0) - fprintf(stderr,"writing done\n"); - else - fprintf(stderr,"writing failed\n"); - return(ret); -} - - -int Cdrskin_grow_overwriteable_iso(struct CdrskiN *skin, int flag) -{ - int ret, i, went_well= 1; - char *track_descr,*td,*md; - double track_size, media_size; - - ret= Cdrtrack_get_iso_fs_descr(skin->tracklist[0],&track_descr,&track_size,0); - if(ret<=0) { - fprintf(stderr,"cdrskin: SORRY : Saw no ISO-9660 filesystem in track 0\n"); - return(ret); - } - if(skin->grow_overwriteable_iso==3) /* initial session */ - return(1); - if(skin->grow_overwriteable_iso!=2) { - fprintf(stderr, - "cdrskin: SORRY : Could not read ISO-9660 descriptors from media\n"); - return(0); - } - ret= Scan_for_iso_size((unsigned char *) skin->overwriteable_iso_head+16*2048, - &media_size, 0); - if(ret<=0) { - fprintf(stderr,"cdrskin: SORRY : No recognizable ISO-9660 on media\n"); - return(0); - } - if(skin->write_start_address>=0.0) - media_size= skin->write_start_address; - - /* Write new sum into media descr 0 */ - md= skin->overwriteable_iso_head+16*2048; - memcpy(md,track_descr,2048); - Set_descr_iso_size((unsigned char *) md,track_size+media_size,0); - if(skin->verbosity>=Cdrskin_verbose_debuG) - ClN(fprintf(stderr,"cdrskin_debug: new ISO-9660 size : %.f (%fs)\n", - track_size+media_size, (track_size+media_size)/2048)); - - /* Copy type 255 CD001 descriptors from track to media descriptor buffer - and adjust their size entries */ - for(i=1; i<16; i++) { - td= track_descr+i*2048; - md= skin->overwriteable_iso_head+(16+i)*2048; - if(td[0] != -1) - break; - /* demand media descrN[0] == track descrN[0] */ - if(td[0] != md[0]) { - fprintf(stderr, - "cdrskin: SORRY : Type mismatch of ISO volume descriptor #%d (%u <-> %u)\n", - i, ((unsigned int) td[0]) & 0xff, ((unsigned int) md[0])&0xff); - went_well= 0; - } - memcpy(md,td,2048); - Set_descr_iso_size((unsigned char *) md,track_size+media_size,0); - } - if(skin->verbosity>=Cdrskin_verbose_debuG) - ClN(fprintf(stderr,"cdrskin_debug: copied %d secondary ISO descriptors\n", - i-1)); - - /* write block 16 to 31 to media */ - if(skin->verbosity>=Cdrskin_verbose_debuG) - ClN(fprintf(stderr,"cdrskin_debug: writing to media: blocks 16 to 31\n")); - ret= burn_random_access_write(skin->grabbed_drive, (off_t) (16*2048), - skin->overwriteable_iso_head+16*2048, - (off_t) (16*2048), 1); - if(ret<=0) - return(ret); - - return(went_well); -} - - -#endif /* Cdrskin_libburn_has_random_access_rW */ - - -/** Burn data via libburn according to the parameters set in skin. - @return <=0 error, 1 success -*/ -int Cdrskin_burn(struct CdrskiN *skin, int flag) -{ - struct burn_disc *disc; - struct burn_session *session; - struct burn_write_opts *o; - enum burn_disc_status s; - enum burn_drive_status drive_status; - struct burn_progress p; - struct burn_drive *drive; - int ret,loop_counter= 0,max_track= -1,i,hflag,nwa,num, wrote_well= 2; - int fifo_disabled= 0,fifo_percent,total_min_fill,min_buffer_fill= 101; - int use_data_image_size, needs_early_fifo_fill= 0,iso_size= -1; - double put_counter,get_counter,empty_counter,full_counter; - double start_time,last_time; - double total_count= 0.0,last_count= 0.0,size,padding,sector_size= 2048.0; - char *doing; - char *source_path; - int source_fd, is_from_stdin; - - if(skin->tell_media_space) - doing= "estimating"; - else - doing= "burning"; - printf("cdrskin: beginning to %s disc\n", - skin->tell_media_space?"estimate":"burn"); - if(skin->fill_up_media && skin->multi) { - ClN(fprintf(stderr, - "cdrskin: NOTE : Option --fill_up_media disabled option -multi\n")); - skin->multi= 0; - } - ret= Cdrskin_grab_drive(skin,0); - if(ret<=0) - goto burn_failed; - drive= skin->drives[skin->driveno].drive; - s= burn_disc_get_status(drive); - if(skin->verbosity>=Cdrskin_verbose_progresS) - Cdrskin_report_disc_status(skin,s,1); - - -#ifndef Cdrskin_libburn_write_mode_ruleS - -#ifdef Cdrskin_allow_libburn_taO - if (s!=BURN_DISC_APPENDABLE && s!=BURN_DISC_BLANK) { -#else - if (s!=BURN_DISC_BLANK) { -#endif - Cdrskin_release_drive(skin,0); - fprintf(stderr,"cdrskin: FATAL : No writeable media detected.\n"); - goto burn_failed; - } - - ret= Cdrskin_activate_write_mode(skin,s,0); - if(ret<=0) { - fprintf(stderr, - "cdrskin: FATAL : Cannot activate the desired write mode\n"); - goto burn_failed; - } - -#endif /* ! Cdrskin_libburn_write_mode_ruleS */ - - - disc= burn_disc_create(); - session= burn_session_create(); - ret= burn_disc_add_session(disc,session,BURN_POS_END); - if(ret==0) { - fprintf(stderr,"cdrskin: FATAL : Cannot add session to disc object.\n"); -burn_failed:; - if(skin->verbosity>=Cdrskin_verbose_progresS) - printf("cdrskin: %s failed\n", doing); - fprintf(stderr,"cdrskin: FATAL : %s failed.\n", doing); - return(0); - } - skin->fixed_size= 0.0; - for(i=0;itrack_counter;i++) { - hflag= (skin->verbosity>=Cdrskin_verbose_debuG); - if(i==skin->track_counter-1) - Cdrtrack_ensure_padding(skin->tracklist[i],hflag&1); - ret= Cdrtrack_add_to_session(skin->tracklist[i],i,session,hflag); - if(ret<=0) { - fprintf(stderr,"cdrskin: FATAL : Cannot add track %d to session.\n",i+1); - goto burn_failed; - } - Cdrtrack_get_size(skin->tracklist[i],&size,&padding,§or_size, - &use_data_image_size,0); - if(use_data_image_size==1) { /* still unfulfilled -isosize demand pending */ - needs_early_fifo_fill= 1; - } else if(size>0) - skin->fixed_size+= size+padding; - else - skin->has_open_ended_track= 1; - } - -#ifndef Cdrskin_libburn_write_mode_ruleS - if (s==BURN_DISC_APPENDABLE) { -#ifdef Cdrskin_allow_sao_for_appendablE - ; -#else - if(skin->write_type!=BURN_WRITE_TAO) { - Cdrskin_release_drive(skin,0); - fprintf(stderr,"cdrskin: FATAL : For now only write mode -tao can be used with appendable disks\n"); - goto burn_failed; - } -#endif /* ! Cdrskin_allow_sao_for_appendablE */ - } -#endif /* ! Cdrskin_libburn_write_mode_ruleS */ - -#ifndef Cdrskin_extra_leaN - /* Final decision on track size has to be made after eventual -isosize - determination via fifo content. - */ - if(needs_early_fifo_fill && !skin->tell_media_space) { - int start_memorized; - - start_memorized= skin->fifo_start_at; - /* try ISO-9660 size recognition via fifo */ - if(32*2048<=skin->fifo_size) - skin->fifo_start_at= 32*2048; - else - skin->fifo_start_at= skin->fifo_size; - ret= Cdrskin_fill_fifo(skin,0); - if(ret<=0) - goto fifo_filling_failed; - if((start_memorized>skin->fifo_start_at || start_memorized<=0) && - skin->fifo_start_atfifo_size) - needs_early_fifo_fill= 2; /* continue filling fifo at normal stage */ - skin->fifo_start_at= start_memorized; - } -#endif /* Cdrskin_extra_leaN */ - - skin->fixed_size= 0.0; - skin->has_open_ended_track= 0; - for(i=0;itrack_counter;i++) { - Cdrtrack_get_size(skin->tracklist[i],&size,&padding,§or_size, - &use_data_image_size,0); - if(use_data_image_size==1 && size<=0 && skin->tell_media_space) - size= 1024*1024; /* a dummy size */ - ret= Cdrtrack_activate_image_size(skin->tracklist[i],&size, - !!skin->tell_media_space); - if(ret<=0) { - Cdrtrack_get_source_path(skin->tracklist[i], - &source_path,&source_fd,&is_from_stdin,0); - fprintf(stderr, - "cdrskin: FATAL : Cannot determine -isosize of track source\n"); - fprintf(stderr, - "cdrskin: '%s'\n", source_path); - {ret= 0; goto ex;} - } - Cdrtrack_get_size(skin->tracklist[i],&size,&padding,§or_size, - &use_data_image_size,0); - if(use_data_image_size==2 && skin->verbosity>=Cdrskin_verbose_debuG) - ClN(fprintf(stderr, - "cdrskin: DEBUG: track %2.2d : activated -isosize %.fs (= %.fb)\n", - i+1, size/2048.0,size)); - if(size>0) - skin->fixed_size+= size+padding; - else - skin->has_open_ended_track= 1; - } - - o= burn_write_opts_new(drive); - burn_write_opts_set_perform_opc(o, 0); - -#ifdef Cdrskin_libburn_has_set_start_bytE - -/* growisofs stunt: assessment of media and start for next session */ - if((skin->grow_overwriteable_iso==1 || skin->grow_overwriteable_iso==2) && - skin->media_is_overwriteable) { - /* Obtain ISO size from media, keep 64 kB head in memory */ - ret= Cdrskin_overwriteable_iso_size(skin,&iso_size,0); - if(ret<0) - goto ex; - if(ret>0 && skin->write_start_address<0) { - skin->write_start_address= ((double) iso_size)*2048.0; - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf( - "cdrskin: write start address by --grow_overwriteable_iso : %ds\n", - iso_size)); - } else if(ret==0) - skin->grow_overwriteable_iso= 3; /* do not patch ISO header later on */ - } - - burn_write_opts_set_start_byte(o, skin->write_start_address); - -#endif /* Cdrskin_libburn_has_set_start_bytE */ - -#ifdef Cdrskin_libburn_has_multI - if(skin->media_is_overwriteable && skin->multi) { - if(skin->grow_overwriteable_iso<=0) { - fprintf(stderr, "cdrskin: FATAL : -multi cannot leave a recognizeable end mark on this media.\n"); - fprintf(stderr, "cdrskin: HINT : For ISO-9660 images try --grow_overwriteable_iso -multi\n"); - {ret= 0; goto ex;} - } - skin->multi= 0; - } - if(skin->multi && !skin->media_does_multi) { - if(skin->prodvd_cli_compatible) { - skin->multi= 0; - if(skin->verbosity>=Cdrskin_verbose_progresS) - fprintf(stderr, "cdrskin: NOTE : Ignored option -multi.\n"); - } - } - burn_write_opts_set_multi(o,skin->multi); -#endif -#ifdef Cdrskin_libburn_has_set_filluP - burn_write_opts_set_fillup(o, skin->fill_up_media); -#endif -#ifdef Cdrskin_libburn_has_set_forcE - burn_write_opts_set_force(o, !!skin->force_is_set); -#endif -#ifdef Cdrskin_libburn_has_stream_recordinG - burn_write_opts_set_stream_recording(o, !!skin->stream_recording_is_set); -#endif - - if(skin->dummy_mode) { - fprintf(stderr, - "cdrskin: NOTE : -dummy mode will prevent actual writing\n"); - burn_write_opts_set_simulate(o, 1); - } - burn_write_opts_set_underrun_proof(o,skin->burnfree); - -#ifdef Cdrskin_libburn_write_mode_ruleS - ret= Cdrskin_activate_write_mode(skin,o,disc,0); - if(ret<=0) - goto burn_failed; -#else /* Cdrskin_libburn_write_mode_ruleS */ - burn_write_opts_set_write_type(o,skin->write_type,skin->block_type); -#endif - - ret= Cdrskin_obtain_nwa(skin, &nwa,0); - if(ret<=0) - nwa= -1; - if(skin->assert_write_lba>=0 && nwa!=skin->assert_write_lba) { - fprintf(stderr, - "cdrskin: FATAL : Option assert_write_lba= demands block number %10d\n", - skin->assert_write_lba); - fprintf(stderr, - "cdrskin: FATAL : but predicted actual write start address is %10d\n", - nwa); - {ret= 0; goto ex;} - } - -#ifndef Cdrskin_extra_leaN - Cdrskin_announce_tracks(skin,0); -#endif - - if(skin->tell_media_space || skin->track_counter<=0) { - /* write capacity estimation and return without actual burning */ - -#ifdef Cdrskin_libburn_has_get_spacE - { - off_t free_space; - char msg[80]; - - free_space= burn_disc_available_space(drive,o); - sprintf(msg,"%d\n",(int) (free_space/(off_t) 2048)); - if(skin->preskin->result_fd>=0) { - write(skin->preskin->result_fd,msg,strlen(msg)); - } else - printf("%s",msg); - } -#endif /* Cdrskin_libburn_has_get_spacE */ - - if(skin->track_counter>0) - fprintf(stderr, - "cdrskin: NOTE : %s burn run suppressed by option --tell_media_space\n", - skin->preskin->write_mode_name); - {ret= 1; goto ex;} - } - - Cdrskin_adjust_speed(skin,0); - -#ifndef Cdrskin_extra_leaN - Cdrskin_wait_before_action(skin,0); - if(needs_early_fifo_fill==1) - ret= 1; - else - ret= Cdrskin_fill_fifo(skin,0); - if(ret<=0) { -fifo_filling_failed:; - fprintf(stderr,"cdrskin: FATAL : Filling of fifo failed\n"); - goto ex; - } - -#endif /* ! Cdrskin_extra_leaN */ - - if(skin->verbosity>=Cdrskin_verbose_progresS && nwa>=0) - printf("Starting new track at sector: %d\n",nwa); - skin->drive_is_busy= 1; - burn_disc_write(o, disc); - if(skin->preskin->abort_handler==-1) - Cleanup_set_handlers(skin,(Cleanup_app_handler_T) Cdrskin_abort_handler,4); - last_time= start_time= Sfile_microtime(0); - - burn_write_opts_free(o); - - while (burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING) { - - /* >>> how do i learn about success or failure ? */ - - ; - } - loop_counter= 0; - while (1) { - drive_status= burn_drive_get_status(drive, &p); - if(drive_status==BURN_DRIVE_IDLE) - break; - - /* >>> how do i learn about success or failure ? */ - - if(loop_counter>0) - Cdrskin_burn_pacifier(skin,drive_status,&p,start_time,&last_time, - &total_count,&last_count,&min_buffer_fill,0); - - if(max_tracksupposed_track_idx) - max_track= skin->supposed_track_idx; - - -#ifndef Cdrskin_extra_leaN - - /* <<< debugging : artificial abort without a previous signal */; - if(skin->abort_after_bytecount>=0.0 && - total_count>=skin->abort_after_bytecount) { - /* whatever signal handling is installed: this thread is the boss now */ - fprintf(stderr, - "cdrskin: DEVELOPMENT : synthetic abort by abort_after_bytecount=%.f\n", - skin->abort_after_bytecount); - skin->control_pid= getpid(); - ret= Cdrskin_abort_handler(skin,0,0); - fprintf(stderr,"cdrskin: done (aborted)\n"); - exit(1); - } - - if(skin->fifo==NULL || fifo_disabled) { - usleep(20000); - } else { - ret= Cdrfifo_try_to_work(skin->fifo,20000,NULL,NULL,0); - if(ret<0) { - int abh; - - abh= skin->preskin->abort_handler; - if(abh!=2) - fprintf(stderr, - "\ncdrskin: FATAL : Fifo encountered error during burn loop.\n"); - if(abh==0) { - ret= -1; goto ex; - } else if(abh==1 || abh==3 || abh==4 || abh==-1) { - Cdrskin_abort_handler(skin,0,0); - fprintf(stderr,"cdrskin: done (aborted)\n"); - exit(10); - } else { - if(skin->verbosity>=Cdrskin_verbose_debuG) - fprintf(stderr, - "\ncdrskin_debug: Cdrfifo_try_to_work() returns %d\n",ret); - } - } - if(ret==2) { /* <0 = error , 2 = work is done */ - if(skin->verbosity>=Cdrskin_verbose_debuG) - fprintf(stderr,"\ncdrskin_debug: fifo ended work with ret=%d\n",ret); - fifo_disabled= 1; - } - } -#else /* ! Cdrskin_extra_leaN */ - usleep(20000); -#endif /* Cdrskin_extra_leaN */ - - loop_counter++; - } - skin->drive_is_busy= 0; - if(skin->verbosity>=Cdrskin_verbose_progresS) - printf("\n"); - -#ifdef Cdrskin_libburn_has_wrote_welL - wrote_well = burn_drive_wrote_well(drive); -#endif - -#ifdef Cdrskin_libburn_has_random_access_rW - if(skin->media_is_overwriteable && skin->grow_overwriteable_iso>0 && - wrote_well) { - /* growisofs final stunt : update volume descriptors at start of media */ - ret= Cdrskin_grow_overwriteable_iso(skin,0); - if(ret<=0) - wrote_well= 0; - } -#endif /* Cdrskin_libburn_has_random_access_rW */ - - if(max_track<0) { - printf("Track 01: Total bytes read/written: %.f/%.f (%.f sectors).\n", - total_count,total_count,total_count/sector_size); - } else { - Cdrtrack_get_size(skin->tracklist[max_track],&size,&padding,§or_size, - &use_data_image_size,1); - printf("Track %-2.2d: Total bytes read/written: %.f/%.f (%.f sectors).\n", - max_track+1,size,size+padding,(size+padding)/sector_size); - } - if(skin->verbosity>=Cdrskin_verbose_progresS) - printf("Writing time: %.3fs\n",Sfile_microtime(0)-start_time); - - -#ifndef Cdrskin_extra_leaN - - if(skin->fifo!=NULL && skin->fifo_size>0 && wrote_well) { - int dummy,final_fill; - Cdrfifo_get_buffer_state(skin->fifo,&final_fill,&dummy,0); - if(final_fill>0) { -fifo_full_at_end:; - fprintf(stderr, - "cdrskin: FATAL : Fifo still contains data after burning has ended.\n"); - fprintf(stderr, - "cdrskin: FATAL : %.d bytes left.\n",final_fill); - fprintf(stderr, - "cdrskin: FATAL : This indicates an overflow of the last track.\n"); - fprintf(stderr, - "cdrskin: NOTE : The media might appear ok but is probably truncated.\n"); - ret= -1; goto ex; - } - -#ifdef Cdrskin_libburn_leaves_inlet_opeN - for(i= 0;itrack_counter;i++) { - ret= Cdrtrack_has_input_left(skin->tracklist[i],0); - if(ret>0) { - fprintf(stderr, - "cdrskin: FATAL : Fifo outlet of track #%d is still buffering some bytes.\n", - i+1); - goto fifo_full_at_end; - } - } -#endif /* Cdrskin_libburn_leaves_inlet_opeN */ - - } - - if(skin->verbosity>=Cdrskin_verbose_progresS) { - if(skin->fifo!=NULL && skin->fifo_size>0) { - int dummy; - - Cdrfifo_get_min_fill(skin->fifo,&total_min_fill,&dummy,0); - fifo_percent= 100.0*((double) total_min_fill)/(double) skin->fifo_size; - if(fifo_percent==0 && total_min_fill>0) - fifo_percent= 1; - Cdrfifo_get_cdr_counters(skin->fifo,&put_counter,&get_counter, - &empty_counter,&full_counter,0); - fflush(stdout); - fprintf(stderr,"Cdrskin: fifo had %.f puts and %.f gets.\n", - put_counter,get_counter); - fprintf(stderr, - "Cdrskin: fifo was %.f times empty and %.f times full, min fill was %d%%.\n", - empty_counter,full_counter,fifo_percent); - } - drive_status= burn_drive_get_status(drive, &p); - -#ifdef Cdrskin_libburn_has_buffer_min_filL - /* cdrskin recorded its own coarse min_buffer_fill. - libburn's is finer - if enough bytes were processed so it is available.*/ - if(p.buffer_min_fill<=p.buffer_capacity && p.buffer_capacity>0) { - num= 100.0 * ((double) p.buffer_min_fill)/(double) p.buffer_capacity; - if(num100) - min_buffer_fill= 50; - printf("Min drive buffer fill was %d%%\n", min_buffer_fill); - } - -#endif /* ! Cdrskin_extra_leaN */ - - ret= 1; - if(wrote_well) { - if(skin->verbosity>=Cdrskin_verbose_progresS) - printf("cdrskin: burning done\n"); - } else - ret= 0; -ex:; - if(ret<=0) { - if(skin->verbosity>=Cdrskin_verbose_progresS) - printf("cdrskin: %s failed\n",doing); - fprintf(stderr,"cdrskin: FATAL : %s failed.\n",doing); - } - skin->drive_is_busy= 0; - if(skin->verbosity>=Cdrskin_verbose_debuG) - ClN(printf("cdrskin_debug: do_eject= %d\n",skin->do_eject)); - Cdrskin_release_drive(skin,0); - for(i= 0;itrack_counter;i++) - Cdrtrack_cleanup(skin->tracklist[i],0); - burn_session_free(session); - burn_disc_free(disc); - return(ret); -} - - -/** Print lba of first track of last session and Next Writeable Address of - the next unwritten session. -*/ -int Cdrskin_msinfo(struct CdrskiN *skin, int flag) -{ - int num_sessions, session_no, ret, num_tracks; - int nwa= -123456789, lba= -123456789, aux_lba; - char msg[80]; - enum burn_disc_status s; - struct burn_drive *drive; - struct burn_disc *disc= NULL; - struct burn_session **sessions= NULL; - struct burn_track **tracks; - struct burn_toc_entry toc_entry; - - ret= Cdrskin_grab_drive(skin,0); - if(ret<=0) - return(ret); - drive= skin->drives[skin->driveno].drive; - s= burn_disc_get_status(drive); - if(s!=BURN_DISC_APPENDABLE) { - if(skin->grow_overwriteable_iso==1 || skin->grow_overwriteable_iso==2) { - lba= 0; - ret= Cdrskin_overwriteable_iso_size(skin,&nwa,0); - if(ret>0) { - s= BURN_DISC_APPENDABLE; - goto put_out; - } - } - Cdrskin_report_disc_status(skin,s,0); - fprintf(stderr,"cdrskin: FATAL : -msinfo can only operate on appendable (i.e. -multi) discs\n"); - if(skin->grow_overwriteable_iso>0) - fprintf(stderr,"cdrskin: or on overwriteables with existing ISO-9660 file system.\n"); - {ret= 0; goto ex;} - } - disc= burn_drive_get_disc(drive); - if(disc==NULL) { - -#ifdef Cdrskin_libburn_has_get_msc1 - /* No TOC available. Try to inquire directly. */ - ret= burn_disc_get_msc1(drive,&lba); - if(ret>0) - goto obtain_nwa; -#endif /* Cdrskin_libburn_has_get_msc1 */ - - fprintf(stderr,"cdrskin: FATAL : Cannot obtain info about CD content\n"); - {ret= 0; goto ex;} - } - sessions= burn_disc_get_sessions(disc,&num_sessions); - for(session_no= 0; session_no0) - nwa= aux_lba+6900; - else - nwa= aux_lba+11400; - } - -put_out:; - if(skin->preskin->result_fd>=0) { - sprintf(msg,"%d,%d\n",lba,nwa); - write(skin->preskin->result_fd,msg,strlen(msg)); - } else - printf("%d,%d\n",lba,nwa); - - if(strlen(skin->msifile)) { - FILE *fp; - - fp = fopen(skin->msifile, "w"); - if(fp==NULL) { - if(errno>0) - fprintf(stderr,"cdrskin: %s (errno=%d)\n", strerror(errno), errno); - fprintf(stderr,"cdrskin: FATAL : Cannot write msinfo to file '%s'\n", - skin->msifile); - {ret= 0; goto ex;} - } - fprintf(fp,"%d,%d",lba,nwa); - fclose(fp); - } - ret= 1; -ex:; - - /* must calm down my NEC ND-4570A afterwards */ - if(skin->verbosity>=Cdrskin_verbose_debuG) - ClN(fprintf(stderr,"cdrskin_debug: doing extra release-grab cycle\n")); - Cdrskin_release_drive(skin,0); - Cdrskin_grab_drive(skin,0); - - Cdrskin_release_drive(skin,0); - return(ret); -} - - -/** Work around the failure of libburn to eject the tray. - This employs a system(2) call and is therefore an absolute no-no for any - pseudo user identities. - @return <=0 error, 1 success -*/ -int Cdrskin_eject(struct CdrskiN *skin, int flag) -{ - -#ifndef Cdrskin_burn_drive_eject_brokeN - -#ifndef Cdrskin_oldfashioned_api_usE - int i,ret,max_try= 5; - - if(!skin->do_eject) - return(1); - - if(skin->n_drives<=skin->driveno || skin->driveno < 0) - return(2); - - /* ??? A61012 : retry loop might now be obsolete - (a matching bug in burn_disc_write_sync() was removed ) */ - /* A61227 : A kindof race condition with -atip -eject on SuSE 9.3. Loop saved - me. Waiting seems to help. I suspect the media demon. */ - - for(i= 0;i0 || i>=max_try-1) - break; - if(skin->verbosity>=Cdrskin_verbose_progresS) - ClN(fprintf(stderr, - "cdrskin: NOTE : Attempt #%d of %d failed to grab drive for eject\n", - i+1,max_try)); - usleep(1000000); - } - if(ret>0) { - ret= Cdrskin_release_drive(skin,1); - if(ret<=0) - goto sorry_failed_to_eject; - } else { -sorry_failed_to_eject:; - fprintf(stderr,"cdrskin: SORRY : Failed to finally eject tray.\n"); - return(0); - } - return(1); - -#else - - if(!skin->do_eject) - return(1); - if(Cdrskin_grab_drive(skin,2|16)>0) { - Cdrskin_release_drive(skin,1); - } else { - fprintf(stderr,"cdrskin: SORRY : Failed to finally eject tray.\n"); - return(0); - } - return(1); - -#endif - -#else /* Cdrskin_burn_drive_eject_brokeN */ - - int ret; - char adr[Cdrskin_adrleN]; - char cmd[5*Cdrskin_strleN+16],shellsafe[5*Cdrskin_strleN+2]; - - if(!skin->do_eject) - return(1); - if(skin->verbosity>=Cdrskin_verbose_progresS) - printf("cdrskin: trying to eject media\n"); - if(getuid()!=geteuid()) { - fprintf(stderr, - "cdrskin: SORRY : uid and euid differ. Will not start external eject.\n"); - Cdrpreskin_consider_normal_user(0); - return(0); - } - -#ifdef Cdrskin_libburn_has_drive_get_adR - ret= burn_drive_get_adr(&(skin->drives[skin->driveno]), adr); - if(ret<=0) - adr[0]= 0; -#else - strcpy(adr,skin->drives[skin->driveno].location); -#endif - - if(strlen(skin->eject_device)>0) - sprintf(cmd,"eject %s",Text_shellsafe(skin->eject_device,shellsafe,0)); - else if(strcmp(adr,"/dev/sg0")==0) - sprintf(cmd,"eject /dev/sr0"); - else - sprintf(cmd,"eject %s",Text_shellsafe(adr,shellsafe,0)); - ret= system(cmd); - if(ret==0) - return(1); - return(0); - -#endif /* Cdrskin_burn_drive_eject_brokeN */ - -} - - -/** Interpret all arguments of the program after libburn has been initialized - and drives have been scanned. This call reports to stderr any valid - cdrecord options which are not implemented yet. - @param flag Bitfield for control purposes: - bit0= do not finalize setup - bit1= do not interpret (again) skin->preskin->pre_argv - @return <=0 error, 1 success -*/ -int Cdrskin_setup(struct CdrskiN *skin, int argc, char **argv, int flag) -{ - int i,k,l,ret,source_has_size=0, idx= -1; - double value,grab_and_wait_value= -1.0; - char *cpt,*value_pt,adr[Cdrskin_adrleN],*blank_mode= ""; - struct stat stbuf; - - /* cdrecord 2.01 options which are not scheduled for implementation, yet */ - static char ignored_partial_options[][41]= { - "timeout=", "debug=", "kdebug=", "kd=", "driver=", "ts=", - "pregap=", "defpregap=", "mcn=", "isrc=", "index=", "textfile=", - "pktsize=", "cuefile=", - "" - }; - static char ignored_full_options[][41]= { - "-d", "-Verbose", "-V", "-silent", "-s", "-setdropts", "-prcap", - "-reset", "-abort", "-overburn", "-ignsize", "-useinfo", - "-fix", "-nofix", - "-raw", "-raw96p", "-raw16", - "-clone", "-text", "-mode2", "-xa", "-xa1", "-xa2", "-xamix", - "-cdi", "-preemp", "-nopreemp", "-copy", "-nocopy", - "-scms", "-shorttrack", "-noshorttrack", "-packet", "-noclose", - "-media-info", "-minfo", - "" - }; - - /* are we pretending to be cdrecord ? */ - cpt= strrchr(argv[0],'/'); - if(cpt==NULL) - cpt= argv[0]; - else - cpt++; - if(strcmp(cpt,"cdrecord")==0 && !(flag&1)) { - fprintf(stderr,"\n"); - fprintf(stderr, - "Note: This is not cdrecord by Joerg Schilling. Do not bother him.\n"); - fprintf(stderr, - " See cdrskin start message on stdout. See --help. See -version.\n"); - fprintf(stderr,"\n"); - /* allow automatic -tao to -sao redirection */ - skin->tao_to_sao_tsize=650*1024*1024; - } - -#ifndef Cdrskin_extra_leaN - if(!(flag&2)) { - if(skin->preskin->pre_argc>1) { - ret= Cdrskin_setup(skin,skin->preskin->pre_argc,skin->preskin->pre_argv, - flag|1|2); - if(ret<=0) - return(ret); - } - } -#endif - - for (i= 1;ipreskin->demands_cdrecord_caps= 1; - if(skin->preskin->fallback_program[0]) - fprintf(stderr,"cdrskin: NOTE : Unimplemented option: '%s'\n",argv[i]); - else - fprintf(stderr,"cdrskin: NOTE : ignoring unimplemented option : '%s'\n", - argv[i]); - fprintf(stderr, - "cdrskin: NOTE : option is waiting for a volunteer to implement it.\n"); - continue; - } - -#ifndef Cdrskin_extra_leaN - if(strncmp(argv[i],"abort_after_bytecount=",22)==0) { - skin->abort_after_bytecount= Scanf_io_size(argv[i]+22,0); - fprintf(stderr, - "cdrskin: NOTE : will perform synthetic abort after %.f bytes\n", - skin->abort_after_bytecount); - - } else if(strcmp(argv[i],"--abort_handler")==0) { -#else /* ! Cdrskin_extra_leaN */ - if(strcmp(argv[i],"--abort_handler")==0) { -#endif - /* is handled in Cdrpreskin_setup() */; - - } else if(strncmp(argv[i],"-abort_max_wait=",16)==0) { - value_pt= argv[i]+16; - goto set_abort_max_wait; - - } else if(strncmp(argv[i],"abort_max_wait=",15)==0) { - value_pt= argv[i]+15; -set_abort_max_wait:; - value= Scanf_io_size(value_pt,0); - if(value<0 || value>86400) { - fprintf(stderr, - "cdrskin: NOTE : ignored out-of-range value: abort_max_wait=%s\n", - value_pt); - } else { - skin->abort_max_wait= value; - if(skin->verbosity>=Cdrskin_verbose_cmD) - printf( - "cdrskin: maximum waiting time with abort handling : %d seconds\n", - skin->abort_max_wait); - } - -#ifdef Cdrskin_libburn_has_get_best_speeD - } else if(strcmp(argv[i],"--adjust_speed_to_drive")==0) { - skin->adjust_speed_to_drive= 1; -#endif - - } else if(strcmp(argv[i],"--allow_emulated_drives")==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strcmp(argv[i],"--allow_setuid")==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strcmp(argv[i],"--allow_untested_media")==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strcmp(argv[i],"--any_track")==0) { - skin->single_track= -1; - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf( - "cdrskin: --any_track : will accept any unknown option as track source\n")); - - } else if(strncmp(argv[i],"assert_write_lba=",17)==0) { - value_pt= argv[i]+17; - value= Scanf_io_size(value_pt,0); - l= strlen(value_pt); - if(l>1) if(isalpha(value_pt[l-1])) - value/= 2048.0; - skin->assert_write_lba= value; - - } else if(strcmp(argv[i],"-atip")==0) { - if(skin->do_atip<1) - skin->do_atip= 1; - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf("cdrskin: will put out some -atip style lines\n")); - - } else if(strcmp(argv[i],"-audio")==0) { - skin->track_type= BURN_AUDIO; - skin->track_type_by_default= 0; - - } else if(strncmp(argv[i],"-blank=",7)==0) { - cpt= argv[i]+7; - goto set_blank; - } else if(strncmp(argv[i],"blank=",6)==0) { - cpt= argv[i]+6; -set_blank:; - skin->blank_format_type= 0; - blank_mode= cpt; - if(strcmp(cpt,"all")==0 || strcmp(cpt,"disc")==0 - || strcmp(cpt,"disk")==0) { - skin->do_blank= 1; - skin->blank_fast= 0; - blank_mode= "all"; - } else if(strcmp(cpt,"fast")==0 || strcmp(cpt,"minimal")==0) { - skin->do_blank= 1; - skin->blank_fast= 1; - blank_mode= "fast"; - } else if(strcmp(cpt,"format_if_needed")==0) { - skin->do_blank= 1; - skin->blank_format_type= 6; - skin->preskin->demands_cdrskin_caps= 1; - } else if(strcmp(cpt,"format_overwrite")==0) { - skin->do_blank= 1; - skin->blank_format_type= 1|(1<<8); - skin->blank_format_size= 128*1024*1024; - skin->preskin->demands_cdrskin_caps= 1; - } else if(strcmp(cpt,"format_overwrite_full")==0) { - skin->do_blank= 1; - skin->blank_format_type= 1|(1<<10); - skin->blank_format_size= 0; - skin->preskin->demands_cdrskin_caps= 1; - } else if(strcmp(cpt,"format_overwrite_quickest")==0) { - skin->do_blank= 1; - skin->blank_format_type= 1; - skin->blank_format_size= 0; - skin->preskin->demands_cdrskin_caps= 1; - } else if(strncmp(cpt,"format_defectmgt",16)==0) { - skin->do_blank= 1; - skin->blank_format_type= 4|(3<<9); /* default payload size */ - skin->blank_format_size= 0; - skin->preskin->demands_cdrskin_caps= 1; - if(cpt[16]=='_') { - cpt+= 17; - if(strcmp(cpt,"none")==0) - skin->blank_format_type= 4|(1<<13); - else if(strcmp(cpt,"max")==0) - skin->blank_format_type= 4; /* smallest payload size above 0 */ - else if(strcmp(cpt,"min")==0) - skin->blank_format_type= 4|(2<<9); /*largest payload size with mgt*/ - else if(strncmp(cpt,"payload_",8)==0) { - skin->blank_format_size= Scanf_io_size(cpt+8,0); - skin->blank_format_type= 4; - } else if(strcmp(cpt,"cert_off")==0) - skin->blank_format_no_certify= 1; - else if(strcmp(cpt,"cert_on")==0) - skin->blank_format_no_certify= 0; - else - goto unsupported_blank_option; - } - skin->preskin->demands_cdrskin_caps= 1; - } else if(strncmp(cpt,"format_by_index_",16)==0) { - sscanf(cpt+16, "%d", &idx); - if(idx<0 || idx>255) { - fprintf(stderr,"cdrskin: SORRY : blank=%s provides unusable index\n", - cpt); - return(0); - } - skin->do_blank= 1; - skin->blank_format_type= 5|(2<<9)|(1<<15); - skin->blank_format_index= idx; - skin->blank_format_size= 0; - skin->preskin->demands_cdrskin_caps= 1; - - } else if(strcmp(cpt,"deformat_sequential")==0) { - skin->do_blank= 1; - skin->blank_format_type= 2; - skin->blank_fast= 0; - skin->preskin->demands_cdrskin_caps= 1; - } else if(strcmp(cpt,"deformat_sequential_quickest")==0) { - skin->do_blank= 1; - skin->blank_format_type= 2; - skin->blank_fast= 1; - skin->preskin->demands_cdrskin_caps= 1; - } else if(strcmp(cpt,"as_needed")==0) { - skin->do_blank= 1; - skin->blank_format_type= 7; - } else if(strcmp(cpt,"help")==0) { - /* is handled in Cdrpreskin_setup() */; - continue; - } else { -unsupported_blank_option:; - fprintf(stderr,"cdrskin: FATAL : Blank option '%s' not supported yet\n", - cpt); - return(0); - } - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf("cdrskin: blank mode : blank=%s\n",blank_mode)); - - } else if(strcmp(argv[i],"--bragg_with_audio")==0) { - /* OBSOLETE 0.2.3 : was handled in Cdrpreskin_setup() */; - - } else if(strcmp(argv[i],"-checkdrive")==0) { - skin->do_checkdrive= 1; - - } else if(strcmp(argv[i],"-data")==0) { - - /* >>> !!! All Subsequent Tracks Option */ - - skin->track_type= BURN_MODE1; - skin->track_type_by_default= 0; - - } else if(strcmp(argv[i],"--demand_a_drive")==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strcmp(argv[i],"--devices")==0) { - skin->do_devices= 1; - -#ifndef Cdrskin_extra_leaN - - } else if(strncmp(argv[i],"dev_translation=",16)==0) { - if(argv[i][16]==0) { - fprintf(stderr, - "cdrskin: FATAL : dev_translation= : missing separator character\n"); - return(0); - } - ret= Cdradrtrn_add(skin->adr_trn,argv[i]+17,argv[i]+16,1); - if(ret==-2) - fprintf(stderr, - "cdrskin: FATAL : address_translation= : cannot allocate memory\n"); - else if(ret==-1) - fprintf(stderr, - "cdrskin: FATAL : address_translation= : table full (%d items)\n", - Cdradrtrn_leN); - else if(ret==0) - fprintf(stderr, - "cdrskin: FATAL : address_translation= : no address separator '%c' found\n", - argv[i][17]); - if(ret<=0) - return(0); - -#endif /* ! Cdrskin_extra_leaN */ - - - } else if(strncmp(argv[i],"-dev=",5)==0) { - /* is handled in Cdrpreskin_setup() */; - } else if(strncmp(argv[i],"dev=",4)==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strncmp(argv[i],"direct_write_amount=",20)==0) { - skin->direct_write_amount= Scanf_io_size(argv[i]+20,0); - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf("cdrskin: amount for direct writing : %.f\n", - skin->direct_write_amount)); - if(skin->direct_write_amount>=0.0) { - skin->do_direct_write= 1; - printf("cdrskin: NOTE : Direct writing will only use first track source and no fifo.\n"); - skin->preskin->demands_cdrskin_caps= 1; - } else - skin->do_direct_write= 0; - - } else if(strcmp(argv[i],"--drive_abort_on_busy")==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strcmp(argv[i],"--drive_blocking")==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strcmp(argv[i],"--drive_not_exclusive")==0 || - strcmp(argv[i],"--drive_not_f_setlk")==0 || - strcmp(argv[i],"--drive_not_o_excl")==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strncmp(argv[i],"drive_scsi_dev_family=",22)==0) { - /* is handled in Cdrpreskin_setup() */; - if(skin->verbosity>=Cdrskin_verbose_debuG && - skin->preskin->drive_scsi_dev_family!=0) - ClN(fprintf(stderr,"cdrskin_debug: drive_scsi_dev_family= %d\n", - skin->preskin->drive_scsi_dev_family)); - - } else if(strcmp(argv[i],"--drive_scsi_exclusive")==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strncmp(argv[i],"-driveropts=",12)==0) { - value_pt= argv[i]+12; - goto set_driveropts; - } else if(strncmp(argv[i],"driveropts=",11)==0) { - value_pt= argv[i]+11; -set_driveropts:; - if(strcmp(value_pt,"burnfree")==0 || strcmp(value_pt,"burnproof")==0) { - skin->burnfree= 1; - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf("cdrskin: burnfree : on\n")); - } else if(strcmp(argv[i]+11,"noburnfree")==0 || - strcmp(argv[i]+11,"noburnproof")==0 ) { - skin->burnfree= 0; - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf("cdrskin: burnfree : off\n")); - } else if(strcmp(argv[i]+11,"help")==0) { - /* handled in Cdrpreskin_setup() */; - } else - goto ignore_unknown; - - } else if(strcmp(argv[i],"-dummy")==0) { - skin->dummy_mode= 1; - - } else if(strcmp(argv[i],"-eject")==0) { - skin->do_eject= 1; - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf("cdrskin: eject after work : on\n")); - - } else if(strncmp(argv[i],"eject_device=",13)==0) { - if(strlen(argv[i]+13)>=sizeof(skin->eject_device)) { - fprintf(stderr, - "cdrskin: FATAL : eject_device=... too long. (max: %d, given: %d)\n", - (int) sizeof(skin->eject_device)-1,(int) strlen(argv[i]+13)); - return(0); - } - strcpy(skin->eject_device,argv[i]+13); - if(skin->verbosity>=Cdrskin_verbose_cmD) -#ifdef Cdrskin_burn_drive_eject_brokeN - ClN(printf("cdrskin: eject_device : %s\n",skin->eject_device)); -#else - ClN(printf("cdrskin: ignoring obsolete eject_device=%s\n", - skin->eject_device)); -#endif - - -#ifndef Cdrskin_extra_leaN - - } else if(strcmp(argv[i],"--fifo_disable")==0) { - skin->fifo_enabled= 0; - skin->fifo_size= 0; - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf("cdrskin: option fs=... disabled\n")); - - } else if(strcmp(argv[i],"--fifo_start_empty")==0) { /* obsoleted */ - skin->fifo_start_at= 0; - - } else if(strncmp(argv[i],"fifo_start_at=",14)==0) { - value= Scanf_io_size(argv[i]+14,0); - if(value>1024.0*1024.0*1024.0) - value= 1024.0*1024.0*1024.0; - else if(value<0) - value= 0; - skin->fifo_start_at= value; - - } else if(strcmp(argv[i],"--fifo_per_track")==0) { - skin->fifo_per_track= 1; - -#endif /* ! Cdrskin_extra_leaN */ - -#ifdef Cdrskin_libburn_has_set_filluP - } else if(strcmp(argv[i],"--fill_up_media")==0) { - skin->fill_up_media= 1; - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf( - "cdrskin: will fill up last track to full free media space\n")); -#endif - - } else if(strcmp(argv[i],"-force")==0) { - skin->force_is_set= 1; - - } else if(strcmp(argv[i],"-format")==0) { - skin->do_blank= 1; - skin->blank_format_type= 3|(1<<10); - skin->blank_format_size= 0; - skin->force_is_set= 1; - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf( - "cdrskin: will format DVD+RW by blank=format_overwrite_full -force\n")); - -#ifndef Cdrskin_extra_leaN - - } else if(strncmp(argv[i],"-fs=",4)==0) { - value_pt= argv[i]+4; - goto fs_equals; - } else if(strncmp(argv[i],"fs=",3)==0) { - value_pt= argv[i]+3; -fs_equals:; - if(skin->fifo_enabled) { - value= Scanf_io_size(value_pt,0); - if(value<0.0 || value>1024.0*1024.0*1024.0) { - fprintf(stderr, - "cdrskin: FATAL : fs=N expects a size between 0 and 1g\n"); - return(0); - } - skin->fifo_size= value; - if(skin->verbosity>=Cdrskin_verbose_cmD) - printf("cdrskin: fifo size : %d\n",skin->fifo_size); - } - - } else if(strncmp(argv[i],"grab_drive_and_wait=",20)==0) { - value_pt= argv[i]+20; - grab_and_wait_value= Scanf_io_size(value_pt,0); - skin->preskin->demands_cdrskin_caps= 1; - - } else if(strncmp(argv[i],"-gracetime=",11)==0) { - value_pt= argv[i]+11; - goto gracetime_equals; - } else if(strncmp(argv[i],"gracetime=",10)==0) { - value_pt= argv[i]+10; -gracetime_equals:; - sscanf(value_pt,"%d",&(skin->gracetime)); - -#ifdef Cdrskin_libburn_has_get_multi_capS -#ifdef Cdrskin_libburn_has_random_access_rW - } else if(strncmp(argv[i],"--grow_overwriteable_iso",24)==0) { - skin->grow_overwriteable_iso= 1; - skin->use_data_image_size= 1; - skin->preskin->demands_cdrskin_caps= 1; -#endif /* Cdrskin_libburn_has_random_access_rW */ -#endif /* Cdrskin_libburn_has_get_multi_capS */ - - -#else /* ! Cdrskin_extra_leaN */ - - } else if( - strcmp(argv[i],"--fifo_disable")==0 || - strcmp(argv[i],"--fifo_start_empty")==0 || - strncmp(argv[i],"fifo_start_at=",14)==0 || - strcmp(argv[i],"--fifo_per_track")==0 || - strncmp(argv[i],"-fs=",4)==0 || - strncmp(argv[i],"fs=",3)==0 || - strncmp(argv[i],"-gracetime=",11)==0 || - strncmp(argv[i],"gracetime=",10)==0) { - fprintf(stderr, - "cdrskin: NOTE : lean version ignores option: '%s'\n", - argv[i]); - -#endif /* Cdrskin_extra_leaN */ - - } else if(strcmp(argv[i],"--help")==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strcmp(argv[i],"-help")==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strcmp(argv[i],"--ignore_signals")==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strcmp(argv[i],"-immed")==0) { -#ifdef Cdrskin_libburn_has_set_waitinG - skin->modesty_on_drive= 1; - skin->min_buffer_percent= 75; - skin->max_buffer_percent= 95; -#else - ; -#endif /* Cdrskin_libburn_has_set_waitinG */ - - } else if(strcmp(argv[i],"-inq")==0) { - skin->do_checkdrive= 2; - - } else if(strcmp(argv[i],"-isosize")==0) { - skin->use_data_image_size= 1; - - } else if(strcmp(argv[i],"--list_formats")==0) { - skin->do_list_formats= 1; - skin->preskin->demands_cdrskin_caps= 1; - - } else if(strcmp(argv[i],"--list_ignored_options")==0) { - char line[80]; - /* is also handled in Cdrpreskin_setup() */; - - line[0]= 0; - printf("cdrskin: List of all ignored options:\n"); - for(k=0;ignored_partial_options[k][0]!=0;k++) - printf("%s\n",ignored_partial_options[k]); - for(k=0;ignored_full_options[k][0]!=0;k++) - printf("%s\n",ignored_full_options[k]); - printf("\n"); - - } else if(strncmp(argv[i],"fallback_program=",17)==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strcmp(argv[i],"-load")==0) { - skin->do_load= 1; - - } else if(strcmp(argv[i],"-lock")==0) { - skin->do_load= 2; - - } else if(strncmp(argv[i],"-minbuf=",8)==0) { - value_pt= argv[i]+8; - goto minbuf_equals; - } else if(strncmp(argv[i],"minbuf=",7)==0) { - value_pt= argv[i]+7; -minbuf_equals:; -#ifdef Cdrskin_libburn_has_set_waitinG - skin->modesty_on_drive= 1; - sscanf(value_pt,"%lf",&value); - if (value<25 || value>95) { - fprintf(stderr, - "cdrskin: FATAL : minbuf= value must be between 25 and 95\n"); - return(0); - } - skin->min_buffer_percent= value; - skin->max_buffer_percent= 95; - ClN(printf("cdrskin: minbuf=%d percent desired buffer fill\n", - skin->min_buffer_percent)); -#else - fprintf(stderr, - "cdrskin: SORRY : Option minbuf= is not available yet.\n"); - return(0); -#endif - - } else if(strncmp(argv[i],"modesty_on_drive=",17)==0) { -#ifdef Cdrskin_libburn_has_set_waitinG - value_pt= argv[i]+17; - if(*value_pt=='0') { - skin->modesty_on_drive= 0; - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf( - "cdrskin: modesty_on_drive=0 : buffer waiting by os driver\n")); - } else if(*value_pt=='1') { - skin->modesty_on_drive= 1; - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf( - "cdrskin: modesty_on_drive=1 : buffer waiting by libburn\n")); - } else if(*value_pt=='-' && argv[i][18]=='1') { - skin->modesty_on_drive= -1; - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf( - "cdrskin: modesty_on_drive=-1 : buffer waiting as libburn defaults\n")); - } else { - fprintf(stderr, - "cdrskin: FATAL : modesty_on_drive= must be -1, 0 or 1\n"); - return(0); - } - while(1) { - value_pt= strchr(value_pt,':'); - if(value_pt==NULL) - break; - value_pt++; - if(strncmp(value_pt,"min_percent=",12)==0) { - sscanf(value_pt+12,"%lf",&value); - if (value<25 || value>100) { - fprintf(stderr, - "cdrskin: FATAL : modest_on_drive= min_percent value must be between 25 and 100\n"); - return(0); - } - skin->min_buffer_percent= value; - ClN(printf("cdrskin: modesty_on_drive : %d percent min buffer fill\n", - skin->min_buffer_percent)); - } else if(strncmp(value_pt,"max_percent=",12)==0) { - sscanf(value_pt+12,"%lf",&value); - if (value<25 || value>100) { - fprintf(stderr, - "cdrskin: FATAL : modest_on_drive= max_percent value must be between 25 and 100\n"); - return(0); - } - skin->max_buffer_percent= value; - ClN(printf("cdrskin: modesty_on_drive : %d percent max buffer fill\n", - skin->max_buffer_percent)); - } else { - fprintf(stderr, - "cdrskin: SORRY : modest_on_drive= unknown option code : %s\n", - value_pt); - } - } - skin->preskin->demands_cdrskin_caps= 1; -#else - fprintf(stderr, - "cdrskin: SORRY : Option modesty_on_drive= is not available yet.\n"); - return(0); -#endif - - } else if(strcmp(argv[i],"-multi")==0) { -#ifdef Cdrskin_libburn_has_multI - skin->multi= 1; -#else - fprintf(stderr,"cdrskin: SORRY : Option -multi is not available yet.\n"); -#endif - - } else if(strncmp(argv[i],"-msifile=",9)==0) { - value_pt= argv[i]+9; - goto msifile_equals; - } else if(strncmp(argv[i],"msifile=",8)==0) { - value_pt= argv[i]+8; -msifile_equals:; -#ifdef Cdrskin_libburn_has_multI - if(strlen(value_pt)>=sizeof(skin->msifile)) { - fprintf(stderr, - "cdrskin: FATAL : msifile=... too long. (max: %d, given: %d)\n", - (int) sizeof(skin->msifile)-1,(int) strlen(value_pt)); - return(0); - } - strcpy(skin->msifile, value_pt); - skin->do_msinfo= 1; -#else - fprintf(stderr, - "cdrskin: SORRY : Option msifile= is not available.\n"); - return(0); -#endif - - } else if(strcmp(argv[i],"-msinfo")==0) { -#ifdef Cdrskin_libburn_has_multI - skin->do_msinfo= 1; -#else - fprintf(stderr,"cdrskin: SORRY : Option -msinfo is not available.\n"); - return(0); -#endif - - } else if(strcmp(argv[i],"--no_abort_handler")==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strcmp(argv[i],"--no_blank_appendable")==0) { - skin->no_blank_appendable= 1; - - } else if(strcmp(argv[i],"--no_convert_fs_adr")==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strcmp(argv[i],"--no_rc")==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strcmp(argv[i],"-nopad")==0) { - skin->padding= 0.0; - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf("cdrskin: padding : off\n")); - - } else if(strcmp(argv[i],"--old_pseudo_scsi_adr")==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strcmp(argv[i],"-pad")==0) { - skin->padding= 15*2048; - skin->set_by_padsize= 0; - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf("cdrskin: padding : %.f\n",skin->padding)); - - } else if(strncmp(argv[i],"-padsize=",9)==0) { - value_pt= argv[i]+9; - goto set_padsize; - } else if(strncmp(argv[i],"padsize=",8)==0) { - value_pt= argv[i]+8; -set_padsize:; - skin->padding= Scanf_io_size(argv[i]+8,0); - skin->set_by_padsize= 1; - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf("cdrskin: padding : %.f\n",skin->padding)); - - } else if(strcmp(argv[i],"--prodvd_cli_compatible")==0) { - skin->prodvd_cli_compatible= 1; - - } else if(strcmp(argv[i],"-raw96r")==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strcmp(argv[i],"-sao")==0 || strcmp(argv[i],"-dao")==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strcmp(argv[i],"-scanbus")==0) { - skin->do_scanbus= 1; - - } else if(strcmp(argv[i],"--single_track")==0) { - skin->single_track= 1; - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf( -"cdrskin: --single_track : will only accept last argument as track source\n")); - skin->preskin->demands_cdrskin_caps= 1; - - } else if(strncmp(argv[i],"-speed=",7)==0) { - value_pt= argv[i]+7; - goto set_speed; - } else if(strncmp(argv[i],"speed=",6)==0) { - value_pt= argv[i]+6; -set_speed:; - if(strcmp(value_pt,"any")==0) - skin->x_speed= -1; - else - sscanf(value_pt,"%lf",&(skin->x_speed)); - if(skin->x_speed<1.0 && skin->x_speed!=0.0 && skin->x_speed!=-1) { - fprintf(stderr,"cdrskin: FATAL : speed= must be -1, 0 or at least 1\n"); - return(0); - } - if(skin->x_speed<0) - skin->preskin->demands_cdrskin_caps= 1; - - /* >>> cdrecord speed=0 -> minimum speed , libburn -> maximum speed */; - - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf("cdrskin: speed : %f\n",skin->x_speed)); - - } else if(strncmp(argv[i],"-stream_recording=",18)==0) { - value_pt= argv[i]+18; - goto set_stream_recording; - } else if(strncmp(argv[i],"stream_recording=",17)==0) { - value_pt= argv[i]+17; -set_stream_recording:; - if(strcmp(value_pt, "on")==0) - skin->stream_recording_is_set= 1; - else - skin->stream_recording_is_set= 0; - - } else if(strcmp(argv[i],"-swab")==0) { - skin->swap_audio_bytes= 0; - - } else if(strcmp(argv[i],"-tao")==0) { - /* is partly handled in Cdrpreskin_setup() */; - -#ifndef Cdrskin_allow_libburn_taO - - if(skin->tao_to_sao_tsize<=0.0) { - fprintf(stderr,"cdrskin: FATAL : libburn does not support -tao yet.\n"); - fprintf(stderr,"cdrskin: HINT : Try option tao_to_sao_tsize=650m\n"); - return(0); - } - ClN(printf("cdrskin: NOTE : substituting mode -tao by mode -sao\n")); - strcpy(skin->preskin->write_mode_name,"SAO"); - -#endif /* ! Cdrskin_allow_libburn_taO */ - - } else if(strncmp(argv[i],"tao_to_sao_tsize=",17)==0) { - skin->tao_to_sao_tsize= Scanf_io_size(argv[i]+17,0); - if(skin->tao_to_sao_tsize>Cdrskin_tracksize_maX) - goto track_too_large; - skin->preskin->demands_cdrskin_caps= 1; - -#ifndef Cdrskin_extra_leaN - if(skin->verbosity>=Cdrskin_verbose_cmD) -#ifdef Cdrskin_allow_libburn_taO - printf("cdrskin: size default for non-tao write modes: %.f\n", -#else - printf("cdrskin: replace -tao by -sao with fixed size : %.f\n", -#endif - skin->tao_to_sao_tsize); -#endif /* ! Cdrskin_extra_leaN */ - -#ifdef Cdrskin_libburn_has_get_spacE - } else if(strcmp(argv[i],"--tell_media_space")==0) { - skin->tell_media_space= 1; - skin->preskin->demands_cdrskin_caps= 1; -#endif - - } else if(strcmp(argv[i],"-toc")==0) { - skin->do_atip= 2; - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf("cdrskin: will put out some -atip style lines plus -toc\n")); - - } else if(strncmp(argv[i],"-tsize=",7)==0) { - value_pt= argv[i]+7; - goto set_tsize; - } else if(strncmp(argv[i],"tsize=",6)==0) { - value_pt= argv[i]+6; -set_tsize:; - skin->fixed_size= Scanf_io_size(value_pt,0); - if(skin->fixed_size>Cdrskin_tracksize_maX) { -track_too_large:; - fprintf(stderr,"cdrskin: FATAL : Track size too large\n"); - return(0); - } - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf("cdrskin: fixed track size : %.f\n",skin->fixed_size)); - if(skin->smallest_tsize<0 || skin->smallest_tsize>skin->fixed_size) - skin->smallest_tsize= skin->fixed_size; - - } else if(strcmp(argv[i],"-v")==0 || strcmp(argv[i],"-verbose")==0) { - /* is handled in Cdrpreskin_setup() */; - } else if(strcmp(argv[i],"-vv")==0 || strcmp(argv[i],"-vvv")==0 || - strcmp(argv[i],"-vvvv")==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strcmp(argv[i],"-version")==0) { - /* is handled in Cdrpreskin_setup() and should really not get here */; - - } else if(strcmp(argv[i],"-waiti")==0) { - /* is handled in Cdrpreskin_setup() */; - - } else if(strncmp(argv[i],"write_start_address=",20)==0) { - skin->write_start_address= Scanf_io_size(argv[i]+20,0); - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf("cdrskin: write start address : %.f\n", - skin->write_start_address)); - skin->preskin->demands_cdrskin_caps= 1; - - } else if( i==argc-1 || - (skin->single_track==0 && strchr(argv[i],'=')==NULL - && !(argv[i][0]=='-' && argv[i][1]!=0) ) || - (skin->single_track==-1)) { - if(strlen(argv[i])>=sizeof(skin->source_path)) { - fprintf(stderr, - "cdrskin: FATAL : Source address too long. (max: %d, given: %d)\n", - (int) sizeof(skin->source_path)-1,(int) strlen(argv[i])); - return(0); - } - source_has_size= 0; - strcpy(skin->source_path,argv[i]); - if(strcmp(skin->source_path,"-")==0) { - if(skin->stdin_source_used) { - fprintf(stderr, - "cdrskin: FATAL : \"-\" (stdin) can be used as track source only once.\n"); - return(0); - } - skin->stdin_source_used= 1; - } else if(argv[i][0]=='#' && (argv[i][1]>='0' && argv[i][1]<='9')) { - if(skin->preskin->allow_fd_source==0) { - fprintf(stderr, - "cdrskin: SORRY : '%s' is a reserved source path with cdrskin\n", - argv[i]); - fprintf(stderr, - "cdrskin: SORRY : which would use an open file descriptor as source.\n"); - fprintf(stderr, - "cdrskin: SORRY : Its usage is dangerous and disabled for now.\n"); - return(0); - } - } else { - if(stat(skin->source_path,&stbuf)!=-1) { - if((stbuf.st_mode&S_IFMT)==S_IFREG) - source_has_size= 1; - else if((stbuf.st_mode&S_IFMT)==S_IFDIR) { - fprintf(stderr, - "cdrskin: FATAL : Source address is a directory: '%s'\n", - skin->source_path); - return(0); - } - } - } - - if(skin->track_counter>=Cdrskin_track_maX) { - fprintf(stderr,"cdrskin: FATAL : Too many tracks given. (max %d)\n", - Cdrskin_track_maX); - return(0); - } - ret= Cdrtrack_new(&(skin->tracklist[skin->track_counter]),skin, - skin->track_counter, - (strcmp(skin->source_path,"-")==0)<<1); - if(ret<=0) { - fprintf(stderr, - "cdrskin: FATAL : Creation of track control object failed.\n"); - return(ret); - } - skin->track_counter++; - skin->use_data_image_size= 0; - if(skin->verbosity>=Cdrskin_verbose_cmD) { - if(strcmp(skin->source_path,"-")==0) - printf("cdrskin: track %d data source : '-' (i.e. standard input)\n", - skin->track_counter); - else - printf("cdrskin: track %d data source : '%s'\n", - skin->track_counter,skin->source_path); - } - /* reset track options */ - if(skin->set_by_padsize) - skin->padding= 0; /* cdrecord-ProDVD-2.01b31 resets to 30k - the man page says padsize= is reset to 0 - Joerg Schilling will change in 2.01.01 to 0 */ - skin->fixed_size= 0; - } else { -ignore_unknown:; - if(skin->preskin->fallback_program[0]) - fprintf(stderr,"cdrskin: NOTE : Unknown option : '%s'\n",argv[i]); - else - fprintf(stderr,"cdrskin: NOTE : ignoring unknown option : '%s'\n", - argv[i]); - skin->preskin->demands_cdrecord_caps= 1; - } - } - - if(flag&1) /* no finalizing yet */ - return(1); - - if(skin->preskin->fallback_program[0] && - skin->preskin->demands_cdrecord_caps>0 && - skin->preskin->demands_cdrskin_caps<=0) { - fprintf(stderr,"cdrskin: NOTE : Unsupported options found.\n"); - fprintf(stderr, - "cdrskin: NOTE : Will delegate job to fallback program '%s'.\n", - skin->preskin->fallback_program); - return(0); - } - -#ifndef Cdrskin_extra_leaN - if(skin->verbosity>=Cdrskin_verbose_cmD) { - if(skin->preskin->abort_handler==1) - printf("cdrskin: installed abort handler.\n"); - else if(skin->preskin->abort_handler==2) - printf("cdrskin: will try to ignore any signals.\n"); - else if(skin->preskin->abort_handler==3) - printf("cdrskin: installed hard abort handler.\n"); - else if(skin->preskin->abort_handler==4) - printf("cdrskin: installed soft abort handler.\n"); - else if(skin->preskin->abort_handler==-1) - printf("cdrskin: will install abort handler in eventual burn loop.\n"); - } -#endif /* ! Cdrskin_extra_leaN */ - - if(strlen(skin->preskin->raw_device_adr)>0 || - strlen(skin->preskin->device_adr)>0) { - if(strlen(skin->preskin->device_adr)>0) - cpt= skin->preskin->device_adr; - else - cpt= skin->preskin->raw_device_adr; - if(strcmp(cpt,"ATA")!=0 && strcmp(cpt,"ATAPI")!=0 && strcmp(cpt,"SCSI")!=0){ - ret= Cdrskin_dev_to_driveno(skin,cpt,&(skin->driveno),0); - if(ret<=0) - return(ret); - if(skin->verbosity>=Cdrskin_verbose_cmD) { - -#ifdef Cdrskin_libburn_has_drive_get_adR - ret= burn_drive_get_adr(&(skin->drives[skin->driveno]), adr); - if(ret<=0) - adr[0]= 0; -#else - strcpy(adr,skin->drives[skin->driveno].location); -#endif - - printf("cdrskin: active drive number : %d '%s'\n", - skin->driveno,adr); - } - } - } - if(grab_and_wait_value>0) { - Cdrskin_grab_drive(skin,16); - for(k= 0; ktrack_counter>0) { - skin->do_burn= 1; - -#ifndef Cdrskin_extra_leaN - if(!skin->do_direct_write) { - ret= Cdrskin_attach_fifo(skin,0); - if(ret<=0) - return(ret); - } -#endif /* ! Cdrskin_extra_leaN */ - - } - return(1); -} - - -/** Initialize libburn, create a CdrskiN program run control object, - set eventual device whitelist, and obtain the list of available drives. - @param o Returns the CdrskiN object created - @param lib_initialized Returns whether libburn was initialized here - @param exit_value Returns after error the proposal for an exit value - @param flag Unused yet - @return <=0 error, 1 success -*/ -int Cdrskin_create(struct CdrskiN **o, struct CdrpreskiN **preskin, - int *exit_value, int flag) -{ - int ret, stdio_drive= 0; - struct CdrskiN *skin; - char reason[4096]; - - *o= NULL; - *exit_value= 0; - - if(strlen((*preskin)->device_adr)>0) { /* disable scan for all others */ - ClN(printf( - "cdrskin: NOTE : greying out all drives besides given dev='%s'\n", - (*preskin)->device_adr)); - burn_drive_add_whitelist((*preskin)->device_adr); - if(strncmp((*preskin)->device_adr, "stdio:", 6)==0) { - ret= Cdrpreskin__allows_emulated_drives((*preskin)->device_adr+6,reason,0); - if((*preskin)->allow_emulated_drives && ret>0) { - stdio_drive= 1; - (*preskin)->demands_cdrskin_caps= 1; - } else if((*preskin)->allow_emulated_drives) { - fprintf(stderr,"cdrskin: SORRY : dev=stdio:... rejected despite --allow_emulated_drives\n"); - fprintf(stderr,"cdrskin: SORRY : Reason: %s.\n", reason); - } else { - fprintf(stderr,"cdrskin: SORRY : dev=stdio:... works only with option --allow_emulated_drives\n"); - if(ret<=0) { - fprintf(stderr,"cdrskin: SORRY : but: %s.\n", reason); - fprintf(stderr, - "cdrskin: SORRY : So this option would not help anyway.\n"); - } - } - if(!stdio_drive) { - Cdrpreskin_consider_normal_user(0); - {*exit_value= 2; goto ex;} - } - } - } - - ret= Cdrskin_new(&skin,*preskin,1); - if(ret<=0) { - fprintf(stderr,"cdrskin: FATAL : Creation of control object failed\n"); - {*exit_value= 2; goto ex;} - } - *preskin= NULL; /* the preskin object now is under management of skin */ - *o= skin; - if(skin->preskin->abort_handler==1 || skin->preskin->abort_handler==3 || - skin->preskin->abort_handler==4) - Cleanup_set_handlers(skin,(Cleanup_app_handler_T) Cdrskin_abort_handler,4); - else if(skin->preskin->abort_handler==2) - Cleanup_set_handlers(skin,(Cleanup_app_handler_T) Cdrskin_abort_handler,2|8); - - printf("cdrskin: scanning for devices ...\n"); - fflush(stdout); - - /* In cdrskin there is not much sense in queueing library messages. - It is done here only for testing it from time to time */ - Cdrpreskin_queue_msgs(skin->preskin,1); - - -#ifndef Cdrskin_oldfashioned_api_usE - if(stdio_drive) { - ret= burn_drive_scan_and_grab(&(skin->drives),skin->preskin->device_adr,0); - if(ret<=0) { - fprintf(stderr,"cdrskin: FATAL : Failed to grab emulated stdio-drive\n"); - {*exit_value= 2; goto ex;} - } - skin->n_drives= 1; - burn_drive_release(skin->drives[0].drive, 0); - } else { -#else - { -#endif /* Cdrskin_oldfashioned_api_usE */ - - while (!burn_drive_scan(&(skin->drives), &(skin->n_drives))) { - usleep(20000); - /* >>> ??? set a timeout ? */ - } - } - - /* This prints the eventual queued messages */ - Cdrpreskin_queue_msgs(skin->preskin,0); - - printf("cdrskin: ... scanning for devices done\n"); - fflush(stdout); -ex:; - return((*exit_value)==0); -} - - -/** Perform the activities which were ordered by setup - @param skin Knows what to do - @param exit_value Returns the proposal for an exit value - @param flag Unused yet - @return <=0 error, 1 success -*/ -int Cdrskin_run(struct CdrskiN *skin, int *exit_value, int flag) -{ - int ret; - - *exit_value= 0; - - if(skin->preskin->allow_setuid==0 && getuid()!=geteuid()) { - fprintf(stderr,"\n"); - fprintf(stderr,"cdrskin: WARNING : THIS PROGRAM WAS TREATED WITH chmod u+s WHICH IS INSECURE !\n"); - fprintf(stderr, - "cdrskin: HINT : Consider to allow rw-access to the writer device and\n"); - fprintf(stderr, - "cdrskin: HINT : to run cdrskin under your normal user identity.\n"); - fprintf(stderr, - "cdrskin: HINT : Option --allow_setuid disables this safety check.\n"); - fprintf(stderr,"\n"); - } - - if(skin->do_devices) { - if(skin->n_drives<=0 && skin->preskin->scan_demands_drive) - {*exit_value= 4; goto no_drive;} - ret= Cdrskin_scanbus(skin,1); - if(ret<=0) { - fprintf(stderr,"cdrskin: FATAL : --devices failed.\n"); - {*exit_value= 4; goto ex;} - } - } - if(skin->do_scanbus) { - if(skin->n_drives<=0 && skin->preskin->scan_demands_drive) - {*exit_value= 5; goto no_drive;} - ret= Cdrskin_scanbus(skin,0); - if(ret<=0) - fprintf(stderr,"cdrskin: FATAL : -scanbus failed.\n"); - {*exit_value= 5*(ret<=0); goto ex;} - } - if(skin->do_load) { - ret= Cdrskin_grab_drive(skin,8); - if(ret>0) { - if(skin->do_load==2 && !skin->do_eject) { - printf( - "cdrskin: NOTE : Option -lock orders program to exit with locked tray.\n"); - printf( - "cdrskin: HINT : Run cdrskin with option -eject to unlock the drive tray.\n"); - } else if(!skin->do_eject) - printf( - "cdrskin: NOTE : option -load orders program to exit after loading tray.\n"); - Cdrskin_release_drive(skin,(skin->do_load==2)<<1); - } - {*exit_value= 14*(ret<=0); goto ex;} - } - if(skin->do_checkdrive) { - ret= Cdrskin_checkdrive(skin,"",(skin->do_checkdrive==2)<<1); - {*exit_value= 6*(ret<=0); goto ex;} - } - if(skin->do_msinfo) { - if(skin->n_drives<=0) - {*exit_value= 12; goto no_drive;} - ret= Cdrskin_msinfo(skin,0); - if(ret<=0) - {*exit_value= 12; goto ex;} - } - if(skin->do_atip) { - if(skin->n_drives<=0) - {*exit_value= 7; goto no_drive;} - ret= Cdrskin_atip(skin,(skin->do_atip>1)); - if(ret<=0) - {*exit_value= 7; goto ex;} - } - if(skin->do_list_formats) { - if(skin->n_drives<=0) - {*exit_value= 14; goto no_drive;} - ret= Cdrskin_list_formats(skin, 0); - if(ret<=0) - {*exit_value= 14; goto ex;} - } - if(skin->do_blank) { - if(skin->n_drives<=0) - {*exit_value= 8; goto no_drive;} - ret= Cdrskin_blank(skin,0); - if(ret<=0) - {*exit_value= 8; goto ex;} - } - -#ifdef Cdrskin_libburn_has_random_access_rW - if(skin->do_direct_write) { - skin->do_burn= 0; - ret= Cdrskin_direct_write(skin,0); - if(ret<=0) - {*exit_value= 13; goto ex;} - } -#endif /* Cdrskin_libburn_has_random_access_rW */ - - if(skin->do_burn || skin->tell_media_space) { - if(skin->n_drives<=0) - {*exit_value= 10; goto no_drive;} - ret= Cdrskin_burn(skin,0); - if(ret<=0) - {*exit_value= 10; goto ex;} - } -ex:; - return((*exit_value)==0); -no_drive:; - fprintf(stderr,"cdrskin: FATAL : This run would need an accessible drive\n"); - goto ex; -} - - -int main(int argc, char **argv) -{ - int ret,exit_value= 0,lib_initialized= 0,i,result_fd= -1; - struct CdrpreskiN *preskin= NULL, *h_preskin= NULL; - struct CdrskiN *skin= NULL; - char *lean_id= ""; -#ifdef Cdrskin_extra_leaN - lean_id= ".lean"; -#endif - - /* For -msinfo: Redirect normal stdout to stderr */ - for(i=1; in_drives<=0) { - fprintf(stderr,"cdrskin: NOTE : No usable drive detected.\n"); - if(getuid()!=0) { - fprintf(stderr, - "cdrskin: HINT : Run this program as superuser with option --devices\n"); - fprintf(stderr, - "cdrskin: HINT : Allow rw-access to the dev='...' file of the burner.\n"); - fprintf(stderr, - "cdrskin: HINT : Busy drives are invisible. (Busy = open O_EXCL)\n"); - } - } - - ret= Cdrskin_setup(skin,argc,argv,0); - if(ret<=0) - {exit_value= 3; goto ex;} - if(skin->verbosity>=Cdrskin_verbose_cmD) - ClN(printf("cdrskin: called as : %s\n",argv[0])); - - if(skin->verbosity>=Cdrskin_verbose_debuG) { -#ifdef Cdrskin_oldfashioned_api_usE - ClN(fprintf(stderr,"cdrskin_debug: Compiled with option -oldfashioned\n")); -#endif -#ifdef Cdrskin_new_api_tesT - ClN(fprintf(stderr,"cdrskin_debug: Compiled with option -experimental\n")); -#endif - } - - Cdrskin_run(skin,&exit_value,0); - -ex:; - if(preskin!=NULL) - h_preskin= preskin; - else if(skin!=NULL) - h_preskin= skin->preskin; - if(h_preskin!=NULL) { - if(skin!=NULL) - if(skin->verbosity>=Cdrskin_verbose_debuG) - ClN(fprintf(stderr, - "cdrskin_debug: demands_cdrecord_caps= %d , demands_cdrskin_caps= %d\n", - h_preskin->demands_cdrecord_caps, h_preskin->demands_cdrskin_caps)); - - if(exit_value && h_preskin->demands_cdrecord_caps>0 && - h_preskin->demands_cdrskin_caps<=0) { /* prepare fallback */ - /* detach preskin from managers which would destroy it */ - preskin= NULL; - if(skin!=NULL) - skin->preskin= NULL; - } else - h_preskin= NULL; /* prevent fallback */ - } - if(skin!=NULL) { - Cleanup_set_handlers(NULL,NULL,1); - if(skin->preskin!=NULL) - Cdrskin_eject(skin,0); - Cdrskin_destroy(&skin,0); - } - Cdrpreskin_destroy(&preskin,0); - if(lib_initialized) - burn_finish(); - if(h_preskin!=NULL) - Cdrpreskin_fallback(h_preskin,argc,argv,0); /* never come back */ - exit(exit_value); -} diff --git a/cdrskin/cdrskin_eng.html b/cdrskin/cdrskin_eng.html deleted file mode 100644 index 638a468..0000000 --- a/cdrskin/cdrskin_eng.html +++ /dev/null @@ -1,500 +0,0 @@ - - - - - - -cdrskin homepage english - - - - - -
- -cdrskin logo: Doener mit Scharf - -

Homepage of

-

cdrskin

- -

Limited cdrecord compatibility wrapper for libburn

-
- -

-

Purpose:

-Burns preformatted data to CD, DVD, and BD media:
-CD-R, DVD-R, DVD+R, DVD+R/DL, CD-RW, DVD-RW, DVD-RAM, DVD+RW, BD-RE -

-

- -


- -Direct hop to download links -> - -

-

Hardware requirements:

-A CD/DVD/BD recorder suitable for -http://libburnia-project.org
-(SCSI , ATA , USB , or SATA writers compliant to standard MMC-3 for CD -and to MMC-5 for DVD or BD). -
-

- -

-

Software requirements :

-
-
Linux with kernel 2.4 or higher (and libc, of course) :
-
With kernel 2.4 an ATA drive has to be under ide-scsi emulation.
-
With kernel 2.6 the drive should not be under ide-scsi.
-
libpthread
-
is supposed to be a standard system component.
-
-

- -

-

-GPL software included:
-

-
-
libburn-0.4.6
-
(founded by Derek Foreman and Ben Jansens, -furthered by team of libburnia-project.org)
-
transfers data to CD and DVD
-
-

- -

-This program system has been tested on Intel/AMD Linux systems only.
-Ports to other usable systems are appreciated. Reports are welcome. -

- -
- -

-

Special features:

-
    -
  • Source code is independent of -cdrecord -
  • -
-

- -

-

Commands:

-
-
The most common options of cdrecord for data and audio on CD media -are provided in a compatible way.
-On all DVD media except DVD-R DL, cdrskin is able to perform any recording job -which is possible with cdrecord. -Other than with cdrecord, options -multi and -tao are supported with -most DVD types and with BD-RE. -
-

-
Get an overview of drives and their addresses
-
# cdrskin -scanbus
-
# cdrskin dev=ATA -scanbus
-
# cdrskin --devices
-
Being superuser avoids permission problems with /dev/srN resp. /dev/hdX . -
-
Ordinary users should then get granted rw access to the /dev files -as listed by option --devices.
-
 
- -
Get info about a particular drive or loaded media:
-
$ cdrskin dev=0,1,0 -checkdrive
-
$ cdrskin dev=ATA:1,0,0 -v -atip
-
$ cdrskin dev=/dev/hdc -toc
- -
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
- -
Format DVD-RW to avoid need for blanking before re-use:
-
$ cdrskin -v dev=/dev/sr0 blank=format_overwrite
- -
De-format DVD-RW to make it capable of multi-session again:
-
$ cdrskin -v dev=/dev/sr0 blank=deformat_sequential
- -
Write ISO-9660 filesystem image as only one to blank or formatted media: -
-
$ cdrskin -v dev=/dev/hdc speed=12 fs=8m \
-
  blank=as_needed -eject padsize=300k my_image.iso
- -
Write compressed afio archive on-the-fly:
-
$ find . | afio -oZ - | \
-
  cdrskin -v dev=0,1,0 fs=32m speed=8 \
-
  blank=as_needed padsize=300k -
- -
Write several sessions to the same CD, DVD-R[W] or DVD+R[/DL]:
-
$ cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 1.iso -
-
$ cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 2.iso -
-
$ cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 3.iso -
-
$ cdrskin dev=/dev/hdc -v padsize=300k -tao 4.iso
- -
Get multi-session info for option -C of program mkisofs:
-
$ c_values=$(cdrskin dev=/dev/sr0 -msinfo 2>/dev/null)
-
$ mkisofs ... -C "$c_values" ...
- -
Inquire free space on media for a -tao -multi run:
-
$ x=$(cdrskin dev=/dev/sr0 -tao -multi \
-
  --tell_media_space 2>/dev/null)
-
$ echo "Available: $x blocks of 2048 data bytes"
- -
Write audio tracks to CD:
-
$ cdrskin -v dev=ATA:1,0,0 speed=48 -sao \
-
  track1.wav track2.au -audio -swab track3.raw
- -
Get overview of the cdrecord compatible options:
-
$ cdrskin -help
- -
Get overview of the non-cdrecord options:
-
$ cdrskin --help
- -
Read the detailed manual page:
-
$ man cdrskin
-
-
-
Read about the standard for which cdrskin is striving:
-
$  - -man cdrecord
-
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.) -
-
-
-
Learn to know a more versatile way to burn ISO 9660 formatted data
-
-Standalone ISO 9660 multi-session CD/DVD tool -xorriso. -
-
- -Testers wanted who are willing to risk some DVD-R DL media -or to do experiments on BD-R media. - -

- -
- - - -

-

-
Download as source code (see README):
-
cdrskin-0.4.6.pl00.tar.gz -(730 KB). -
-
-The cdrskin tarballs are source code identical with libburn releases -of the same version number. -They get produced via a different procedure, though.
-cdrskin is part of libburn - full libburn is provided with cdrskin releases. -
- - - - -
-
Documentation:
-
README an introduction
-
cdrskin --help non-cdrecord options
-
cdrskin -help cdrecord compatible options
-
man cdrskin the manual page
-
 
-
-
Contact:
-
Thomas Schmitt, scdbackup@gmx.net
-
libburn development mailing list, -libburn-hackers@pykix.org
-
-
License:
-
GPL, an Open Source approved license
-
 
-
-

- -
- -

-Enhancements towards previous stable version cdrskin-0.4.4.pl00: -

    -
  • Support for BD-RE media is now official
  • -
  • New option stream_recording=on can speed up DVD-RAM and BD-RE
  • -
  • New option --list_formats
  • -
  • New blank types for expert formatting of DVD-RAM and BD-RE
  • -
  • New blank type blank=as_needed for automatic handling -of media type and state
  • -
- - - -

- -
- -

-

-

Development snapshot, version 0.4.7 :

-
Enhancements towards current stable version 0.4.6.pl00: -
    - -
  • none yet
  • - -
-
-
 
-
README 0.4.7 -
cdrskin_0.4.7 --help
-
cdrskin_0.4.7 -help
-
man cdrskin (as of 0.4.7)
-
 
-
Maintainers of cdrskin unstable packages please use SVN of - libburnia-project.org
-
Download: svn co http://svn.libburnia-project.org/libburn/trunk libburn -
-
Build: cd libburn ; ./bootstrap ; ./configure --prefix /usr ; make ; cdrskin/compile_cdrskin.sh -
-
Build of SVN versions needs -autotools of at least version 1.7 installed. -But after the run of ./bootstrap, only -vanilla tools like make and gcc are needed.
- -
 
-
The following download is intended for adventurous end users or -admins with full system souvereignty.
-
Source (./bootstrap is already applied, build tested, for more see -upcoming README ): -
-
-cdrskin-0.4.7.tar.gz -(730 KB). -
- - - -
-

- -
- -

-Many thanks to Joerg Schilling for cdrecord, -
-and to Derek Foreman and Ben Jansens for creating libburn. -
-Historic versions based on Derek's and Ben's -icculus.org/burn :
-cdrskin-0.1.2.0.2.ts.tar.gz
-cdrskin-0.1.3.0.2.ts.tar.gz -
-Very special thanks to Andy Polyakov whose -dvd+rw-tools -provide libburn with invaluable examples on how to deal with DVD media. -

- -
- - -

-

-
Example for a setup of device permissions. To be done by the superuser:
-
(CD devices which offer no rw-permission are invisible to normal users.) -
-
# cdrskin --devices
-
...
-
0  dev='/dev/sr0'  rwrwr- :  'TEAC' 'CD-ROM CD-532S'
-
1  dev='/dev/hdc'  rwrw-- :  'LITE-ON' 'LTR-48125S'
-
# chmod a+rw /dev/sr0 /dev/hdc
-
-

- -
- -
-

- -Example how to setup K3b to use cdrskin for burning data CD projects. -
-(
K3b -is a GUI frontend which uses cdrecord for CD burning.) -

- - - -
- - -

-

About the relationship of cdrecord and cdrskin

-First of all: this relationship is single sided, as cdrskin has to be aware of -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 not problem with it. -
-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). -One has to be aware, though, that this relationship might lead to a situation -where cdrecord is no longer available for certain Linux kernels. -
-To have my own project prepared for such a time, i began to implement its -cdrecord gestures on top of libburn. -From now on i invite other interested users of cdrecord to teach cdrskin -the gestures necessary for their cdrecord applications. -Contact me. Let's see what we can achieve. -
-
-libburn and cdrskin are now mature enough to substitute cdrecord in its -major use cases of CD and DVD burning. It is possible to foist cdrskin on -various software packages if it gets falsely named "cdrecord". -I do not encourage this approach, but of course such a replacement -opportunity is the goal of a cdrecord compatibility wrapper. -
-
-It is very important to me that this project is not perceived as hostile -towards Joerg Schilling and his ongoing work. -I owe him much. For cdrecord, for mkisofs, for star. Chapeau. -
-

-
- -
- - -cdrskin logo: Doener mit Scharf -

-Enjoying free Open Source hosting by www.webframe.org
- -100 % Microsoft free
-and by sourceforge.net
- -SourceForge Logo - -
-
-
-
Links to my other published software projects : -
-xorriso, a standalone ISO 9660 multi-session CD/DVD burn tool. -No mkisofs needed. -
-
- -(a second source of above) -
-
-
-
-scdbackup, multi volume CD backup -
-(a second source of above)
-
Some Tools for Image Collectors -
-
-pppoem, a DSL throughput monitor (mainly for Linux kernel 2.4) -
-
-

-Legal statement: This website does not serve any commercial purpose.
-
- - diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h deleted file mode 100644 index ae3d365..0000000 --- a/cdrskin/cdrskin_timestamp.h +++ /dev/null @@ -1 +0,0 @@ -#define Cdrskin_timestamP "2008.05.10.080001" diff --git a/cdrskin/changelog.txt b/cdrskin/changelog.txt deleted file mode 100644 index 61732f3..0000000 --- a/cdrskin/changelog.txt +++ /dev/null @@ -1,5561 +0,0 @@ ------------------------------------------------------------------------------- - libburnia-project.org scdbackup.sourceforge.net/cdrskin ------------------------------------------------------------------------------- - -Deliberate deviations of cdrskin from cdrecord compatibility: - -+ cdrskin does drive operations (on its drive 0) without a dev= option - (Note: cdrecord meanwhile has a default for missing dev= option.) - -+ gracetime=0 is allowed and set by default - -+ -pad is always set for audio tracks - -+ -sao is default where possible, -tao is default where needed - (Note: cdrecord write mode defaults have changed in cdrtools-2.01.01a20) - -+ driveropts=burnfree is default if the drive supports buffer underrun - protection. If desired, use driveropts=noburnfree to disable this feature. - -+ premature end of source is not an error and leads to full announced tracksize - -+ -msinfo pushes all other messages to stderr. It works independently of - other options which would prevent it with cdrecord (-atip, -scanbus, ...) - -+ DVD track sources get not concateneated to a single track. In general DVD - writing is quite different from cdrecord-ProDVD: - DVD-R[W] "Disc-at-once" (-sao) is nearest to cdrecord-ProDVD's methods. - DVD-R[W] "Incremental Streaming" (-tao) on unformatted media allows - multi-session and track sources of unpredictable size. - Writing DVD-RAM, DVD+RW and "Restricted Overwrite" DVD-RW is like single - track -tao on blank CD. Formatting is done via cdrskin-specific - blank=format_overwrite and not with option -format. - -+ DVD-RW get blanked fast only with option blank=deformat_sequential_quickest . - Option blank=fast is the same as blank=all in order to achieve media which - are capable of Incremental Streaming. - -+ It has not been evaluated how far -isosize is compatible with the original - cdrecord option. man cdrecord forbids stdin as source, cdrskin allows it - if a fifo is used. - - ------------------------------------------------------------------------------- - Changelog ------------------------------------------------------------------------------- - -19 Aug 2006 [committed] -README -cdrskin/README cdrskin/cdrskin.c cdrskin/add_ts_changes_to_libburn_0_2_1 \ -cdrskin/cdrskin_timestamp.h cdrskin/compile_cdrskin.sh -cdrskin-0.1.4 "stable" released on base of August 15 2006 version of -libburn-svn.pykix.org/trunk after initial merge of libburn and cdrskin-0.1.3 . - ------------------------------------------------------------------------------- - -19 Aug 2006 [committed 16] -cdrskin/changelog.txt -cdrskin-0.1.5 development started. -Introduced this changelog. ----------------------------------- Format (still emerging): - -Day Month Year [eventual commit mark with revision number] -affected files , naked, one by line, -[eventually = internal snapshot tarball] -More ore less concise description. - ----------------------------------- End of Format - -20 Aug 2006 [committed together with next change, i fear] -libburn/sg.c -Hopefully fixed a file descriptor resource leak in sg_grab(). -All scanned drives (seem to) stay open once, the grabbed one got re-opened -and its stored first file descriptor got forgotten. Now we try to detect -and re-use the still open fd. - -21 Aug 2006 [committed] -libburn/libburn.h -libburn/sg.c -libburn/init.c -= libburn_cdrskin_A60819.tgz -cdrskin/cdrskin.c [committed later as revision 11] -O_EXCL experiments imported from cdrskin-0.1.3 -In default configuration and on compliant kernels expect that a busy drive is -invisible to further cdrskin instances. The user gets hints in case of empty -bus scan result resp. busy drive given with dev=... -Wether cdrecord and cdrskin respect each other would have to be evaluated. -Options to play with: - --demand_a_drive exit !=0 on bus scans with empty result - --drive_abort_on_busy abort process if busy drive is found - (might be triggered by a busy hard disk) - --drive_blocking try to wait for busy drive to become free - (might be stalled by a busy hard disk) - --drive_not_exclusive do not ask kernel to prevent opening - busy drives. Effect is kernel dependend. - grab_drive_and_wait= grab drive, wait given number of - seconds, release drive, and do normal work - -21 Aug 2006 [committed] -libburn/write.c -Rectified non-ANSI-C comment, complained by gcc. - -21 Aug 2006 [committed 13] -cdrskin/cdrskin_eng.html -The homepage moved in from scdbackup's internal doc collection. - -21 Aug 2006 [committed with revision 11, i fear] -cdrskin/cdrskin.c -Removed flaw: -Help text of tao_to_sao_tsize= clarified. - -21 Aug 2006 [committed 12] -cdrskin/wiki_plain.txt -The initial filling of the cdrskin wiki on libburn.pykix.org . -I am not sure about the future fate of this text. I plan to keep it up to -date with the online wiki for now. The online version will be considered -the original. - -21 Aug 2006 [committed 15] -cdrskin/cdrskin_timestamp.h -Timestamping the new version. - -21 Aug 2006 [committed 14] -cdrskin/add_ts_changes_to_libburn_0_2_1 -cdrskin/compile_cdrskin.sh -Readjusted relationship glue of libburn and cdrskin. - ---------------------------------------------------------------------- cycled - - -27 Aug 2006 [40] -libburn/mmc.c -libburn/sg.c -Inserted prints to see how sg_issue_command() is called (printing is disabled now) - -21 Aug 2006 [17] -README -Reported obvious need for automake >=1.7 - -21 Aug 2006 [18] -cdrskin/cdrskin_eng.html -cdrskin/README -Reported obvious need for automake >=1.7 - -22 Aug 2006 [19] -libburn/drive.c -libburn/drive.h -New internal function burn_drive_is_open() - -23 Aug 2006 [20] -cdrskin/cdrskin.c -Implemented Lorenzo Taylor's audio patch manually by copy+paste -as i wanted to fully understand it. -Hopefully did not break it that way. - -24 Aug 2006 [21] -libburn/libburn.h -libburn/drive.c -Introduced API functions burn_drive_scan_and_grab() burn_drive_get_adr() - -24 Aug 2006 [22] -cdrskin/compile_cdrskin.sh -Experimental option cdrskin/compile_cdrskin.sh -newapi - -24 Aug 2006 [23] -cdrskin/cdrskin.c -First test of possibility to obey the self imposed rules of Revison 21 - -24 Aug 2006 [25] -cdrskin/cdrskin.c -Fixed undefined track_type introduced by revision 20. -(We broke cdrskin, but i did not break the patch. Success.) - -24 Aug 2006 [30] -libburn/libburn.h -Hopefully fixed an unintended line break in API doxygen - -25 Aug 2006 [32] -cdrskin/cdrskin.c -Installed protection against resource leak in Cdrskin_grab_drive() -Just to be sure. - -25 Aug 2006 [33] -libburn/drive.c -burn_drive_free() now closes all open drive file descriptors - -25 Aug 2006 [34] -libburn/libburn.h -Adjusted statement at API documention of burn_initialize() - -25 Aug 2006 [35] -cdrskin/cdrskin.c -Worked forth in order to make cdrskin fully newapi compliant - -26 Aug 2006 [37] -Makefile.am -libburn/back_hacks.h -libburn/drive.c -libburn/init.c -Allowed to blank appendable files and installed first back_hacks.h variable ever - -26 Aug 2006 [38] -test/burniso.c -Rewrote it to new API practice, inflated explanation comments, SAO mode - -27 Aug 2006 [39] -cdrskin/cdrskin.c -Implemented Lorenzos blank-appendable patch plus option --no_blank_appendable - -27 Aug 2006 [44] -test/blank.c -Rewrote test/blank.c to new API practice, inflated explanation comments - -27 Aug 2006 [41] -cdrskin/cdrskin.c -Fixed obscure sigsegv introduced with 35 or 39 by obeying libburn.h text -(could be a fandango starting in burn_drive_info_free) - -27 Aug 2006 [45] -test/burniso.c -Disabled inner burn_drive_info_free like in cdrskin, polished a bit - -27 Aug 2006 [43] -libburn/libburn.h -Changed some 'release' to 'close' with specs of burn_drive_scan_and_grab - -28 Aug 2006 [46] -test/burniso.c -Polished a bit more for doxygen - -28 Aug 2006 [50] -libburn/libburn.h -cdrskin/cdrskin.c -Wrote into API the imperative not to use drive.location but burn_drive_get_adr - -28 Aug 2006 [47] -test/burniso.c -Integrated functionality of test/devices.c into test/burniso.c -Proposed to rename it to test/libburner.c - -28 Aug 2006 [51] -cdrskin/cdrskin.c -Closed a pitfall with reading from '-' and no tsize= or tao_to_sao_tsize= -Ticket 55 - -28 Aug 2006 [52] -cdrskin/cdrskin.c -Added personal commitment to grant BSD license on request. Insisted in GPL for now. - -28 Aug 2006 [53] -cdrskin/cdrskin.c -Forced each track to have a minimum size of 600 kB -Ticket 55 - -29 Aug 2006 [58] -test/burniso.c -Integrated functionality of test/blank.c into test/burniso.c - -29 Aug 2006 [55] -cdrskin/cdrskin.c -Made cdrskin ready to make good use of now working libburn-eject - -29 Aug 2006 [56] -cdrskin/cdrskin.c -Avoided unwanted tray loading on eject of never grabbed drive - -29 Aug 2006 [57] -cdrskin/cdrskin.c -Disabled unconditionality of eject introduced by 55 or 56 - -30 Aug 2006 [59] -test/burniso.c -Repaired SIGSEGV caused by releasing ungrabbed drive after mere bus scan - -30 Aug 2006 [60] -test/libburner.c -Makefile.am -My proposal for new souvereign app as API doc and reference for API decisions - -31 Aug 2006 [61] -libburn/sg.c -cdrskin/cdrskin.c -Outcommented "experimental:" messages of O_EXCL development - -31 Aug 2006 [62] -test/libburner.c -Added 300 kB of padding to get rid of warning in doc, plus end sector padding - -31 Aug 2006 [63] -cdrskin/cdrskin.c -Promoted "newapi" functionality and libburn-eject from test to standard - -31 Aug 2006 [64] -cdrskin/cdrskin.c -Made cdrskin abort if fifo filling before burn yields 0 bytes (ticket 55) - -1 Sep 2006 [65] -cdrskin/README -cdrskin/cdrskin.c -cdrskin/cdrskin_eng.html -Updated cdrskin help tests and docs: -audio, obsolete eject_device= - -1 Sep 2006 [66] -libburn/write.c -cdrskin/cdrskin.c -Implemented track number patch by bonfire-app@wanadoo.fr, tickets 58 and 9 - -1 Sep 2006 [67] -cdrskin/cdrskin.c -Added clarifying URGE to ABORT texts - -1 Sep 2006 [71] -test/libburner.c -Made "read-ahead" comment sufficiently ambigous: "buffer"|"filesystem" == "" - -1 Sep 2006 [72] [73] -cdrskin/cdrskin.c -cdrskin/compile_cdrskin.sh -Rowed back from revision 64. Now #ifdef Cdrskin_fifo_abort_on_emptY - -1 Sep 2006 [74] -cdrskin/cdrskin.c -cdrskin/compile_cdrskin.sh -Rowed forth from revision 73. Now hopefully compliant to man cdrecord. - -1 Sep 2006 [78] -cdrskin/cdrskin.c -Made -pad behave cdrecord-ly on audio tracks (not tested acousticly) - -2 Sep 2006 [85] -test/libburner.c -Added upcoming clarification of copyright and license aspiration - -3 Sep 2006 [86] -README -Added upcoming clarification of copyright and license aspiration - -3 Sep 2006 [87] [88] -cdrskin/README -cdrskin/cdrskin.c -Added upcoming clarification of copyright and license aspiration - -3 Sep 2006 [91] -cdrskin/changelog.txt -cdrskin/cdrskin_timestamp.h -Opened new cdrskin-0.1.5 upload cycle. This marks a should-be-stable phase. - ----------------------------------------------------- cycled - 2006.09.03.132934 - - -3 Sep 2006 [89] -doc/comments_test_ts -Made a try to get doxygen portal page readable by html dl lists - -4 Sep 2006 [92] -cdrskin/README -Made changes as reported by Lorenzo on libburn-hackers today - -4 Sep 2006 [93] -libburn/transport.h -libburn/drive.h -libburn/drive.c -libburn/init.c -libburn/libburn.h -Integrated elmom patch proposal #3 from ticket #62 -/* ts A60904 : ticket 62, contribution by elmom */ - -4 Sep 2006 [94] -cdrskin/README -Removed reference to frontend "burn" (needs a patch to work for .mp3) - -5 Sep 2006 [95] -doc/comments_test_ts -Made a try to get doxygen portal page readable by pre tags and truncation - -5 Sep 2006 [96] -test/libburner.c -Rearranged definitions and header inclusions. Is safer so. - -5 Sep 2006 [97] -test/libburner.c -Re-inserted lost tab. - -6 Sep 2006 [trac] -closed ticket 55: burn of empty tracks from stdin is now forbidden - -6 Sep 2006 [98] -libburn/libburn.h -libburn/drive.c -Added new parameter "force" to API-experimental burn_drive_info_forget() - -6 Sep 2006 [99] -doc/comments -Made doc test portal the official doc portal - -6 Sep 2006 [100] -cdrskin/cdrfifo.c -Added an initial value on proposal by Bart Vanherck - -7 Sep 2006 [101] -test/libburner.c -Changed a macro name from Burniso_ to Libburner_ - -7 Sep 2006 [102] [103] -libburn/libburn.h -libburn/drive.c -cdrskin/cdrskin.c -Implemented first use of API-experimental burn_drive_info_forget() in cdrskin signal handler - -7 Sep 2006 [104] -cdrskin/cdrskin.c -Tried to make abort messages clearer - -7 Sep 2006 [105] -Makefile.am -test/testburner.c -Prepared test bed for burn_drive_info_forget() as regular API call - -7 Sep 2006 [106] -test/testburner.c -Removed a remnant piece of rather unhealthy test code - -7 Sep 2006 [106] -test/testburner.c -Corrected test reciepe - -7 Sep 2006 [107] -test/libburner.c -Added constraint --stdin_size >= 600k, better bus scan behavior - -8 Sep 2006 2006 [109] -libburn/drive.c -test/testburner.c -cdrskin/cdrskin.c -Hopefully ensured correct burn_disc_erasable() already after first grab - -9 Sep 2006 2006 [112] -libburn/drive.c -cdrskin/cdrskin.c -Hunted down the bug which let newapi-cdrskin fail with drive 1 - -10 Sep 2006 [113] -libburn/drive.c -test/libburner.c -test/testburner.c -cdrskin/cdrskin.c -Slowed down highspeed loops waiting for drive status changes - -10 Sep 2006 [114] -cdrskin/compile_cdrskin.sh -Aliased switch name -newapi by -experimental - -10 Sep 2006 [115] -test/libburner.c -test/testburner.c -cdrskin/cdrskin.c -Re-enabled call to burn_drive_info_free() after repair by revision 93 - -11 Sep 2006 [116] -cdrskin/compile_cdrskin.sh -Changed -newapi to -experimental in help text - -11 Sep 2006 [117] -libburn/drive.c -Removed a bug introduced with revison 93 - -11 Sep 2006 [118] -libburn/libburn.h -test/libburner.c -Officialized burn_drive_info_forget() - -11 Sep 2006 [119] [120] -Makefile.am -test/testburner.c -Deleted until next occasion: testburner - -12 Sep Sep 2006 [124] -cdrskin/cdrskin.c -Repaired regression of -eject which loaded tray again - -12 Sep 2006 [126] -cdrskin/cdrskin.c -Replaced -experimental method of closing libburn by burn_drive_info_forget() - -12 Sep 2006 [129] -cdrskin/cdrskin.c -Added automated padding to last audio track (ticket 41) - -2006.09.13.093350 [130] -cdrskin/make_timestamp.sh -Prepared for new revision timestamps to mark cdrskin test versions -From now on cdrskin/cdrskin_timestamp.h is to be part of any commit. - -15 Sep 2006 [135] -Makefile.am -Replaced a few 8-blanks by tab - -15 Sep 2006 [136] -README -Moved installation instructions in front of overview paragraph - -15 Sep 2006 [137] -Makefile.am -cdrskin/README -Made cdrskin an installable program - -2006.09.15.092509 [138] -cdrskin/cdrskin.c -cdrskin/compile_cdrskin.sh -Prepared cdrskin-build for version leap - - ------------------------------ cycled (last cdrskin-0.1.5 ?) - 2006.09.15.101326 - -2006.09.15.101326 [139] -cdrskin/README -cdrskin/changelog.txt -New upload of scdbackup.sourceforge.net/cdrskin-0.1.5.tar.gz - -2006.09.15.174748 [143] -cdrskin/cdrskin.c -Revoked change of 1 Sep 2006 revision 78 (full -nopad) (ticket 41) - -16 Sep 2006 [144] -libburn/libburn.h -Made doxygen happy with parameter of burn_drive_get_adr - -2006.09.16.194730 [145] -000_CAUTION_RELEASE_CANDIDATE -zzz_CAUTION_RELEASE_CANDIDATE -README -Makefile.am -cdrskin/README -cdrskin/cdrskin.c -cdrskin/compile_cdrskin.sh -Perfomed version leap in respect to SVN - -2006.09.19.124540 [160] [161] -cdrskin/cdrskin.c -Allowed driveropts=burnproof as alias for burnfree - -2006.09.19.140716 [162] [163] -cdrskin/cdrskin.c -Added error message in case of failed eject - -2006.09.20.134219 [175] [176] [177] -cdrskin/cdrskin.c -Fixed bug with dev=1,1,0 (ticket 75) - -21 Sep 2006 [186] -configure.ac -Makefile.am -Forwarded changes from 0.2.2 to 0.2.3 - -Sep 2006 [187] [188] [189] [190] -cdrskin/cdrskin.c -cdrskin/compile_cdrskin.sh -cdrskin/cdrskin_eng.html -cdrskin/README -cdrskin/changelog.txt -- cdrskin/add_ts_changes_to_libburn_0_2_1 -+ cdrskin/add_ts_changes_to_libburn_0_2_3 -Makefile.am -cdrskin/cdrskin_timestamp.h -Performed development version leap to cdrskin-0.2.3 - ------------------------------------- cycled - cdrskin-0.2.3 - 2006.09.21.082411 - -21 Sep 2006 [191] -README -Clarified build from SVN versus tarball - -2006.09.21.173012 [192] -cdrskin/cdrskin.c -cdrskin/compile_cdrskin.sh -Gave up compile options -tarball_0_2 , -cvs_A51208 , -libburn_0_2_1 -Now standard and therefore no longer needed as macros: -Cdrskin_libburn_p_sectoR -Cdrskin_libburn_with_fd_sourcE -Cdrskin_libburn_largefilE -Cdrskin_libburn_padding_does_worK - -2006.09.21.185623 [193] -cdrskin/cdrskin.c -cdrskin/compile_cdrskin.sh -Officialized gestures of pre-0.2.3 -experimental, introduced -oldfashioned - -2006.09.21.194006 [194] -cdrskin/cdrskin.c -Investigating failure to open drive on eject - -2006.09.22.133027 [195] -libburn/libburn.h -libburn/sg.c -libburn/sg.h -libburn/drive.c -cdrskin/cdrskin.c -Implemented resolving of softlinks (ticket 33) - -2006.09.22.170220 [196] -libburn/libburn.h -libburn/sg.c -libburn/sg.h -libburn/drive.c -cdrskin/cdrskin.c -Implemented new API function burn_drive_convert_fs_adr() - - -2006.09.22.172307 [197] -cdrskin/cdrskin.c -Fixed SIGSEGV of -eject on non-existent device address - -22 Sep 2006 [198] -libburn/sg.c -libburn/sg.h -libburn/drive.c -Implemented finding matching /dev/sgN from /dev/srM or /dev/scdK -(ioctl(): SCSI_IOCTL_GET_IDLUN) - -2006.09.22.195414 [199] -cdrskin/cdrskin.c -Removed bug prone implementation of link resolving (now only via libburn) - -2006.09.22.202631 [200] -cdrskin/cdrskin.c -Kept new address conversion from hopping on libburn drive numbers - -2006.09.22.203939 [201] -cdrskin/cdrskin.c -Fixed --no_follow_links and renamed to --no_convert_fs_adr - -2006.09.23.080015 [202] -libburn/drive.c -Restructured SCSI search, removed a potential bug with hdX - -23 Sep 2006 [203] -libburn/libburn.h -Made burn_drive_convert_scsi_adr() a new API function - -23 Sep 2006 [204] -libburn/drive.c -libburn/sg.c -Changed outdated comments - -23 Sep 2006 [205] -libburn/libburn.h -libburn/drive.c -Introduced new API function burn_drive_obtain_scsi_adr() - -2006.09.23.100001 [not in libburn-0.2.2 yet] -cdrskin-0.2.2/cdrskin/cdrskin.c -Backported bug fix of revision 197. Version timestamp : 2006.09.23.100001 - -23 Sep 2006 [206] [207] -libburn/drive.c -libburn/sg.c -Enabled unused SCSI part of struct burn_drive. Switched persistent address to burn_drive.devname - -2006.09.23.114858 [208] -cdrskin/cdrskin.c -Implemented --no_pseudo_scsi_adr - -2006.09.23.132755 [209] -cdrskin/cdrskin.c -libburn/drive.c -Removed a bug with SCSI address of scanned drives without such address - -23 Sep 2006 [210] -cdrskin/README -Explained the new addressing mode - -2006.09.23.182444 [211] -cdrskin/README -cdrskin/cdrskin.c -Bus,Target,Lun for dev=ATA and dev=ATAPI, real SCSI addressing by default - -2006.09.23.183608 [212] -cdrskin/cdrskin.c -Made small improvement with debug message - -2006.09.24.171706 [214] -Makefile.am -libburn/libburn.h -libburn/libdax_msgs.h -libburn/libdax_msgs.c -libburn/init.c -cdrskin/compile_cdrskin.sh -cdrskin/cdrskin.c -Added an error message handling facility (ticket 74) - -2006.09.24.180836 [215] -libburn/init.c -libburn/sg.c -libburn/libdax_msgs.h -libburn/libdax_msgs.c -cdrskin/cdrskin.c -Made use of new message handling facility and removed first bugs - -24 Sep 2006 [216] -libburn/libdax_msgs.h -Recorded error_code 0x00020001 - -24 Sep 2006 [217] [218] -Makefile.am -libburn/libburn.h -libburn/write.c -libburn/drive.c -cdrskin/compile_cdrskin.sh -Obsoleted libburn/message.[ch] - -25 Sep 2006 [219] -libburn/read.c -libburn/write.c -Removed inclusion of libburn/message.h - -2006.09.25.104629 [220] -libburn/init.c -libburn/drive.c -cdrskin/cdrskin.c -Converted "libburn_experimental:" messages of address conversion into "DEBUG" - -2006.09.25.141035 [221] -libburn/libdax_msgs.h -libburn/libdax_msgs.c -libburn/drive.c -libburn/sg.h -libburn/sg.c -Implemented sg_close_drive_fd (ticket 74) - -2006.09.25.144506 [222] -libburn/libdax_msgs.c -Achieved minimum strerror thread safety (strerror_r is burned by Unix and GNU) - -2006.09.26.114552 [223] -libburn/libburn.h -libburn/init.c -libburn/libdax_msgs.c -cdrskin/cdrskin.c -Made first use of queued messages and fixed several bugs with that - -2006.09.26.142824 [224] -libburn/sg.c -libburn/libdax_msgs.h -cdrskin/cdrskin.c -Made changes with usage of queued messages - -24 Sep 2006 [225] -Makefile.am -libburn/libburn.h -libburn/write.c -libburn/drive.c -- libburn/message.c -- libburn/message.h -Removed libburn/message.[ch] - -2006.09.26.205504 [227] -libburn/drive.c -Enhanced softlink resolution - -2006.09.26.210711 [228] -libburn/drive.c -Fixed bug in enhanced softlink resolution - -2006.09.27.063147 [229] -cdrskin/cdrskin.c -Fixed bug with relative device addresses and Cdrpreskin__cdrecord_to_dev() - -2006.09.27.074910 [230] -cdrskin/cdrskin.c -Fixed broken -version and --help (second time for same mistake) - -2006.09.27.080826 [231] -cdrskin/README -cdrskin/cdrskin.c -Allowed comments and empty lines in startup files - -2006.09.27.082057 [232] -cdrskin/cdrskin.c -Prevented reading of startup files with first arg -version, -help or --help - -2006.09.27.115919 [233] -libburn/drive.c -libburn/sg.h -libburn/sg.c -libburn/libdax_msgs.h -cdrskin/cdrskin.c -Disabled but did not discarded failed attempt to lock against growisofs - -2006.09.27.120656 [234] -libburn/drive.h -libburn/init.c -libburn/transport.h -libburn/libburn.h -Disabled but did not discarded failed attempt to lock against growisofs - -2006.09.27.134332 [235] -libburn/sg.c -Kept /dev/hdX from all having SCSI address 0,0,0 - -2006.09.27.142312 [236] -libburn/drive.c -Curbed endless links to 20 hops - -2006.09.27.143843 [237] -libburn/sg.c -Removed obsolete code and comments - -2006.09.28.074434 [238] -cdrskin/cdrskin.c -Enabled optional growisofs lock attempt via --drive_scsi_exclusive - -28 Sep 2006 [239] -libburn/libburn.h -Made official exclusive==2 with burn_preset_device_open() - ------------------------------------- cycled - cdrskin-0.2.3 - 2006.09.28.100934 - -2006.09.28.115152 [240] -cdrskin/cdrskin.c -Restored vanished line at end of -help text and added a new one - -2006.10.01.104140 [243] -libburn/drive.c -cdrskin/cdrskin.c -Enhanced Cdrpreskin__cdrecord_to_dev so it warns of invisible SCSI drive. - -2006.10.02.103418 [244] -libburn/libburn.h -libburn/drive.h -libburn/drive.c -libburn/libdax_msgs.h -libburn/libdax_msgs.c -cdrskin/cdrskin.c -Implemented burn_abort() and made use of it - -2006.10.03.162719 [245] -Makefile.am -libburn/libburn.h -libburn/init.c -libburn/cleanup.h -libburn/cleanup.c -cdrskin/cleanup.h -cdrskin/cleanup.c -test/libburner.c -cdrskin/compile_cdrskin.sh -cdrskin/cdrskin.c -Implemented new API function burn_set_signal_handling(), libburner uses it - -5 Oct 2006 [246] -libburn/drive.c -Uploaded forgotten part of revision 245 - -2006.10.05.142628 [247] -libburn/libburn.h -libburn/transport.h -libburn/sg.c -libburn/sg.h -libburn/drive.c -cdrskin/cdrskin.c -Made use of SCSI_IOCTL_GET_BUS_NUMBER in hope of cdrecord compatibility - -6 Oct 2006 [248] -+ libburn/asserts.txt -Listed findings on assert() within libburn - -7 Oct 2006 [249] -libburn/async.c -libburn/libdax_msgs.h -libburn/asserts.txt -Got rid by soft means of assert() in async.c - -2006.10.07.121234 [250] -libburn/libburn.h -libburn/async.c -libburn/drive.h -libburn/drive.c -libburn/init.c -libburn/libdax_msgs.h -libburn/sg.c -libburn/asserts.txt -Got rid of assert() in drive.c by soft means - -2006.10.07.132916 [251] -libburn/init.c -libburn/async.c -Got rid of assert() in init.c by soft means - -2006.10.07.142454 [252] -libburn/libburn.h -libburn/async.c -libburn/options.c -libburn/sector.c -libburn/spc.c -libburn/libdax_msgs.h -Got rid of assert() in options.c by soft means - -7 Oct 2006 [253] -libburn/read.c -Got rid of assert() in read.c by soft means - -2006.10.07.170913 [254] -libburn/sg.c -libburn/asserts.txt -Got rid of some assert() in sg.c by soft means - -2006.10.07.175427 [255] -libburn/spc.c -libburn/async.c -libburn/libdax_msgs.h -Got rid of assert() in spc.c by soft means - -2006.10.08.095016 [256] -libburn/structure.c -libburn/sector.c -libburn/spc.c -libburn/libdax_msgs.h -libburn/asserts.txt -Got rid of assert() in structure.c by soft means - -8 Oct 2006 [257] -libburn/toc.c -Got rid of assert() in toc.c by soft means - -8 Oct 2006 [258] -libburn/util.c -Got rid of assert() in util.c by soft means - -2006.10.09.083438 [259] -libburn/write.c -libburn/structure.c -libburn/libdax_msgs.h -libburn/asserts.txt -Got rid of assert() in write.c by soft means - -2006.10.09.123518 [260] -libburn/mmc.c -libburn/read.c -libburn/sector.c -libburn/mmc.h -libburn/transport.h -libburn/asserts.txt -Got rid of assert() in mmc.c by soft means - -2006.10.10.112545 [261] -libburn/sector.h -libburn/sector.c -libburn/async.c -libburn/write.h -libburn/write.c -libburn/libdax_msgs.h -libburn/asserts.txt -Got rid of assert() in sector.c by soft means - -2006.10.10.175444 [262] -libburn/sg.c -libburn/libdax_msgs.h -Got rid of assert() in sg.c by soft means - -10 Oct 2006 [263] -libburn/asserts.txt -Got rid of assert() in libburn - -2006.10.11.191959 [264] -cdrskin/cdrskin.c -cdrskin/README -Changed pseudo-cdrecord addresses: /dev/hdX = ATA:(X-'a')/2,(X-'a')%2,0 - -13 Oct 2006 [270] -Makefile.am -libburn/sg.c -libburn/cleanup.c -libburn/sg-linux.c -libburn/read.c -libburn/drive.c -libburn/sbc.c -libburn/transport.h -cdrskin/cleanup.c -Made libburn and cdrskin build on my Linux again - -2006.10.13.114554 [271] -cdrskin/cdrskin.c -libburn/write.c -libburn/sg-linux.c -libburn/libdax_msgs.h -Removed bug in burn_disc_write_sync(): BURN_DRIVE_IDLE, then d->sync_cache() - -2006.10.14.105224 [272] -libburn/sg.h -libburn/sg-freebsd.c -libburn/sg-linux.c -libburn/drive.c -Introduced burn_drive_enumerator_t to allow more complete sg-freebsd implementation - -2006.10.15.133035 [274] -cdrskin/cdrskin.c -Changed ambigous include statement of libburn.h - -15 Oct 2006 2006 [275] -Makefile.am -libburn/libdax_msgs.h -+ libburn/libdax_audioxtr.h -+ libburn/libdax_audioxtr.c -Implemented a first attempt of a .wav decapitator (ticket 38) - -15 Oct 2006 2006 [276] -+ test/dewav.c -Implemented a first attempt of a .wav decapitator (ticket 38) - -15 Oct 2006 2006 [277] -test/dewav.c -Fixed permissions of eventually created output file - -15 Oct 2006 2006 [278] -test/dewav.c -cdrskin/compile_cdrskin.sh -Hunting a malloc/free memory problem - -15 Oct 2006 2006 [279] -libburn/libdax_audioxtr.c -Hopefully fixed memory problem which causes sigabrt on free - -15 Oct 2006 2006 [280] -libburn/libdax_audioxtr.c -Hopefully fixed problem with stdin as audio source - -15 Oct 2006 2006 [281] -test/dewav.c -Made helptext print to stderr rather than stdout - -2006.10.17.141053 [283] -cdrskin/cdrskin.c -cdrskin/compile_cdrskin.sh -libburn/libdax_audioxtr.h -libburn/libdax_audioxtr.c -test/dewav.c -Roughly implemented automatic .wav extraction in cdrskin - -2006.10.17.164140 [284] -cdrskin/cdrskin.c -libburn/libdax_audioxtr.h -libburn/libdax_audioxtr.c -test/dewav.c -Implemented some cdrecord pickiness for .wav extraction - -18 Oct 2006 [285] -test/libburner.c -Added --audio and multi-track, removed --verbose, hid --burn_for_real - -2006.10.18.174334 [286] -cdrskin/cdrskin.c -Removed assumption BURN_DRIVE_IDLE==0 - -18 Oct 2006 [287] -cdrskin/README -Changed audio statements to reflect new situation - -18 Oct 2006 [288] -cdrskin/README -Removed a typo - -19 Oct 2006 [292] -test/libburner.c -Freed all tracks after burning and not only last one - -2006.10.19.094543 [293] -cdrskin/cdrskin.c -cdrskin/compile_cdrskin.sh -Made cdrskin use libburn/cleanup.[oh] by default (not cdrskin/cleanup.[ch]) - ------------------------------------- cycled - cdrskin-0.2.3 - 2006.10.19.105730 - -2006.10.19.162254 [294] -cdrskin/cdrskin.c -cdrskin/cdrskin_eng.html -cdrskin/changelog.txt -Updated documentation about cdrskin-0.2.3 - -2006.10.19.164742 [295] -cdrskin/cdrskin.c -Corrected -help text - -2006.10.20.113421 [297] -libburn/libburn.h -libburn/mmc.c -libburn/sg-linux.c -libburn/sg-freebsd.c -libburn/drive.c -cdrskin/cdrskin.c -Made cdrskin produce "ATIP start of lead" (on non-blank media for now) - -20 Oct 2006 [298] -doc/comments -Updated help text of libburner - -2006.10.20.151602 [299] -libburn/libburn.h -libburn/drive.c -libburn/mmc.c -libburn/libdax_msgs.h -cdrskin/cdrskin.c -Classified media with TOC read error as unsuitable (rather than as blank) - -2006.10.21.103352 [300] -libburn/libburn.h -libburn/transport.h -libburn/drive.c -libburn/mmc.c -libburn/spc.c -libburn/sg-linux.c -libburn/sg-freebsd.c -libburn/libdax_msgs.h -cdrskin/cdrskin.c -Implemented some ATIP functionality - -2006.10.21.103653 [301] [302] -libburn/libburn.h -Clarified relation of burn_disc_read_atip() and burn_drive_get_start_end_lba() - -2006.10.21.185102 [303] -libburn/sg.h -libburn/mmc.h -libburn/mmc.c -libburn/sbc.h -libburn/sbc.c -libburn/spc.h -libburn/spc.c -libburn/drive.h -libburn/drive.c -libburn/transport.h -libburn/sg-linux.c -libburn/sg-freebsd.c -Split enumerate_common() into logic-layer, command-layer, transport-layer - -2006.10.22.130341 [304] -libburn/libburn.h -libburn/mmc.c -libburn/drive.c -libburn/cleanup.c -cdrskin/cleanup.c -cdrskin/cdrskin.c -Implemented cdrskin -toc - -2006.10.22.131452 [305] -cdrskin/cdrskin.c -Regulated coexistence of options -toc and -atip - -23 Oct 2006 [306] -libburn/mmc.c -Made clarification in remark about atip speed conversion - -2006.10.23.074430 [307] -cdrskin/cdrskin.c -Made use of burn_drive_info.revision as firmware revision text - -2006.10.23.113116 [308] -libburn/libburn.h -libburn/transport.h -libburn/mmc.h -libburn/mmc.c -libburn/write.c -cdrskin/cdrskin.c -cdrskin/cdrskin_eng.html -cdrskin/README -Made available drive buffer fill during write - -23 Oct 2006 [309] -libburn/sg-freebsd.c -Updated tangling of FreeBSD code with mmc.c :( - -2006.10.23.134719 [310] -cdrskin/cdrskin.c -Corrected -toc track counter and notified about "hidden" tracks - -2006.10.24.075039 [311] -libburn/libdax_audioxtr.h -libburn/libdax_audioxtr.c -test/dewav.c -cdrskin/cdrskin.c -Introduced extraction of .au (but not its usage within cdrskin) - -2006.10.24.102107 [312] -libburn/libburn.h -libburn/structure.h -libburn/structure.c -libburn/sector.c -cdrskin/cdrskin.c -cdrskin/README -Enabled byte swapping for audio track sources, added anti option -swab - -2006.10.24.130259 [313] -test/dewav.c -cdrskin/cdrskin.c -cdrskin/README -Enabled automatic extraction of .au - -24 Oct 2006 [314] -Makefile.am -+ test/fake_au.c -Introduced temporary test program to produce SUN .au files - ------------------------------------- cycled - cdrskin-0.2.3 - 2006.10.24.144650 - -2006.10.24.165427 [315] -libburn/sector.c -Closed some loopholes for byte swapping. - - -2006.10.24.165610 [316] -cdrskin/cdrskin.c -Enabled audio byte swapping by default (to be disabled via option -swab) - ------------------------------------- cycled - cdrskin-0.2.3 - 2006.10.24.173602 - -25 Oct 2006 [317] -cdrskin/README -cdrskin/cdrskin_eng.html -cdrskin/wiki_plain.txt -Announced full -audio compatibility with cdrecord - ------------------------------------- cycled - cdrskin-0.2.3 - 2006.10.25.160540 - -2006.10.27.114326 [319 branch] -- cdrskin/add_ts_changes_to_libburn_0_2_3 -+ cdrskin/add_ts_changes_to_libburn_0_2_4 -cdrskin/README -cdrskin/cdrskin.c -cdrskin/cdrskin_eng.html -cdrskin/changelog.txt -README -Performed cdrskin version leap to cdrskin-0.2.4 - -2006.10.28.093922 [320 branch] -cdrskin/cdrskin_timestamp.h -Set final timestamp 2006.10.28.093922 - ------------------------------------- cycled - cdrskin-0.2.4 - 2006.10.28.093922 - -2006.10.28.115213 [321 trunk] [322 trunk] -- cdrskin/add_ts_changes_to_libburn_0_2_3 -+ cdrskin/add_ts_changes_to_libburn_0_2_4 -+ cdrskin/add_ts_changes_to_libburn_0_2_5 -cdrskin/README -cdrskin/cdrskin.c -cdrskin/cdrskin_eng.html -cdrskin/changelog.txt -README -Performed cdrskin version leap to cdrskin-0.2.5 - -28 Oct 2006 [323 branch] -- cdrskin/add_ts_changes_to_libburn_0_2_3 -cdrskin/add_ts_changes_to_libburn_0_2_4 -Corrected misnaming of my development directory - -28 Oct 2006 [324 trunk] -cdrskin/add_ts_changes_to_libburn_0_2_4 -cdrskin/add_ts_changes_to_libburn_0_2_5 -Corrected misnaming of my development directory - -2006.10.28.132532 [325 branch] -cdrskin/cdrskin.c -Corrected last-minute bug which made every track from file an audio track - -2006.10.28.151521 [326 trunk] -cdrskin/cdrskin.c -Corrected bug which made every track from file an audio track - -29 Oct 2006 [327 branch] [328 trunk] -+ CONTRIBUTORS -Copied missing file from libburn-0.2.2 - -29 Oct 2006 [329 branch] [330 trunk] -Makefile.am -Added to EXTRA_DIST cdrskin/cleanup.[ch] - -29 Oct 2006 [331 branch] [332 trunk] -Makefile.am -Added to EXTRA_DIST libburn/sg-*.[ch] - -29 Oct 2006 [333 branch] [334 trunk] -Makefile.am -Deleted from to EXTRA_DIST libburn/sg-*.h - -30 Oct 2006 [337] -libburn/transport.h -libburn/mmc.c -libburn/sg-freebsd.c -Made MMC command CLOSE TRACK/SESSION available to struct burn_drive - -2006.10.31.115606 [338] -libburn/transport.h -libburn/spc.c -libburn/mmc.c -libburn/write.h -libburn/write.c -libburn/sector.c -libburn/libdax_msgs.h -libburn/sg.h -libburn/sg-linux.c -cdrskin/cdrskin.c -Made single track TAO work (sector i/o still wants fixed size, though) - -2006.10.31.184736 [339] -libburn/sector.c -libburn/source.c -libburn/structure.h -libburn/structure.c -libburn/write.c -cdrskin/cdrskin.c -Made single track TAO work without fixed size (compile -experimental) - -2006.11.01.163934 [340] -libburn/libburn.h -libburn/source.c -libburn/write.h -libburn/write.c -libburn/structure.c -libburn/structure.h -libburn/sector.c -cdrskin/cdrskin.c -cdrskin/compile_cdrskin.sh -Adapted cdrskin pacifier to possibly unknown track size - -2006.11.01.172004 [341] -configure.ac -bootstrap -test/libburner.c -Repaired broken macro settings during Linux build - -2 Nov 2006 [342] -cdrskin/README -Mentioned -tao and experimental compile - -2006.11.02.211816 [343] -libburn/libburn.h -libburn/write.c -cdrskin/cdrskin.c -Installed status communications about closing session ("Fixating") - -3 Nov 2006 [344] -test/libburner.c -Changed status report during blanking (there are no "sectors") - -2006.11.03.063307 [345] -cdrskin/cdrskin.c -Removed some obsolete debugging messages - -2006.11.03.151137 [346] -libburn/structure.h -libburn/structure.c -libburn/write.h -libburn/write.c -libburn/sector.c -libburn/libdax_msgs.h -Installed decent abort behavior with TAO - -2006.11.03.202403 [347] -libburn/write.c -Enabled TAO for multiple -data tracks (-audio still ends after 0 bytes) - -2006.11.04.092909 [348] -libburn/spc.c -libburn/sector.c -Enabled audio tracks with TAO - -2006.11.02.140329 (pl01) [351 tags/CdrskinZeroTwoFourPlZeroOne] -../cdrskin-0.2.4.patch01/configure.ac -../cdrskin-0.2.4.patch01/bootstrap -../cdrskin-0.2.4.patch01/cdrskin/README -../cdrskin-0.2.4.patch01/cdrskin/add_ts_changes_to_libburn_0_2_4_patch01 -../cdrskin-0.2.4.patch01/cdrskin/cdrskin_timestamp.h -../cdrskin-0.2.4.patch01/test/libburner.c -Revoked autotools aspect of revision 290 - -2006.11.06.073810 [352] -cdrskin/cdrskin.c -cdrskin/cdrskin_eng.html -cdrskin/changelog.txt -Adapted documentation to reflect experimental TAO mode - ------------------------------------- cycle - cdrskin-0.2.5 - 2006.11.06.085056 - -2006.11.06.114159 [353] -libburn/libburn.h -libburn/spc.c -libburn/options.c -cdrskin/cdrskin.c -New API burn_write_opts_set_multi(). (But libburn cannot burn next session yet) - -2006.11.06.121409 [354] -cdrskin/cdrskin.c -Made -toc on multiple sessions more compatible - -2006.11.06.155237 [355] -libburn/libburn.h -libburn/drive.c -libburn/write.c -libburn/mmc.c -libburn/sg-linux.c -cdrskin/cdrskin.c -Made CD with unclosed track blankable (by -force) - -2006.11.06.195743 [356] -libburn/transport.h -libburn/mmc.c -libburn/spc.c -libburn/write.c -libburn/sg-linux.c -Cared for some SCSI error conditions which were ignored up to now - -2006.11.07.114514 [357] -cdrskin/cdrskin.c -Made -tao default for single track or stdin, -sao for any other multi-track - -7 Nov 2006 [358] -cdrskin/cdrskin_eng.html -cdrskin/changelog.txt -Prepared next cdrskin-0.2.5 upload cycle - -7 Nov 2006 [359] -cdrskin/changelog.txt -cdrskin/README -cdrskin/wiki_plain.txt -Updated documentation about TAO - -2006.11.07.152018 [360] -cdrskin/cdrskin.c -cdrskin/changelog.txt -Updated documentation about TAO - ------------------------------------- cycle - cdrskin-0.2.5 - 2006.11.07.152018 -* Enabled TAO - - -2006.11.08.165648 [361] -cdrskin/cdrfifo.h -cdrskin/cdrfifo.c -cdrskin/cdrskin.c -Avoided error message and nonzero exit with trailing trash on .wav - -8 Nov 2006 [362] -cdrskin/cdrskin_eng.html -Mentioned bug fix about trailing trash - -2006.11.08.172918 [363] -libburn/write.c -Made track write counter of SAO count rather too much than too few bytes - -8 Nov 2006 [364] -cdrskin/changelog.txt -Prepared next cdrskin-0.2.5 upload cycle - ------------------------------------- cycle - cdrskin-0.2.5 - 2006.11.08.181016 -* Bug fixed: Trailing trash appended to .wav files caused error message - and, if exceeding fifo size, could even stall a burn. - - -2006.11.09.112832 [365] -cdrskin/cdrskin.c -Check desired write and block type with burn_drive_info.*_block_types - -2006.11.09.113729 [366] -libburn/sg-linux.c -Silenced SCSI error (debugging) messages about missing media - -2006.11.09.151431 [367] -cdrskin/cdrskin.c -Corrected first speed measurement report in TAO mode (which was random) - -2006.11.09.193030 [368] -libburn/libburn.h -libburn/write.c -cdrskin/cdrskin.c -Experimentally enabled burning to BURN_DISC_APPENDABLE (tested with TAO only) - -2006.11.10.093843 [369] -cdrskin/cdrskin.c -doc/comments -Expressing more self-confidence - -2006.11.10.172212 [370] -cdrskin/cdrskin.c -Provisory -msinfo (very verbous on stderr) - -2006.11.10.184047 [371] -cdrskin/cdrskin.c -Made it work with fifos and other non-plain files as track sources - -2006.11.10.185209 [372] -cdrskin/cdrskin.c -Read -msinfo from first track of last session and not from last track - -2006.11.11.122402 [373] -libburn/libburn.h -libburn/transport.h -libburn/mmc.h -libburn/mmc.c -libburn/write.c -libburn/drive.c -libburn/libdax_msgs.h -New API function burn_disc_track_lba_nwa() - -2006.11.11.122907 [374] [375] -cdrskin/cdrskin.c -Implemented not so provisory -msinfo - -2006.11.11.124020 [376] [377] -cdrskin/cdrskin.c -Reacted on some warnings of gcc -O2 - -2006.11.11.134752 [378] -cdrskin/cdrskin.c -Implemented handling of unsuitable disk states with -msinfo - -2006.11.11.152037 [379] -cdrskin/cdrskin.c -Demanded (for now) -tao for writing to appendable CDs - -2006.11.11.152748 [380] -cdrskin/cdrskin.c -Generally enabled -multi, -msinfo and writing to appendable CDs in TAO mode - -11 Nov 2006 [381] -cdrskin/changelog.txt -Prepared next cdrskin-0.2.5 cycle - -11 Nov 2006 [382] -cdrskin/cdrskin_eng.html -cdrskin/README -Updated docs about multi-session - ------------------------------------- cycle - cdrskin-0.2.5 - 2006.11.11.163625 -* Multi-session CDs (for now restricted to write mode TAO), -multi, -msinfo -* Bug fixed: False speed with first pacifier cycle. Potential SIGFPE by NaN. - - -2006.11.12.085808 [383] -libburn/mmc.c -Made speed 0 in burn_drive_set_speed() really maximum speed (i.e. FFFFh) - -2006.11.12.113629 [384] -cdrskin/cdrskin.c -Made SAO preferrable default write mode, kept TAO as default where needed - -2006.11.12.152723 [385] -libburn/mmc.c -libburn/libdax_msgs.h -Reacted on error condition during write operation - -2006.11.12.185342 [386] -cdrskin/cdrskin.c -Made -toc on blank CD exit with value 0 (rather than 7 with no media) - -13 Nov 2006 [390] -README -cdrskin/add_ts_changes_to_libburn_0_2_5 -cdrskin/cdrskin_eng.html -Changed SVN URLs to reflect new structure - -13 Nov 2006 [391] -README -Refered to both libburn and libisofs in SVN description, updated history - ------------------------------------- cycle - cdrskin-0.2.5 - 2006.11.13.122418 -* Enabled named pipes and other non-plain file types as track sources - (actually already in previous cycle) -* Bug fixed: Default speed was not highest possible but announced as "MAX" -* SAO is preferred default write mode, TAO is default when needed - - -2006.11.13.122418 [392] -cdrskin/changelog.txt -Next cdrskin-0.2.5 cycle - -13 Nov 2006 [393] -cdrskin/cdrskin_eng.html -Adjusted description of write mode default - -13 Nov 2006 [394] -Makefile.am -configure.ac -Removed references to libisofs - -14 Nov 2006 [399] -README -Changed references to libisofs - -14 Nov 2006 [400] -cdrskin/README -Corrected a typo reported by George Danchev - -2006.11.14.104023 [401] -cdrskin/cdrskin.c -Implemented try to find on restricted drives a suitable write mode as default - -14 Nov 2006 [402] -libburn/libburn.h -Fixed a wrong name in API description - -15 Nov 2006 [403] -libburn/write.h -libburn/write.c -Prepared tests for eventual drive which might support SAO to appendable CD - -15 Nov 2006 [404] -libburn/sg-linux.c -Enhanced optional SCSI command logging - -2006.11.15.091329 [405] -cdrskin/cdrskin.c -Adjusted some texts to new multi-session situation - -2006.11.15.170927 [406] -libburn/sg.h -libburn/sg-linux.c -libburn/sg-freebsd.c -+ libburn/sg-freebsd-port.c -libburn/spc.h -libburn/spc.c -libburn/drive.c -Made portability clarifications - -15 Nov 2006 [407] -libburn/sg-linux.c -libburn/sg-freebsd-port.c -Narrowed system specific part of enumerate_common() - -2006.11.16.111656 [408] [409] -Makefile.am -+ libburn/os.h -+ libburn/os-linux.h -+ libburn/os-freebsd.h -libburn/sg.h -libburn/sg.c -libburn/transport.h -libburn/cleanup.c -libburn/sg-linux.c -libburn/sg-freebsd-port.c -cdrskin/cleanup.c -cdrskin/compile_cdrskin.sh -Made consolidaed operating system adapters for ease of porting - -2006.11.16.133951 [410] -libburn/sg-linux.c -libburn/sg-freebsd-port.c -Polished porting hints and self-compliance to newly established specs - -16 Nov 2006 [411] -libburn/sg-linux.c -libburn/sg-freebsd-port.c -Polished porting hints - -16 Nov 2006 [412] -test/libburner.c -Obsoleted --stdin_size by automatic TAO, cared for non-plain track files - -16 Nov 2006 [413] -doc/comments -Updated help text of libburner - -17 Nov 2006 [414] -Makefile.am -+ test/telltoc.c -Created info retrieval companion for libburner - -17 Nov 2006 [415] -test/libburner.c -Enabled multi-session with libburner - -17 Nov 2006 [416] -Makefile.am -- test/toc.c -Obsoleted old test program - -17 Nov 2006 [417] [418] -test/telltoc.c -Shifted a comma - -2006.11.18.194606 [419] -libburn/transport.h -libburn/sbc.h -libburn/sbc.c -libburn/drive.c -Test wether SCSI 1Bh START UNIT would be helpful with ticket 90 - -2006.11.19.114413 [420] -libburn/libburn.h -libburn/mmc.c -libburn/sector.c -libburn/write.c -cdrskin/cdrskin.c -Implemented libburn builtin fine granulated drive buffer min-fill recording - -2006.11.19.162900 [421] -cdrskin/cdrskin.c -Avoided self contradiction with "Min drive buffer fill" - -2006.11.19.163646 [422] -cdrskin/cdrskin.c -Fixed missing brackets from revison 421 - -2006.11.20.090207 [423] -libburn/sector.c -Silenced compiler warnings - -2006.11.20.090503 [424] -libburn/drive.c -Removed a redundant d->start_unit() of revision 419 - - ------------------------------------- cycle - cdrskin-0.2.5 - 2006.11.20.092808 -* libisofs unbundled from libburn+cdrskin -* Hints for porting to other operating systems are now in sg-*.c - -20 Nov 2006 [425] -cdrskin/changelog.txt -Next cdrskin-0.2.5 cycle - -2006.11.20.132717 [426] -cdrskin/cdrskin.c -cdrskin/cdrfifo.h -cdrskin/cdrfifo.c -cdrskin/wiki_plain.txt -Implemented new option fifo_start_at= - -20 Nov 2006 [427] -cdrskin/wiki_plain.txt -Updated in respect to multi-session - -2006.11.22.122228 [428] -libburn/spc.h -libburn/spc.c -Coordinated scsi_notify_error() and scsi_error() - - ------------------------------------- cycle - cdrskin-0.2.5 - 2006.11.22.142517 - -23 Nov 2006 [433] -cdrskin/changelog.txt -Last cdrskin-0.2.5 cycle - -23 Nov 2006 [434] -- test/burn.c -- test/master.c -- test/tree.py -- test/tree.pyc -- test/rip.c -Removed obsolete test programs - -2006.11.23.102340 [435] -Makefile.am -cdrskin/compile_cdrskin.sh -cdrskin/cdrskin.c -cdrskin/cdrskin_eng.html -cdrskin/README -cdrskin/wiki_plain.txt -+ cdrskin/add_ts_changes_to_libburn_0_2_6 -+ cdrskin/add_ts_changes_to_libburn_0_2_7 -- cdrskin/add_ts_changes_to_libburn_0_2_4 -- cdrskin/add_ts_changes_to_libburn_0_2_5 -Version leap to 0.2.6 - -24 Nov 2006 -Published cdrskin-0.2.6.pl01 on cdrskin home pages - -------------------------------- cycle - cdrskin-0.2.6.pl01 - 2006.11.23.114611 - - -2006.11.24.121745 [437] -Makefile.am -configure.ac -cdrskin/compile_cdrskin.sh -cdrskin/cdrskin.c -cdrskin/README -Version leap to 0.2.7 - -24 Nov 2006 [438] -doc/comments -Mentioned telltoc and dewav as helpers of libburner - - ------------------------------------- cycle - cdrskin-0.2.7 - 2006.11.24.125445 - -24 Nov 2006 [439] -cdrskin/changelog.txt -First cdrskin-0.2.7 cycle - -24 Nov 2006 [440] -doc/comments -Updated libburner helptext copy - -24 Nov 2006 [441] -doc/comments -Made our claim of burning CD more general - -2006.11.25.104047 [442] -cdrskin/cdrskin.c -Disabled old workaround for ticket 8, burn_disc_read_atip() fixed the problem - -25 Nov 2006 [443] -libburn/drive.h -libburn/drive.c -libburn/write.c -test/libburner.c -Ticket 91: update media state model after content change - -25 Nov 2006 [444] -test/libburner.c -test/telltoc.c -Made use of libburn device address translation (/dev/sr0, /dev/cdrom, ...) - -25 Nov 2006 [445] -test/libburner.c -Corrected two minor bugs - -2006.11.25.170456 [446] -libburn/cleanup.c -cdrskin/cleanup.c -Trying to keep signal handler from repeating messages - -2006.11.25.182841 [447] -libburn/write.c -libburn/drive.c -Prevented premature BURN_DRIVE_IDLE introduced with revision 443 - -2006.11.25.210321 [448] -cdrskin/cdrskin.c -Enabled options -vv, -vvv and -vvvv - -28 Nov 2006 [449] -README -Mentioned renaming of umbrella project to libburnia - -2006.11.29.205136 [450] -cdrskin/cdrskin.c -Added preliminary support for new cdrecord 1000+ = ATA busses (input only) - -2006.12.01.213845 [451] -libburn/transport.h -libburn/libdax_msgs.h -libburn/mmc.c -Ticket 21: media type via 46h GET CONFIGURATION , Current Profile - -2006.12.02.111701 [452] -libburn/libburn.h -libburn/mmc.c -libburn/drive.c -cdrskin/cdrskin.c -New API function to obtain media type: burn_disc_get_profile() - -2006.12.02.130631 [453] -libburn/mmc.c -Correction for drives which return empty tray as profile 0x00 rather than error - - ------------------------------------- cycle - cdrskin-0.2.7 - 2006.12.02.151257 -* Improved recognition of unsuitable media types - - -2 Dec 2006 [454] -cdrskin/changelog.txt -cdrskin/cdrskin_eng.html -Next cdrskin-0.2.7 cycle - -2006.12.02.201405 [456] -libburn/drive.c -libburn/mmc.c -Avoided unsuitable media complaint on burn_drive_grab() with load==0 - -2006.12.02.201529 [457] -cdrskin/cdrskin.c -Testing wether the after-grab status waiting loops are necessary - -3 Dec 2006 [461] -cdrskin/doener_150x200_tr.gif -cdrskin/doener_150x200_tr_octx.gif -cdrskin/cdrskin_eng.html -cdrskin is declared honoray Doenerware (burp) - -3 Dec 2006 [463] -cdrskin/cdrskin_eng.html -Have wikipedia explain doenerism ("Eat the rich" and so) - -2006.12.03.155703 [464] -README -doc/comments -test/libburner.c -cdrskin/cdrskin_eng.html -cdrskin/README -cdrskin/cdrskin.c -Changed URLs and umbrella names to libburnia - -3 Dec 2006 [465] -cdrskin/wiki_plain.txt -Changed URLs and umbrella names to libburnia - -3 Dec 2006 [466] -cdrskin/wiki_plain.txt -Added Doener logo and link - -3 Dec 2006 [468] -cdrskin/cdrskin_eng.html -cdrskin/add_ts_changes_to_libburn_0_2_7 -Excluded doener gifs from cdrskin tarballs - - ------------------------------------- cycle - cdrskin-0.2.7 - 2006.12.03.204709 - - -2006.12.03.204709 [469] -cdrskin/changelog.txt -Next cdrskin-0.2.7 cycle - -4 Dec 2006 [470] -cdrskin/cdrskin_eng.html -Removed a newline which made the Mozilla family show a "_" - -4 Dec 2006 [471] -test/telltoc.c -Added reporting of current media profile, changed "Media type" to "Media reuse" - -2006.12.09.111108 [475] -cdrskin/cdrskin.c -Replaced setuid blocker by warning. People must know themselves what they do. - - ------------------------------------- cycle - cdrskin-0.2.7 - 2006.12.09.141837 -* Replaced ban of chmod u+s by loud warning - - -11 Dec 2006 [484] -cdrskin/cdrskin_eng.html -cdrskin/changelog.txt -Next cdrskin-0.2.7 cycle - -2006.12.11.095230 [485] -cdrskin/cdrskin_timestamp.h -Belated timestamp for changes in cdrskin - -11 Dec 2006 [486] -Makefile.am -Unified mix of tab an blanks which looks ugly in diff - -2006.12.11.100021 [487] -libburn/sg-linux.c -Prepared experiments for new Linux SCSI adventures - -2006.12.11.101350 [488] -cdrskin/README -cdrskin/cdrskin.c -cdrskin/wiki_plain.txt -Consequences from newly introduces startup file - -11 Dec 2006 [489] -cdrskin/wiki_plain.txt -Repaired README link and planted helptext links - -2006.12.11.115802 [490] -libburn/sg-linux.c -Silenced a compiler warning. Worked further on /dev/srM test. Not done yet. - -2006.12.11.125222 [491] -libburn/mmc.c -libburn/structure.c -Prevented SIGSEGVs when using -atip with my SCSI CD-ROM (sr,sg: no matter) - -2006.12.11.134452 [492] -libburn/sg-linux.c -Enabled correct SCSI address parameter registration for /dev/srM. - -2006.12.11.145332 [493] -libburn/sg-linux.c -Removed ban on linux_sg_device_family, warning now of linux_sg_accept_any_type - -2006.12.11.161952 [494] -libburn/sg-linux.c -Reacted better on failing ioctl(SG_GET_SCSI_ID) - -2006.12.11.191826 [495] -libburn/sg-linux.c -cdrskin/cdrskin.c -Trying to identfy CD device via ioctl(CDROM_DRIVE_STATUS) - -2006.12.11.215017 [496] -libburn/libburn.h -Appeased doxygen warnings - -2006.12.13.170319 [497] -cdrskin/cdrskin.c -Updated dev=help to versions >= 0.2.4, new option --list_ignored_options - -13 Dec 2006 [498] -+ cdrskin/cdrskin.1 -Detailed man page for cdrskin. Based on work of George Danchev. - -2006.12.13.195441 [499] -Makefile.am -Trying to get new man page into release tarball and installation. - -13 Dec 2006 [500] -cdrskin/README -Took care for man page - -13 Dec 2006 [501] -cdrskin/cdrskin.1 -Clarified track content meaning. Corrected some typos and beauty flaws - -13 Dec 2006 [502] -cdrskin/README -cdrskin/cdrskin_eng.html -Took more care for man page - - ------------------------------------- cycle - cdrskin-0.2.7 - 2006.12.13.221921 -* detailed man page for cdrskin - - -13 Dec 2006 [503] -cdrskin/changelog.txt -Next cdrskin-0.2.7 cycle - -13 Dec 2006 [504] -cdrskin/cdrskin.1 -Explained recordable CD media. Removed a typo. - -14 Dec 2006 [505] -cdrskin/cdrskin.1 -Unified some nomenclature. Removed an error with dev_translation= - -14 Dec 2006 [506] -CONTRIBUTORS -Mentioned George Danchev for his merits about cdrskin man page - -2006.12.14.102857 [507] -Makefile.am -cdrskin/cdrskin_eng.html -+ cdrskin/convert_man_to_html.sh -cdrskin/add_ts_changes_to_libburn_0_2_7 -Publishing cdrskin.1 as man_1_cdrskin.html - -14 Dec 2006 [508] -- doc/comments_test_ts -Removed outdated experiment - - ------------------------------------- cycle - cdrskin-0.2.7 - 2006.12.14.111807 - -2006.12.14.140001 -+ cdrskin-0.2.6/cdrskin/cdrskin.1 -cdrskin-0.2.6/cdrskin/README -cdrskin-0.2.6/cdrskin/cdrskin_eng.html -cdrskin-0.2.6/cdrskin/changelog.txt -Backported manpage to cdrskin-0.2.6 -> pl02 and libburn-0.2.6 -> 0.2.6.2 - - -14 Dec 2006 [509] -cdrskin/cdrskin_eng.html -Re-arranged examples of documentation commands - -14 Dec 2006 [510] -cdrskin/cdrskin.1 -Corrected alphabetical sorting error - -14 Dec 2006 [511] -cdrskin/changelog.txt -Next cdrskin-0.2.7 cycle - -14 Dec 2006 [512] -cdrskin/convert_man_to_html.sh -Added some meta info to the document header, changed title to "man 1 cdrskin" - -14 Dec 2006 [513] -cdrskin/wiki_plain.txt -Adapted to existence of man page - -15 Dec 2006 [514] -cdrskin/cdrskin.1 -Clarified drives and their addresses - -15 Dec 2006 [515] -cdrskin/convert_man_to_html.sh -Adapted to changes in cdrskin.1 - -15 Dec 2006 [516] -cdrskin/cdrskin.1 -Introduced term "session" - -2006.12.16.090001 [518] -cdrskin-0.2.6/Makefile.am -+ cdrskin-0.2.6/cdrskin/cdrskin.1 -cdrskin-0.2.6/cdrskin/README -cdrskin-0.2.6/cdrskin/cdrskin_eng.html -cdrskin-0.2.6/cdrskin/changelog.txt -cdrskin-0.2.6/cdrskin/cdrskin_timestamp.h -Backported manpage to libburn-0.2.6.1 -> libburn-0.2.6.2 - -18 Dec 2006 [519] -cdrskin/cdrskin.1 -Made several minor clarifications - -2006.12.18.123242 [520] -libburn/mmc.c -Noted some insight about necessity of OPC gained from growisofs_mmc.cpp - -2006.12.20.111932 [522] -libburn/transport.h -libburn/options.h -libburn/options.c -libburn/write.c -libburn/sector.c -libburn/mmc.c -libburn/libdax_msgs.h -Prepared experiments for writing to DVD (most easy: DVD+RW) - -2006.12.20.142301 [523] -libburn/write.c -libburn/libdax_msgs.h -Refuse to burn audio tracks to DVD - -2006.12.20.145222 [524] -libburn/drive.c -libburn/mmc.c -Avoid undefined 43h commands (TOC/ATIP) with non-CD - -2006.12.20.170502 [525] -libburn/mmc.c -Corrected DVD+RW track number and nwa with 52h READ TRACK INFORMATION - -2006.12.20.171230 [526] -libburn/mmc.c -Corrected bug reported by gcc -O2 - -2006.12.20.174016 [527] -yylibburn/write.c -Corrected bug reported by gcc -O2 - -2006.12.20.180214 [528] -cdrskin/cdrskin.c -With -atip report "booktype" for DVD media and no questionable ATIP info - -2006.12.20.195421 [529] -cdrskin/cdrskin.c -With -atip on DVD report no RAW/RAW96R among "Supported modes" - -2006.12.21.122301 [530] -libburn/write.c -Removed some debugging messages - -2006.12.21.122533 [531] -cdrskin/cdrskin.c -DVD speed reporting (and setting for drives which obey BBh SET CD SPEED) - -2006.12.21.200556 [532] -libburn/mmc.c -libburn/libdax_msgs.h -DVD speed setting via B6h SET STREAMING, DVD+RW now enabled in vanilla build - -2006.12.21.205702 [533] -libburn/write.c -Disallowed multi flag with DVD+RW (nurses wrong hopes for now) - -21 Dec 2006 [534] -test/libburner.c -Report media type, avoid self contradicting messages with DVD+RW --multi - -2006.12.21.214641 [535] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -cdrskin/README -cdrskin/cdrskin_eng.html -doc/comments -Some bragging about DVD+RW - - ------------------------------------- cycle - cdrskin-0.2.7 - 2006.12.22.120854 -* Burning of DVD+RW media as single-track TAO-like initial session - - -2006.12.23.102056 [536] -libburn/libburn.h -libburn/options.h -libburn/options.c -libburn/write.c -Adjustable write position for DVD+RW: burn_write_opts_set_start_byte() - -2006.12.23.102201 [537] -cdrskin/cdrskin.c -New option write_start_address= - -23 Dec 2006 [538] -cdrskin/cdrskin.1 -cdrskin/README -cdrskin/convert_man_to_html.sh -Added more info about DVD+RW - -2006.12.23.141315 [539] -libburn/libburn.h -libburn/drive.c -libburn/write.c -cdrskin/cdrskin.c -New API function to inquire burn success (and avoid confusing messages) - -2006.12.23.184353 [540] -libburn/libburn.h -libburn/write.c -cdrskin/cdrskin.c -More appropriate drive status during format and close of DVD+RW - -2006.12.24.140904 [547] -cdrskin/cdrskin.c -libburn/write.c -Fixed a bug with speed measurement at end of DVD+RW burning - -2006.12.24.142512 [548] -libburn/options.h -libburn/options.c -libburn/write.c -Made DVD 32k end padding controllable - -2006.12.24.154455 [549] -cdrskin/cdrskin.c -Made DVD ignore CD write modes of drive. Made TAO default for DVD+RW. - -2006.12.24.182307 [550] -libburn/write.c -Bugfix with DVD+RW : progress indicators were initialized too late - -2006.12.24.182410 [551] -libburn/options.c -Bugfix after changes for DVD+RW: start_byte was initialized 0, but must be -1 - -24 Dec 2006 [552] -test/libburner.c -test/telltoc.c -Removed unnecessary waiting loops after grab, mentioned DVD+RW - -2006.12.25.113534 [553] -libburn/libburn.h -libburn/spc.c -libburn/drive.c -Ticket 93: write speeds from mode page 2Ah descriptors - -25 Dec 2006 [554] -test/telltoc.c -Adjusted to new (still immature) speed info semantics - -2006.12.25.185747 [555] -cdrskin/cdrskin.c -Corrected CD speed conversion factor to 2352*75/1000 = 176.4 kB/s - -2006.12.25.190055 [556] -libburn/spc.c -libburn/mmc.h -libburn/mmc.c -libburn/write.c -libburn/libdax_msgs.h -Ticket 93: write speeds from ACh GET PERFORMANCE, Type 03h, DVD media capacity - -25 Dec 2006 [557] -test/telltoc.c -Adjusted to new (more mature) speed info semantics - -2006.12.25.190811 [558] -libburn/transport.h -Completed revision 556 - -2006.12.26.170459 [559] -libburn/libburn.h -libburn/transport.h -libburn/drive.h -libburn/drive.c -libburn/mmc.c -libburn/spc.c -New API calls burn_drive_get_speedlist() , burn_drive_free_speedlist() - -26 Dec 2006 [560] -test/telltoc.c -Enabled report of speed descriptor list - -2006.12.26.184321 [561] -libburn/libburn.h -test/telltoc.c -Minor corrections to revisions 559 and 560 - -2006.12.27.125948 [562] -libburn/drive.c -Disabled obsolete drive-media-state workaround. (Spinoff of ticket 93 :)) - -2006.12.27.130125 [563] -libburn/mmc.c -Corrected kB conversion factor to 176.4 with ATIP speed codes - -2006.12.27.130239 [564] -cdrskin/cdrskin.c -Defended against a race condition on SuSE 9.3 after -atip (hald et.al. ?) - -2006.12.27.132653 [565] -libburn/mmc.c -Avoided self contradicting result of ATIP speed inquiry - -2006.12.27.162846 [566] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Emulated wodim option -msifile=path - -2006.12.27.213729 [567] -cdrskin/cdrskin.c -Followed revision 644 of wodim (msifile output without newline) - -27 Dec 2006 [568] -cdrskin/cdrskin_eng.html -cdrskin/cdrskin.1 -Updated about msifile=path - - ------------------------------------- cycle - cdrskin-0.2.7 - 2006.12.27.214424 -* New option -msifile=path from cdrkit/wodim - - -2006.12.29.143734 [569] -libburn/mmc.c -Corrected DVD-RW sequential profile name - -2006.12.30.001343 [570] -libburn/mmc.h -libburn/mmc.c -libburn/spc.c -libburn/write.c -libburn/libdax_msgs.h -cdrskin/cdrskin.c -Prepared support for DVD-RW in mode Restricted Overwrite - -29 Dec 2006 [571] -cdrskin/changelog.txt -Next cdrskin-0.2.7 cycle - -2007.01.01.170824 [572] -libburn/libburn.h -libburn/transport.h -libburn/spc.c -libburn/mmc.h -libburn/mmc.c -libburn/async.c -libburn/drive.h -libburn/drive.c -libburn/write.c -libburn/libdax_msgs.h -Prepared formatting of DVD-RW - -2007.01.01.171725 [573] -cdrskin/cdrskin.c -cdrskin/README -cdrskin/cdrskin.1 -cdrskin/wiki_plain.txt -cdrskin/cdrskin_eng.html -Made use of formatting of DVD-RW - -2 Jan 2007 [574] -cdrskin/wiki_plain.txt -Added links to cdrskin help texts - -2007.01.02.090530 [575] -COPYRIGHT -README -cdrskin/cdrskin.c -Greeting the new year - - ------------------------------------- cycle - cdrskin-0.2.7 - 2007.01.02.101027 -* Formatting and then burning to DVD-RW like to DVD+RW - - -2 Jan 2007 [576] -cdrskin/changelog.txt -Next cdrskin-0.2.7 cycle - -2 Jan 2007 [577] -cdrskin/wiki_plain.txt -cdrskin/README -Some DVD-RW statements - -2 Jan 2007 [578] -test/libburner.c -doc/comments -Made use of formatting of DVD-RW - -2 Jan 2007 [579] -cdrskin/cdrskin.1 -Some DVD-RW statements - -2007.01.03.163026 [583] -libburn/mmc.c -Made formatting report progress (as good as the drive does) - -2007.01.03.164716 [584] -libburn/async.c -libburn/drive.c -Moved blanking suitability test before eventual spwaning of threads - -2007.01.05.125715 [587] -libburn/mmc.c -libburn/write.c -Comments and name changes from new findings out of reading MMC-5 - -2007.01.06.120551 [591] -libburn/libburn.h -libburn/transport.h -libburn/mmc.h -libburn/mmc.c -libburn/async.c -libburn/drive.h -libburn/drive.c -libburn/write.c -cdrskin/cdrskin.c -test/libburner.c -New formatting parameter "size". Sorry for changing API. Function is a week old. - -8 Jan 2007 [592] -libburn/os-linux.h -libburn/os-freebsd.h -Added note that buffer may not be smaller than 32768 - -2007.01.08.104222 [593] -libburn/libburn.h -libburn/drive.c -libburn/write.c -libburn/mmc.c -Introduced size parameter to DVD-RW formatting plus writing of zeros. - -2007.01.08.104407 [594] -cdrskin/cdrskin.1 -cdrskin/cdrskin.c -Using 128 MB of size plus writing of zeros with blank=format_overwrite - -2007.01.09.140302 [595] -libburn/drive.c -Fixed a SIGFPE with formatting via libburner - -9 Jan 2007 [596] -libburn/libburn.h -libburn/transport.h -libburn/libdax_msgs.h -libburn/drive.c -libburn/write.c -libburn/mmc.c -Enhanced DVD-RW formatting - -2007.01.09.211152 [597] -cdrskin/README -cdrskin/cdrskin.1 -cdrskin/cdrskin.c -Now available: "quickest" and "full" formatting for DVD-RW - - ------------------------------------- cycle - cdrskin-0.2.7 - 2007.01.10.101406 - - -10 Jan 2007 [598] -cdrskin/cdrskin_eng.html -Updated size estimation of development downloads - -10 Jan 2007 [599] -cdrskin/changelog.txt -Next cdrskin-0.2.7 cycle - -2007.01.10.152350 [600] -libburn/libburn.h -libburn/mmc.c -libburn/drive.c -libburn/async.c -cdrskin/cdrskin.c -Option -force enables re-formatting - -2007.01.10.152520 [601] -libburn/mmc.c -Switched full formatting from type 10h to 00h which includes lead-out - -2007.01.10.152812 [602] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -cdrskin/README -Removed writing of dummy data with blank=format_overwrite_full - -2007.01.10.204839 [603] -libburn/mmc.c -libburn/async.c -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Enabled explicit full formatting of DVD+RW ("de-icing") - -11 Jan 2007 [604] -cdrskin/README -Removed outdated option from startup file example - -2007.01.11.131106 [605] -libburn/mmc.c -With full formatting prefer format 10h over 13h or 15h - -2007.01.11.131302 [606] -libburn/os-linux.h -libburn/os-freebsd.h -libburn/cleanup.c -cdrskin/cleanup.c -Kept SIGWINCH from spoiling a burn. - -2007.01.11.131615 [607] -libburn/init.c -Sketched better handling of self-inflicted SIGs - -2007.01.11.131716 [608] -libburn/drive.c -Removed surplus newlines from messages - -2007.01.12.162239 [609] -libburn/write.c -libburn/spc.c -libburn/mmc.c -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Enabled writing to DVD-RAM - -2007.01.13.140812 [610] [611] -libburn/sg-linux.c -Implemented debugging messages for ATA enumeration - -13 Jan 2007 [612] -cdrskin/cdrskin_eng.html -cdrskin/README -Documentation updates about DVD-RAM - -2007.01.13.211425 [613] -libburn/transport.h -libburn/mmc.c -Load array of format capacities into struct burn_drive - -2007.01.13.211639 [614] -libburn/libburn.h -libburn/drive.c -libburn/async.c -Introduced API for inspection and selection of format capacities - -13 Jan 2007 [615] -test/telltoc.c -Added printing of list of available formats - -13 Jan 2007 [616] -test/libburner.c -Mentioned DVD-RAM where appropriate - -2007.01.13.214259 [617] -cdrskin/cdrskin.c -Shifted fifo reporting to new 4-times -v verbosity level - -2007.01.14.101742 [618] -cdrskin/cdrskin.c -Corrected bug with debug messages for fifo - -2007.01.14.115347 [619] -libburn/write.c -Added missing cache sync in case of aborted DVD-RW burns - -2007.01.14.133951 [620] -libburn/transport.h -libburn/mmc.c -libburn/write.c -Avoided closing of 0x13-DVD-RW sessions which are not intermediate - -15 Jan 2007 [621] -cdrskin/wiki_plain.txt -Updated about overwriteable DVD and pointer to dvd+rw-tools - - ------------------------------------- cycle - cdrskin-0.2.7 - 2007.01.15.131357 -* Burning to DVD-RAM - - -15 Jan 2007 [623] -cdrskin/changelog.txt -Next cdrskin-0.2.7 cycle - -2007.01.16.120001 [tag 624] -Makefile.am -configure.ac -README -cdrskin/cdrskin.c -cdrskin/README -cdrskin/compile_cdrskin.sh -cdrskin/cdrskin_timestamp.h -cdrskin/changelog.txt -Made version number transition to 0.3.0 - -15 Jan 2007 [tag 625] -- cdrskin/add_ts_changes_to_libburn_0_2_6 -- cdrskin/add_ts_changes_to_libburn_0_2_7 -+ cdrskin/add_ts_changes_to_libburn_0_3_0 -Updated cdrskin tarball generator - -16 Jan 2007 [tag 626] -README -Corrected statement about restriction to CD - -16 Jan 2007 [tag 627] -cdrskin/cdrskin.c -Silenced a compiler warning - -16 Jan 2007 [tag 628] -cdrskin/README -Corrected name of tarball - -16 Jan 2007 [tag 632] -test/telltoc.c -Corrected old libburn.pykix.org URL - -16 Jan 2007 [tag 634] -cdrskin/cdrskin_eng.html -Updated web page - - -------------------------------- cycle - cdrskin-0.3.0.pl00 - 2007.01.16.120001 -* Improved recognition of unsuitable media types -* Replaced ban of chmod u+s by loud warning -* detailed man page for cdrskin -* Burning of DVD+RW and DVD-RAM media as single-track TAO-like initial session -* Formatting and then burning to DVD-RW like to DVD+RW -* New option -msifile=path from cdrkit/wodim - - -16 Jan 2007 [629] -- cdrskin/add_ts_changes_to_libburn_0_2_6 -- cdrskin/add_ts_changes_to_libburn_0_2_7 -+ cdrskin/add_ts_changes_to_libburn_0_3_0 -+ cdrskin/add_ts_changes_to_libburn_0_3_1 -Updated cdrskin tarball generator - -2007.01.16.151041 [630] -Makefile.am -configure.ac -cdrskin/cdrskin.c -cdrskin/README -cdrskin/compile_cdrskin.sh -Made version number transition to 0.3.1 - -16 Jan 2007 [631] -test/telltoc.c -Corrected old libburn.pykix.org URL - -16 Jan 2007 [633] -cdrskin/cdrskin_eng.html -Corrected typo - - ------------------------------------- cycle - cdrskin-0.3.1 - 2007.01.16.152345 - - -16 Jan 2007 [635] -cdrskin/changelog.txt -Next cdrskin-0.3.1 cycle - -17 Jan 2007 [636] -cdrskin/wiki_plain.txt -Removed paragraph about obsoleted tao_to_sao_tsize= - -18 Jan 2007 [637] -+ doc/cookbook.txt -Wrote down what i learned from implementing support for overwriteable DVD - -18 Jan 2007 [638] -doc/cookbook.txt -More info about Current/Maximum Capacity Descriptor - -18 Jan 2007 [639] -doc/cookbook.txt -Made clarification about formatting state recognition - -2007.01.18.211740 [640] -libburn/transport.h -libburn/mmc.c -libburn/write.c -Kept DVD+RW from stopping BG formatting if it was not started at all - -2007.01.19.110510 [641] -libburn/mmc.c -Removed forgotten debug message printed to stderr - -19 Jan 2007 [642] -doc/cookbook.txt -Began to describe TAO multi-session CD writing - -20 Jan 2007 [643] -doc/cookbook.txt -Changes with CD part. Especially explanation of TOC. - -2007.01.21.190928 [644] -cdrskin/cdrskin.c -Removed unnecessary after-grab loops - -2007.01.21.191058 [645] -libburn/write.c -Comments learned from studying MMC-3 and MMC-5 for SAO CD cookbook - -21 Jan 2007 [646] -doc/cookbook.txt -Clarification about TAO and mode page 05h per track - -2007.01.22.114245 [647] -libburn/libburn.h -libburn/write.c -libburn/async.c -libburn/libdax_msgs.h -cdrskin/cdrskin.c -Bug fix: Banned mixed mode SAO (because broken in libburn and unclear in MMC) - -23 Jan 2007 [648] -doc/cookbook.txt -Added SAO CD Cookbook - -23 Jan 2007 [649] -doc/cookbook.txt -Corrections of typos and text debris - -2007.01.25.145846 [652] -libburn/structure.c -Bug fix: DVD tracks of defined size >=2GB suffered 32-bit integer wraparound - -2007.01.25.185214 [655] -libburn/libburn.h -libburn/write.c -libburn/structure.h -libburn/structure.c -libburn/file.h -libburn/file.c -Enforce minimum track length with SAO - -2007.01.25.180001 [tag 656] -libburn_0_3_0_1/libburn/structure.c -libburn_0_3_0_1/cdrskin/cdrskin_timestamp.h -libburn_0_3_0_1/cdrskin/README -Bug fix: DVD tracks of defined size >=2GB suffered 32-bit integer wraparound - -26 Jan 2007 [tag 657] -libburn_0_3_0_1/cdrskin/cdrskin_eng.html -Mentioned new cdrskin patch level 01 - -26 Jan 2007 [658] -cdrskin/cdrskin_eng.html -Now offering cdrskin-0.3.0.pl01 for download - - ------------------------------------- cycle - cdrskin-0.3.1 - 2007.01.26.111920 - -2007.01.26.173236 [659] -libburn/file.h -libburn/file.c -Unified burn_file_source and burn_fd_source - -27 Jan 2007 [660] -libburn/null.c -Initialized member set_size of burn_source within burn_null_source_new() - -27 Jan 2007 [tag 661] -libburn_0_3_0_1/libburn/file.c -Removed 1.3 GB curbs for sources created by burn_file_source_new() - -29 Jan 2007 [662] -doc/cookbook.txt -Added a statement about blanking of DVD-RW - -2007.01.29.175822 [663] -libburn/transport.h -libburn/drive.c -libburn/write.c -libburn/mmc.c -Experiments about list of features and profiles - -2007.01.30.165317 [664] -libburn/write.c -libburn/mmc.c -Preparations for DVD-R[W] Sequential Recording - -2007.01.30.191740 [665] -libburn/write.c -libburn/mmc.c -First successful multi-session write to a sequential DVD-RW - -30 Jan 2007 [666] -doc/cookbook.txt -Added snapshot of emerging sequential DVD-R[W] cookbook - -2007.01.30.220220 [667] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Enabled Burnfree buffer underrun protection by default - -2007.01.31.130100 [668] -libburn/async.c -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Blank sequential DVD-RW, deformat overwriteable DVD-RW - -2007.01.31.173611 [669] -libburn/libburn.h -libburn/transport.h -libburn/drive.c -libburn/mmc.c -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Provisorily obtain multi-session -C parameters (violates MMC specs but works) - -2007.02.01.161634 [670] -libburn/libburn.h -libburn/transport.h -libburn/mmc.c -test/telltoc.c -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Obtain TOC from non-CD via 52h READ TRACK INFORMATION - -2007.02.01.163511 [671] -cdrskin/cdrskin.c -Reacted on justified compiler warning about unitialized sessions variable - -2007.02.01.191638 [672] -libburn/mmc.c -cdrskin/cdrskin.c -Allow blanking of DVD-RW which offer no Incremental Streaming - -1 Feb 2007 [673] -cdrskin/cdrskin_eng.html -cdrskin/README -cdrskin/cdrskin.1 -Prepared next cdrskin-0.3.1 cycle - -1 Feb 2007 [674] -cdrskin/changelog.txt -Prepared next cdrskin-0.3.1 cycle - -1 Feb 2007 [675] [676] -cdrskin/cdrskin.1 -Mentioned DVD-RW multi-session in overview of features - ------------------------------------- cycle - cdrskin-0.3.1 - 2007.02.01.203057 -* Burnfree enabled by default -* Multi-session recording on sequential DVD-RW, including -toc, -msinfo - - -2 Feb 2007 [677] -cdrskin/convert_man_to_html.sh -Some sed expressions for beautification - -2 Feb 2007 [678] -doc/cookbook.txt -Updated about DVD-R[W] blanking, multi-session info and TOC - -2007.02.02.151327 [679] -libburn/mmc.c -test/telltoc.c -Make mmc_read_multi_session_c1 use TOC if available - -2007.02.02.173345 [680] -libburn/mmc.c -cdrskin/cdrskin.c -Improved classification and TOC of finalized DVD-R[W] media - ------------------------------------- cycle - cdrskin-0.3.1 - 2007.02.02.183755 - -3 Feb 2007 [681] -cdrskin/cdrskin.1 -cdrskin/wiki_plain.txt -Mentioned DVD-RW multi-session - -2007.02.03.205526 (comitted 4 Feb 2007) [682] -libburn/libburn.h -libburn/mmc.c -libburn/drive.c -libburn/async.c -test/telltoc.c -New in API : struct burn_multi_caps and burn_disc_get_multi_caps() - -2007.02.05.132335 [683] -libburn/transport.h -libburn/mmc.c -Preparations for DVD-R[W] DAO - -2007.02.06.130410 [684] -libburn/libburn.h -libburn/mmc.c -libburn/write.c -libburn/drive.c -libburn/libdax_msgs.h -Implemented DVD-R[W] DAO as BURN_WRITE_SAO - -2007.02.06.170621 [685] -libburn/write.c -libburn/mmc.c -Beautification of debugging messages - -2007.02.06.174320 [686] -cdrskin/cdrskin.c -tao_to_sao_tsize= for DVD-R[W] DAO - -2007.02.06.185534 [687] -libburn/async.c -cdrskin/cdrskin.c -Enabled fast blank for DVD-R[W] - -6 Feb 2007 [688] -cdrskin/cdrskin.1 -Clarified CD and DVD peculiarities - -6 Feb 2007 [689] -doc/cookbook.txt -Described DVD-R[W] DAO mode - ------------------------------------- cycle - cdrskin-0.3.1 - 2007.02.06.200802 -* DVD-R[W] Disk-at-once writing - -6 Feb 2007 [690] -cdrskin/README -cdrskin/changelog.txt -cdrskin/cdrskin_eng.html -Next cdrskin-0.3.1 cycle - -2007.02.07.162836 [691] -libburn/libburn.h -libburn/drive.h -libburn/drive.c -libburn/options.c -libburn/libdax_msgs.h -New API function burn_write_opts_auto_write_type() - -7 Feb 2007 [692] -test/libburner.c -Made use of burn_write_opts_auto_write_type() - -7 Feb 2007 [693] -test/libburner.c -doc/comments -Updated documentation aspects - -8 Feb 2007 [694] -README -doc/comments -cdrskin/cdrskin.1 -cdrskin/README -Finally made tests with DVD-R. They burn indeed like DVD-RW. - -2007.02.08.210744 [695] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -New option --prodvd_cli_compatible - -8 Feb 2007 [696] -cdrskin/wiki_plain.txt -cdrskin/cdrskin_eng.html -Mentioned DVD-R - -2007.02.08.225208 [697] -cdrskin/cdrskin.c -Silenced compiler warning - - ------------------------------------- cycle - cdrskin-0.3.1 - 2007.02.09.074058 - -9 Feb 2006 [698] -cdrskin/cdrskin_eng.html -Added special thanks towards Andy Polyakov - -9 Feb 2006 [699] -cdrskin/cdrskin.1 -doc/cookbook.txt -Small corrections in documentation - -10 Feb 2007 [tag 701] [705] -- cdrskin/add_ts_changes_to_libburn_0_3_0 -- cdrskin/add_ts_changes_to_libburn_0_3_1 -+ cdrskin/add_ts_changes_to_libburn_0_3_2 -+ cdrskin/add_ts_changes_to_libburn_0_3_3 -Updated cdrskin tarball generator - -2007.02.10.120001 [tag 702] [704] -Makefile.am -configure.ac -README -cdrskin/cdrskin.c -cdrskin/README -cdrskin/compile_cdrskin.sh -cdrskin/cdrskin_timestamp.h -cdrskin/wiki_plain.txt -cdrskin/cdrskin_eng.html -Made number transition and activated development documentation - -10 Feb 2007 [tag 703] [707] -cdrskin/changelog.txt -Documented changes and 0.3.2 release timestamp - - ------------------------------ release - cdrskin-0.3.2.pl00 - 2007.02.10.120001 -* Burnfree enabled by default -* Multi-session recording on sequential DVD-R[W], including -toc, -msinfo -* DVD-R[W] Disk-at-once recording - - -10 Feb 2007 [706] -libburn/mmc.c -Added a comment about DVD-R - - ------------------------------------- cycle - cdrskin-0.3.3 - 2007.02.10.190528 - - -12 Feb 2007 [708] -cdrskin/cdrskin.1 -Being exacting about on-the-fly and DVD-RW - - -12 Feb 2007 [709] -cdrskin/cdrskin_eng.html -Updated list of keywords - -2007.02.12.142245 [710] -libburn/mmc.c -Made profile 0010h DVD-ROM suitable,full,not erasable. So it delivers a TOC. - - -2007.02.13.115459 [711] -libburn/spc.c -Set a suitable page 05h after spc_probe_write_modes() - -2007.02.13.143718 [712] -libburn/libburn.h -libburn/transport.h -libburn/mmc.c -libburn/spc.c -libburn/drive.c -Mew API function burn_disc_available_space() - -13 Feb 2007 [713] -test/libburner.c -Removed or updated outdated restriction statements - -13 Feb 2007 [714] -test/telltoc.c -Applied new API function burn_disc_available_space() - -2007.02.14.120213 [715] -libburn/spc.c -Removed outdated ifdef - -14 Feb 2007 [716] -test/telltoc.c -Set the advised write mode before inquiring media space - -2007.02.14.121440 [717] -libburn/libdax_msgs.h -libburn/mmc.c -Handle eventual ridiculously high d->last_track_no - -2007.02.14.122218 [718] -libburn/mmc.h -Forgotten part of revision 718 - -2007.02.14.202944 [719] -libburn/libburn.h -libburn/options.h -libburn/options.c -libburn/structure.h -libburn/structure.c -libburn/write.c -libburn/drive.c -Optional padding up to full media size when closing (incomplete yet) - -2007.02.14.203635 [720] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -New options --fill_up_media and --tell_media_space - -2007.02.15.201506 [722] -libburn/options.c -libburn/drive.c -cdrskin/cdrskin.c -libburn/write.c -Took fill_up_media into respect with automatic write mode decisions - -2007.02.15.201651 [723] -libburn/transport.h -libburn/mmc.c -libburn/libdax_msgs.h -Installed a guardian for predicted track end - -2007.02.15.201757 [724] -libburn/structure.c -Corrected bug about open_ended filluped tracks - -15 Feb 2007 [725] -libburn/libburn.h -cdrskin/cdrskin.1 -Clarifications about current state of fillup - -2007.02.15.203448 [726] -libburn/write.c -Repaired debugging message spoiled by uninitialized variable - -2007.02.16.111941 [728] -libburn/write.c -Corrected CD TAO bug introduced with DVD bug fix 724 and CD SAO change 655 - -2007.02.17.085118 [729] -libburn/structure.c -Another bug fix for revision 724 - -2007.02.17.085533 [730] -libburn/async.c -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -test/libburner.c -Allowed forceful blanking of blank media in burn_disc_erase() - -17 Feb 2007 [731] -test/libburner.c -Removed unprecise unnecessary comment - - ------------------------------------- cycle - cdrskin-0.3.3 - 2007.02.17.121238 -* New option --tell_media_space tells the maximum size for the next burn - - -2007.02.18.094414 [732] -libburn/libburn.h -Clarified usage comment with burn_drive_info_free() (see ticket 98) - -18 Feb 2007 [733] -cdrskin/cdrskin.1 -cdrskin/cdrskin_eng.html -cdrskin/changelog.txt -Next cdrskin-0.3.3 cycle - - -2007.02.18.094858 [734] -libburn/mmc.h -Adjusted maximum realistic number of tracks to MMC specs - -2007.02.19.184132 [735] -cdrskin/cdrskin.c -Repaired slightly broken pacifier track size display with -audio - -2007.02.19.225102 [736] -libburn/libburn.h -libburn/async.c -libburn/structure.h -libburn/structure.c -libburn/write.h -libburn/write.c -libburn/drive.h -libburn/drive.c -libburn/options.c -libburn/libdax_msgs.h -Re-arranged checking and defaulting of write parameters -= -New API function burn_track_set_default_size() -New API function burn_precheck_write() -Make wide use of burn_disc_write_mode_demands() - -2007.02.21.205244 [737] -libburn/libburn.h -libburn/async.c -libburn/drive.c -libburn/options.c -libburn/structure.c -libburn/write.c -libburn/libdax_msgs.h -cdrskin/cdrskin.c -Moved tao_to_sao_tsize into libburn, let cdrskin use auto_write_type and precheck - -21 Feb 2007 [738] -cdrskin/add_ts_changes_to_libburn_0_3_3 -cdrskin/add_ts_changes_to_libburn_0_3_2 -Added -O2 to binary production - -2007.02.22.072700 [739] -libburn/libburn.h -libburn/drive.c -libburn/options.c -Re-enabled overwriteable pseudo-pseudo-SAO with unpredicted track size - -2007.02.22.073157 [740] -libburn/mmc.c -Disabled debugging messages about format descriptors - -2007.02.22.094939 [741] -libburn/libburn.h -libburn/options.c -libburn/write.c -libburn/async.c -test/libburner.c -cdrskin/cdrskin.c -Macro for length of rejection reasons string (old size is still safe) - -2007.02.22.113016 [742] -libburn/libburn.h -libburn/drive.c -Made burn_disc_available_space() take into respect burn_write_opts_set_start_byte() - -2007.02.23.190937 [743] -libburn/libburn.h -libburn/drive.c -libburn/mmc.c -libburn/write.c -doc/cookbook.txt -Enabled DVD-R/DL Sequential via burn_allow_untested_profiles() - -2007.02.23.191117 [744] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Enabled DVD-R/DL Sequential via --allow_untested_media_types - -2007.02.23.193427 [745] -libburn/init.c -Forgotten source file for revision 743 - ------------------------------------- cycle - cdrskin-0.3.3 - 2007.02.24.102731 - - -2007.02.25.112733 [746] -libburn/write.h -libburn/write.c -libburn/drive.c -cdrskin/cdrskin.1 -Took into respect deliberate lack of DVD-R/DL multi session capability - -2007.03.01.120945 [747] -libburn/drive.c -libburn/mmc.c -libburn/write.c -cdrskin/cdrskin.c -doc/cookbook.txt -Preparations for supporting DVD+R[/DL] - -3 Mar 2007 [748] -cdrskin/cdrskin.1 -Updated DVD-R[W] write mode description - -2007.03.03.141240 [749] -libburn/transport.h -libburn/mmc.c -Determine physical interface SCSI,ATA,SATA,USB,... (for future use) - -2007.03.03.141435 [750] -libburn/libburn.h -libburn/write.c -libburn/options.h -libburn/options.c -cdrskin/cdrskin.c -Re-enabled -force with write modes which seem unavailable - -2007.03.03.151812 [751] -libburn/options.c -Fixed bug introduced with rev 736ff which prevented audio CD burning - -2007.03.04.184720 [752] -cdrskin/cdrskin.c -cdrskin/cdrfifo.c -Fifo got stuck if sum of processed track sizes was exactly aligned to fifo size - ------------------------------------- cycle - cdrskin-0.3.3 - 2007.03.04.185202 -* Bug fix: Multi-track runs with fifo could stall in rare cases - -5 Mar 2007 [753] -cdrskin/cdrskin_eng.html -cdrskin/add_ts_changes_to_libburn_0_3_2 -Released cdrskin-0.3.2.pl01 - -2007.03.06.195203 [754] -libburn/mmc.c -libburn/write.c -Enabled DVD+R, DVD+R DL via --allow_untested_media_types, always -multi for now - -2007.03.06.205312 [755] -libburn/mmc.c -cdrskin/cdrskin.1 -doc/cookbook.txt -doc/comments -Enabled DVD+R as tested media (-multi is still always on) - -2007.03.07.151514 [756] -libburn/write.c -cdrskin/cdrskin.1 -cdrskin/README -doc/cookbook.txt -Some adjustments for DVD+R recording - -2007.03.07.151514 [756] -cdrskin/cdrskin_eng.html -cdrskin/changelog.txt -Next cdrskin-0.3.3 cycle - ------------------------------------- cycle - cdrskin-0.3.3 - 2007.03.07.155750 -* Multi-session burning to DVD+R - - -8 Mar 2007 [757] -cdrskin/cdrskin.1 -cdrskin/convert_man_to_html.sh -cdrskin/wiki_plain.txt -Polished documentation - -2007.03.09.134622 [758] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -New option assert_write_lba= - -10 Mar 2007 [759] -cdrskin/cdrskin.1 -cdrskin/wiki_plain.txt -Polished documentation - - ------------------------------------- cycle - cdrskin-0.3.3 - 2007.03.10. -* New option assert_write_lba= - -2007.03.12.110001 [tag 761] -Makefile.am -configure.ac -README -cdrskin/cdrskin.c -cdrskin/README -cdrskin/compile_cdrskin.sh -cdrskin/cdrskin_timestamp.h -cdrskin/cdrskin_eng.html -Made number transition to 0.3.4 and activated development documentation - -12 Mar 2007 [tag 762] -- cdrskin/add_ts_changes_to_libburn_0_3_2 -- cdrskin/add_ts_changes_to_libburn_0_3_3 -+ cdrskin/add_ts_changes_to_libburn_0_3_4 -+ cdrskin/add_ts_changes_to_libburn_0_3_5 -Updated cdrskin tarball generator - -12 Mar 2007 [tag 763] -cdrskin/changelog.txt -Documented most recent changes - -12 Mar 2007 [tag 764] -README -Removed redundant sentence - ------------------------------ release - cdrskin-0.3.4.pl00 - 2007.03.12.110001 -* Multi-session burning to DVD+R -* New option --tell_media_space tells the maximum size for the next burn -* New option assert_write_lba= -* Bug fix: Multi-track runs with fifo could stall in rare cases - - -2007.03.12.155600 [765] -Makefile.am -configure.ac -README -cdrskin/cdrskin.c -cdrskin/README -cdrskin/compile_cdrskin.sh -cdrskin/cdrskin_timestamp.h -cdrskin/cdrskin_eng.html -Made number transition to 0.3.5 - -12 Mar 2007 [766] -- cdrskin/add_ts_changes_to_libburn_0_3_2 -- cdrskin/add_ts_changes_to_libburn_0_3_3 -+ cdrskin/add_ts_changes_to_libburn_0_3_4 -+ cdrskin/add_ts_changes_to_libburn_0_3_5 -Updated cdrskin tarball generator - - ------------------------------------- cycle - cdrskin-0.3.5 - 2007.03.12.160658 - -14 Mar 2007 [767] -cdrskin/cdrskin_eng.html -Corrected truncated sentence and file sizes - -14 Mar 2007 [768] -cdrskin/changelog.txt -Next cdrskin-0.3.5 cycle - -2007.03.14.133618 [769] -libburn/libburn.h -libburn/init.c -libburn/sg-linux.c -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -New option drive_scsi_dev_family=sr|scd|sg - -2007.03.15.194531 [770] -libburn/drive.c -React properly on drive stating that it cannot write any media - -2007.03.15.195005 [771] -libburn/spc.h -libburn/spc.c -libburn/sbc.c -After loading tray wait for unit to become ready or to report some clear error - -2007.03.15.195251 [772] -cdrskin/cdrskin.c -Moved manual device family decision to a sufficiently early stage - -2007.03.15.195428 [773] -libburn/mmc.c -Kept mmc_get_configuration() from believing the announcement of 1 GB reply - -2007.03.15.195534 [774] -libburn/sg-linux.c -Trying to recognize kernel >= 2.6 and use /dev/sr by default - -15 Mar 2007 [775] -cdrskin/cdrskin.1 -Updated drive_scsi_dev_family= - -15 Mar 2007 [776] -cdrskin/changelog.txt -Next cdrskin-0.3.5 cycle - ------------------------------------- cycle - cdrskin-0.3.5 - 2007.03.16.001311 -* Usage of /dev/srN rather than /dev/sgN on Linux >= 2.6 -* New option drive_scsi_dev_family=sr|scd|sg - - -18 Mar 2007 [777] -cdrskin/cdrskin_eng.html -Mentioned new sr behavior - -2007.03.24.093238 [785] -libburn/drive.c -Fixed bug with burn_disc_available_space(...,NULL) - -2007.03.24.093623 [786] -cdrskin/cdrskin.c -Warning of very small tsize= settings. (Proposal by Eduard Bloch) - -2007.03.27.213543 [787] -cdrskin/cdrskin.c -cdrskin/cdrfifo.h -cdrskin/cdrfifo.c -Preparations for option -isosize via fifo (only a debug message yet) - -2007.03.28.100934 [788] -libburn/libburn.h -libburn/structure.c -cdrskin/cdrskin.c -Enabled -isosize for first track by help of fifo and without seeking - -2007.03.28.111739 [789] -cdrskin/cdrskin.c -Silenced error condition about -sao with stdin and -isosize - -2007.03.28.160503 [790] -cdrskin/cdrskin.c -Enabled -isosize with S_IFREG or S_IFBLK files and without fifo - -2007.03.28.182419 [791] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Made fifo based -isosize read 64k first and the rest only at normal stage - -2007.03.28.202802 [792] -cdrskin/cdrskin.c -Silenced error message if tsize= is smaller than source is willing to deliver - - ------------------------------------- cycle - cdrskin-0.3.5 - 2007.03.28.212322 -* Option -isosize is supported now - - -29 Mar 2007 [793] -cdrskin/cdrskin_eng.html -cdrskin/changelog.txt -Next cdrskin-0.3.5 cycle - -2007.03.30.201034 [794] -libburn/write.c -cdrskin/cdrskin.1 -Allowed finalizing of DVD+R - -2007.03.30.214657 [795] -libburn/write.c -Avoided unconditional finalizing of DVD+R - -2007.04.03.140356 [796] -libburn/sg-linux.c -Added fcntl() locking to O_EXCL locking - -2007.04.03.145637 [797] -cdrskin/cdrskin.c -Make --old_pseudo_scsi_adr -scanbus work with any drive_scsi_dev_family= - -2007.04.03.145806 [798] -libburn/libdax_msgs.h -Added fcntl() locking to O_EXCL locking - -2007.04.04.184341 [799] -libburn/libburn.h -libburn/init.c -libburn/sg-linux.c -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -New cdrskin options --drive_not_f_setlk and --drive_not_o_excl - -6 Apr 2007 [801] -test/libburner.c -Updated media list in introduction comment - -2007.04.09.105543 [802] -libburn/transport.h -libburn/os-linux.h -libburn/sg-linux.c -cdrskin/cdrskin.1 -Cleaned up scsi sibling management, sketched grafting of DDLP - -2007.04.09.111215 [803] -libburn/sg-linux.c -Reacted on compiler warning about last_rdev, fixed fresh typo bug - - ------------------------------------- cycle - cdrskin-0.3.5 - 2007.04.09.112127 -* DVD+R now get finalized (if not -multi is given) - - -10 Apr 2007 [804] -cdrskin/changelog.txt -Next cdrskin-0.3.5 cycle - -2007.04.10.081855 [805] -libburn/init.c -Fixed bug with drive_scsi_dev_family= introduced by revision 796 (fcntl lock) - -2007.04.10.082229 [806] -libburn/sg-linux.c -Used O_EXCL|O_RDWR and fcntl() even within sg_obtain_scsi_adr() - -2007.04.10.083119 [807] -libburn/sg-linux.c -Fixed bug in sg_open_scsi_siblings() introduced with revision 802 - -2007.04.10.144840 [808] -libburn/spc.c -libburn/libdax_msgs.h -Avoided SIGSEGV with an old SCSI CD-ROM drive and its wild replies - -12 Apr 2007 [810] -README -Clarified license. People who object shall please come forward now. - -2007.04.13.171347 [815] -libburn/sg-linux.c -libburn/libdax_msgs.h -Switched from O_NONBLOCK to O_NDELAY (see http://lkml.org/lkml/2007/4/11/141) - -2007.04.13.173008 [816] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Made use of fcntl(F_SETLK) switchable (and thus became more free with default) - -15 Apr 2007 [819] -+ libburn/ddlpa.h -+ libburn/ddlpa.c -Began test implementation of DDLP-A - -15 Apr 2007 [820] -libburn/ddlpa.h -libburn/ddlpa.c -Implemented ddlpa_lock_btl() - -16 Apr 2007 [821] -doc/cookbook.txt -Finalized DVD+R cookbook - -16 Apr 2007 [822] -+ doc/ddlp.txt -Emerging description of DDLP - -16 Apr 2007 [823] -doc/ddlp.txt -libburn/ddlpa.h -libburn/ddlpa.c -Polished txt and finally threw out getter functions - -16 Apr 2007 [824] -libburn/ddlpa.h -Corrected description of return values - -18 Apr 2007 [825] -+ test/open-cd-excl.c -Program for probing access to device files. By Ted Ts'o with modifications by me. - -18 Apr 2007 [826] -doc/ddlp.txt -Allowed for Friendly Programs: O_EXCL | O_RDONLY - -18 Apr 2007 [827] -libburn/ddlpa.h -libburn/ddlpa.c -Progress due to tests with test/open-cd-excl - -2007.04.18.103734 [828] -libburn/mmc.c -Updated comments about DVD+R - -18 Apr 2007 [829] -test/open-cd-excl.c -libburn/ddlpa.c -doc/ddlp.txt -Polished messages, comments and description of DDLP-A - -18 Apr 2007 [830] -test/open-cd-excl.c -doc/ddlp.txt -Adaptations to new test results and discussions - -18 Apr 2007 [831] -doc/ddlp.txt -Corrected a list of standard paths - -19 Apr 2007 [832] [833] -doc/ddlp.txt -Clarifications about motivation and duties of the participants - -20 Apr 2007 [834] -doc/ddlp.txt -Beginning to develop DDLP-B - -21 Apr 2007 [835] -doc/ddlp.txt -Declared failure of DDLP to entirely solve the concurrency problem - ------------------------------------- cycle - cdrskin-0.3.5 - 2007.04.22.112236 - -22 Apr 2007 [836] -cdrskin/changelog.txt -Next cdrskin-0.3.5 cycle - -22 Apr 2007 [837] -cdrskin/add_ts_changes_to_libburn_0_3_5 -cdrskin/add_ts_changes_to_libburn_0_3_4 -Repaired autotools bootstrap bug by help of sed - -22 Apr 2007 [838] -cdrskin/cdrskin.1 -Changed many /dev/sg to /dev/sr - - -2007.04.23.130001 [tag 841] -Makefile.am -configure.ac -README -cdrskin/cdrskin.c -cdrskin/README -cdrskin/compile_cdrskin.sh -cdrskin/cdrskin_timestamp.h -cdrskin/wiki_plain.txt -cdrskin/cdrskin_eng.html -doc/comments -Made number transition and activated development documentation - -23 Apr 2007 [tag 842] -- cdrskin/add_ts_changes_to_libburn_0_3_4 -- cdrskin/add_ts_changes_to_libburn_0_3_5 -+ cdrskin/add_ts_changes_to_libburn_0_3_6 -+ cdrskin/add_ts_changes_to_libburn_0_3_7 -Updated cdrskin tarball generator - -23 Apr 2007 [tag 844] -cdrskin/README -Corrected false info about outdated addressing method - -2007.04.23.154600 [843] -Makefile.am -configure.ac -README -cdrskin/cdrskin.c -cdrskin/README -cdrskin/compile_cdrskin.sh -cdrskin/wiki_plain.txt -cdrskin/cdrskin_eng.html -doc/comments -Made number transition and activated development documentation - -23 Apr 2007 [845] -- cdrskin/add_ts_changes_to_libburn_0_3_4 -- cdrskin/add_ts_changes_to_libburn_0_3_5 -+ cdrskin/add_ts_changes_to_libburn_0_3_6 -+ cdrskin/add_ts_changes_to_libburn_0_3_7 -Updated cdrskin tarball generator - - ------------------------------ release - cdrskin-0.3.6.pl00 - 2007.04.23.130001 -* Usage of /dev/srN rather than /dev/sgN on Linux >= 2.6 -* New option drive_scsi_dev_family=sr|scd|sg -* Option -isosize is supported now -* DVD+R now get finalized (if not -multi is given) - - -2007.04.23.171735 [846] -cdrskin/changelog.txt -Next cdrskin-0.3.7 cycle - - ------------------------------------- cycle - cdrskin-0.3.7 - 2007.04.24.113310 - -2007.05.21.184334 [853] -libburn/sg-linux.c -Prepared fflushing and stderr output of SCSI command log - -2007.05.21.185450 [854] -libburn/sbc.c -libburn/spc.h -libburn/spc.c -libburn/mmc.c -libburn/toc.c -libburn/transport.h -For Linux 2.4, USB : Carefully avoided to inquire more data than available - -2007.05.21.185644 [855] -libburn/sector.c -libburn/write.c -For Linux 2.4, USB audio : Reduced CD output buffer size to 32 kiB - -21 May 2007 [856] -cdrskin/cdrskin_eng.html -cdrskin/changelog.txt -Next cdrskin-0.3.7 cycle - - ------------------------------------- cycle - cdrskin-0.3.7 - 2007.05.21.201501 -* Now able to cope with the peculiarities of Linux 2.4 USB - - -2007.05.22.154407 [857] -libburn/sg-linux.c -Report eventual sg_io_hdr_t host_status,driver_status as debug messages - -2007.05.22.154504 [858] -cdrskin/cdrskin.c -Disabled macro Cdrskin_debug_libdax_msgS. Thus getting unqueued error messages. - -2007.05.22.164850 [859] -libburn/sg-linux.c -Added SCSI opcode to output of revision 857 - -2007.05.28.132412 [860] -libburn/os-linux.h -libburn/write.c -Moved general 32 kiB buffer restriction from write.c to os-linux.h - -2007.05.28.165630 [861] -libburn/libburn.h -libburn/drive.c -test/telltoc.c -Extended struct burn_multi_caps by .might_simulate - -28 May 2007 [862] -libburn/libdax_msgs.h -Forgotten update of error list with revison 857 - -2007.05.28.170243 [863] -libburn/options.c -cdrskin/cdrskin.1 -Added check for .might_simulate to burn_write_opts_auto_write_type() - -2007.05.28.192421 [864] -libburn/sector.c -Fixed low transaction size introduced by cooperation of revisions 855 and 860 - - ------------------------------------- cycle - cdrskin-0.3.7 - 2007.05.28.192853 -* Refusal to perform -dummy runs on media which cannot simulate burning - -29 May 2007 [865] -cdrskin/cdrskin_eng.html -cdrskin/changelog.txt -Next cdrskin-0.3.7 cycle - -8 Jun 2007 [873] -- cdrskin/doener_150x200_tr.gif -- cdrskin/doener_150x200_tr_octx.gif -+ cdrskin/doener_150x200_tr.png -+ cdrskin/doener_150x200_tr_octx.png -cdrskin/cdrskin_eng.html -Changed logo graphics format from GIF to PNG - -8 Jun 2007 [874] -cdrskin/wiki_plain.txt -cdrskin/add_ts_changes_to_libburn_0_3_6 -cdrskin/add_ts_changes_to_libburn_0_3_7 -Took into respect change of logo graphics format - -8 Jun 2007 [875] -cdrskin/cdrskin.1 -Prevented macro interpretation of text snippet ".wav" - -10 Jun 2007 [876] -cdrskin/README -cdrskin/cdrskin.1 -Clarified MB to MiB if compatibility allows it (ticket 100) - -10 Jun 2007 [877] -cdrskin/cdrskin.1 -doc/cookbook.txt -test/libburner.c -Changed "KB" to "kiB" - ------------------------------------- cycle - cdrskin-0.3.7 - 2007.06.10.081025 - - -2007.07.12.162856 [882] -libburn/transport.h -libburn/mmc.c -libburn/write.c -libburn/libdax_msgs.h -Preparations to avoid writing which will not fit in drive buffer - -2007.07.12.171727 [883] -libburn/libburn.h -libburn/drive.c -New API-Function burn_drive_set_buffer_waiting() - -2007.07.12.171832 [884] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -New options modesty_on_drive= and minbuf= - -2007.07.14.111614 [885] -libburn/libburn.h -libburn/drive.c -New API function burn_drive_get_best_speed() - -2007.07.14.112029 [886] -libburn/mmc.c -Only set realistic maximum DVD speeds (for my LG GSA which fails otherwise) - -2007.07.14.112326 [887] -cdrskin/cdrskin.c -Experimental option --adjust_speed_to_drive. Caution: May vanish soon. - -17 Jul 2007 [888] -cdrskin/cdrskin.1 -Clarification on option speed= - -2007.07.17.085823 [889] -libburn/libburn.h -libburn/drive.c -libburn/mmc.c -cdrskin/cdrskin.c -Implemented minimum speed in burn_drive_set_speed() - -2007.07.19.072434 [890] -libburn/libburn.h -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Removed ban against speed 0 with burn_drive_set_buffer_waiting() - -2007.07.19.143139 [891] -cdrskin/cdrskin.c -Trying to prevent usage of burn drive as track source - -2007.07.19.171947 [892] -cdrskin/cdrskin.c -Avoided new track-drive test with option --no_convert_fs_adr - -19 Jul 2007 [893] -cdrskin/cdrskin.1 -Documented option --adjust_speed_to_drive (i.e. it will stay) - -19 Jul 2007 [894] -cdrskin/changelog.txt -Next cdrskin-0.3.7 cycle - -19 Jul 2007 [895] -cdrskin/cdrskin_eng.html -Next cdrskin-0.3.7 cycle - ------------------------------------- cycle - cdrskin-0.3.7 - 2007.07.19.174859 -* New option modesty_on_drive= may help with hda -> hdb burns -* New option minbuf= , cdrecord compatible frontend of modesty_on_drive= -* New option --adjust_speed_to_drive -* Precautions against using the burner drive as track source - -2007.07.20.120001 [branch 897] -Makefile.am -configure.ac -README -cdrskin/cdrskin.c -cdrskin/README -cdrskin/compile_cdrskin.sh -cdrskin/cdrskin_timestamp.h -cdrskin/cdrskin_eng.html -Made number transition to 0.3.8 - -20 Jul 2007 [branch 898] -- cdrskin/add_ts_changes_to_libburn_0_3_6 -- cdrskin/add_ts_changes_to_libburn_0_3_7 -+ cdrskin/add_ts_changes_to_libburn_0_3_8 -+ cdrskin/add_ts_changes_to_libburn_0_3_9 -Updated cdrskin tarball generators - -20 Jul 2007 [branch 899] -cdrskin/changelog.txt -Documented changes and release timestamp - -2007.07.20.210001 [900] -Makefile.am -configure.ac -README -cdrskin/cdrskin.c -cdrskin/README -cdrskin/compile_cdrskin.sh -cdrskin/cdrskin_timestamp.h -cdrskin/cdrskin_eng.html -Made number transition to 0.3.9 - -20 Jul 2007 [901] -- cdrskin/add_ts_changes_to_libburn_0_3_6 -- cdrskin/add_ts_changes_to_libburn_0_3_7 -+ cdrskin/add_ts_changes_to_libburn_0_3_8 -+ cdrskin/add_ts_changes_to_libburn_0_3_9 -Updated cdrskin tarball generators - -20 Jul 2007 [902] -cdrskin/changelog.txt -Documented changes - ------------------------------ release - cdrskin-0.3.8.pl00 - 2007.07.20.120001 -* Now able to cope with the peculiarities of Linux 2.4 USB -* Refusal to perform -dummy runs on media which cannot simulate burning -* New option modesty_on_drive= may help with hda -> hdb burns -* New option minbuf= , cdrecord compatible frontend of modesty_on_drive= -* New option --adjust_speed_to_drive -* Precautions against using the burner drive as track source - ------------------------------------- cycle - cdrskin-0.3.9 - 2007.07.20.200422 - -2 Aug 2007 [917] -cdrskin/cdrskin_eng.html -Corrected a harmless typo - -2 Aug 2007 [918] -doc/cookbook.txt -cdrskin/cdrskin.1 -Took into respect new info from Andy Polyakov about closing DVD+-R - -9 Aug 2007 [920] -cdrskin/cdrskin_eng.html -Corrected a dead link - -2007.08.09.133137 [921] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Allowed speed=any - -2007.08.09.133259 [922] -libburn/transport.h -Changed "unsigned" to "unsigned int" - -2007.08.09.133420 [923] -libburn/libdax_msgs.h -Corrected a typo - -9 Aug 2007 [924] -+ doc/libdax_model.txt -+ doc/libdax_overview.gif -+ doc/libdax_equip.gif -+ doc/libdax_job.gif -Obscure backup of my unripe model ideas about libcevap (former libdax) - -10 Aug 2007 [936] -doc/libdax_model.txt -Fiddled on the model attributes - -2007.08.10.201450 [937] -libburn/libburn.h -Updated comments about supported profiles and media types - -2007.08.10.203040 [938] -configure.ac -Changed "libburn-1.pc" to "libburn-5.pc" to re-enable ./bootstrap ; ./configure - -2007.08.11.075330 [941] -cdrskin/README -cdrskin/add_ts_changes_to_libburn_0_3_9 -cdrskin/cdrskin.c -cdrskin/cdrskin_eng.html -cdrskin/wiki_plain.txt -doc/comments -doc/cookbook.txt -test/libburner.c -test/telltoc.c -Reflected recent URL changes to libburnia-project.org - -2007.08.11.202027 [942] -libburn/libburn.h -libburn/write.c -libburn/libdax_msgs.h -New API function burn_random_access_write() - -2007.08.11.202627 [943] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -New option direct_write_amount= using new API call burn_random_access_write() - -12 Aug 2007 [944] -libburn/libburn.h -Clarifications about burn_random_access_write() - -2007.08.12.095446 [945] -libburn/write.c -libburn/libdax_msgs.h -Checked in burn_random_access_write() wether drive is grabbed - -2007.08.12.095623 [946] -cdrskin/cdrskin.c -Debug message explaining why burn_drive_convert_fs_adr() acts on track source - -2007.08.12.152937 [947] -libburn/libburn.h -libburn/transport.h -libburn/mmc.h -libburn/mmc.c -libburn/write.c -libburn/read.c -libburn/libdax_msgs.h -New API function burn_read_data() - -12 Aug 2007 [948] -test/telltoc.c -Testing burn_read_data() by option --read_and_print - ------------------------------------- cycle - cdrskin-0.3.9 - 2007.08.12.161808 -* New option direct_write_amount= - -13 Aug 2007 [949] -cdrskin/changelog.txt -Next cdrskin-0.3.9 cycle - -13 Aug 2007 [950] -cdrskin/cdrskin.1 -cdrskin/cdrskin_eng.html -Some polishing about option direct_write_amount= - -13 Aug 2007 [951] -doc/libdax_model.txt -Beautified implementation names and added some more attributes - -15 Aug 2007 [952] -doc/libdax_model.txt -Added more attributes and distinguished read-write, read-only, private ones - -2007.08.17.081901 [953] -libburn/transport.h -Corrected harmless type declaration flaws - -17 Aug 2007 [954] -doc/libdax_model.txt -Added more attributes and comments - -19 Aug 2007 [955] -+ libcevap/ -+ libcevap/cgen.c -+ libcevap/cgen.h -+ libcevap/ctyp.c -+ libcevap/ctyp.h -+ libcevap/smem.c -+ libcevap/smem.h -+ libcevap/cgen.txt -The C code generator mentioned in doc/libdax_model.txt. See there. - -19 Aug 2007 [956] -doc/libdax_model.txt -More comments, new capabilities of C code generator - -19 Aug 2007 [957] -+ libcevap/libcevap_gen.sh -+ libcevap/extract_cgen_input.sh -+ libcevap/main.c -doc/libdax_model.txt -Generator frontend scripts (./libcevap_gen.sh to be run in libcevap/) - -19 Aug 2007 [958] -doc/libdax_model.txt -Corrected description of compiling and generating - -20 Aug 2007 [959] -libcevap/cgen.c -Corrected a bug about inclusion of cevap*.h files - -21 Aug 2007 [960] -libcevap/smem.h -Added some function type declarations - -2007.08.22.134731 [961] -libburn/mmc.c -Corrected dangerous typo with error message production of mmc_read_10() - -22 Aug 2007 [962] -test/telltoc.c -Retrieving my old backups which are hit by the Linux Read-Ahead-Bug - -22 Aug 2007 [963] -libburn/read.c -test/telltoc.c -Avoiding libburn read-ahead-bug - -22 Aug 2007 [964] -test/telltoc.c -Avoided locked drive with interrupted telltoc read. (eject unlocks anyway) - -2007.08.22.173459 [965] -libburn/libburn.h -libburn/drive.c -libburn/read.c -libburn/write.c -Taking synchronous read/write into respect with abort handling - -2007.08.23.150423 [966] -libburn/libburn.h -libburn/mmc.c -libburn/read.c -Allowed to suppress error message from failed burn_read_data() - -23 Aug 2007 [967] -test/telltoc.c -Try to read last 2 blocks of CD track without eventual error message - -2007.08.25.085709 [968] -libburn/libburn.h -libburn/mmc.c -libburn/file.c -libburn/source.c -libburn/structure.c -Corrected memory management flaws found by Joris Dobbelsteen - -25 Aug 2007 [969] -test/telltoc.c -Reacted on false compiler warning about potentially unused variable - -2007.08.25.155931 [970] -libburn/mmc.c -libburn/file.c -More memory management changes proposed by Joris Dobbelsteen - -2007.08.26.200829 [971] -cdrskin/cdrskin.c -cdrskin/cdrfifo.h -cdrskin/cdrfifo.c -cdrskin/cdrskin.1 -New cdrskin option --grow_overwriteable_iso - -2007.08.28.143057 [974] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Made program behavior with --grow_overwriteable_iso more consistent - -28 Aug 2007 [975] -cdrskin/README -Mentioned --grow_overwriteable_iso - -29 Aug 2007 [976] -doc/libdax_model.txt -Work goes on - -29 Aug 2007 [977] -cdrskin/cdrskin_eng.html -cdrskin/changelog.txt -Next cdrskin-0.3.9 cycle - ------------------------------------- cycle - cdrskin-0.3.9 - 2007.08.29.124057 -* New option --grow_overwriteable_iso - -29 Aug 2007 [978] -cdrskin/compile_cdrskin.sh -Added missing file to link list: read.o - -29 Aug 2007 [979] -- doc/libdax_model.txt -- doc/libdax_overview.gif -- doc/libdax_job.gif -- doc/libdax_equip.gif -+ libcevap/libdax_model.txt -+ libcevap/libdax_overview.gif -+ libcevap/libdax_job.gif -+ libcevap/libdax_equip.gif -Moved libdax-libcevap model stuff to libcevap/ - -29 Aug 2007 [980] -libcevap/libcevap_gen.sh -Adapted C code generator script to new address of libdax_model.txt - -2007.09.01.182319 [984] -libburn/libburn.h -libburn/options.c -New API function burn_write_opts_get_drive() - -2007.09.04.224905 [987] -libburn/libburn.h -libburn/transport.h -libburn/async.c -libburn/drive.c -libburn/write.c -libburn/read.c -libburn/options.c -libburn/spc.c -libburn/libdax_msgs.h -New API calls burn_drive_grab_dummy(), burn_drive_get_drive_role() - -5 Sep 2007 [988] -test/telltoc.c -test/libburner.c -Testing new API functions via --drive stdio: - -2007.09.04.225558 [989] -libburn/write.c -libburn/read.c -Reacted on compiler warnings - -2007.09.05.194124 [991] -libburn/libburn.h -libburn/drive.c -test/libburner.c -test/telltoc.c -burn_drive_grab_dummy() becomes invisible part of burn_drive_scan_and_grab() - -2007.09.05.195248 [992] -libburn/write.c -Fixed a bug with failed opening of pseudo-drive - -2007.09.06.094402 [995] -libburn/drive.c -Added forgotten handling of pseudo-drives in burn_drive_grab() - -2007.09.06.095954 [996] -libburn/write.c -Added forgotten read/write counters in burn_stdio_write_track() - -2007.09.06.100100 [997] -cdrskin/cdrskin.c -Removed obstacles for use of stdio-drives - -2007.09.06.120844 [999] -libburn/libburn.h -libburn/drive.c -Promoted burn_drive_raw_get_adr() to API function burn_drive_d_get_adr() - -2007.09.07.102728 [1002] -libburn/write.c -Corrected write counter in burn_stdio_write_track() - -2007.09.07.123748 [1003] -libburn/libburn.h -libburn/async.c -libburn/drive.c -libburn/libdax_msgs.h -Made burn_drive_info_free() only delete the drive of its parameter - -7 Sep 2007 [1004] -test/telltoc.c -Reacted on changed media profile of stdio-drives - -2007.09.07.154951 [1005] -libburn/drive.h -libburn/drive.c -libburn/async.c -libburn/init.c -Made burn_drive_scan() refuse work on non-empty drive list. - -2007.09.07.163949 [1006] -libburn/async.c -libburn/drive.c -Corrected memory leak introduced by revision 1005 - -2007.09.07.164532 [1007] -libburn/drive.h -Forgotten file for revision 1006 - -2007.09.07.184631 [1008] -libburn/init.c -libburn/libdax_msgs.h -Avoided locked tray after failed burn_finish() because of busy drive - -7 Sep 2007 [1009] -test/telltoc.c -Lowered report severity to LIBDAX_MSGS_SEV_WARNING. - -2007.09.07.190916 [1010] -libburn/libburn.h -libburn/drive.c -libburn/libdax_msgs.h -Made burn_drive_scan_and_grab() extend the drive list rather than replacing it - -2007.09.07.234122 [1011] -libburn/drive.c -cdrskin/cdrskin.c -Report media profile in cdrskin blank, format, burn runs - -2007.09.07.234704 [1012] -libburn/drive.c -Bug fix about stdio: - -2007.09.08.102151 [1013] -libburn/drive.c -Fixed memory leak and possible SIGSEGV with pseudo-drives - -2007.09.08.102620 [1014] -cdrskin/cdrskin.c -Made cdrskin work with null-drive (which it mistook for something like ATA:) - -2007.09.08.132058 [1015] -libburn/drive.c -libburn/write.c -Allowed -dummy burns with stdio-drives (because /dev/null is no block device) - -2007.09.08.132206 [1016] -cdrskin/cdrskin.c -Changed speed measurement of stdio-drives to DVD 1x units - -8 Sep 2007 [1017] -libburn/libburn.h -Documentation of stdio-drives - -2007.09.08.164924 [1018] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -cdrskin/convert_man_to_html.sh -New option --allow_emulated_drives - -2007.09.08.174757 [1019] -libburn/libburn.h -libburn/async.c -libburn/write.c -Made Libburn_precheck_write_ruleS unconditional code - -8 Sep 2007 [1020] -cdrskin/cdrskin_eng.html -cdrskin/changelog.txt -Next cdrskin-0.3.9 cycle - ------------------------------------- cycle - cdrskin-0.3.9 - 2007.09.08.212130 -* New option --allow_emulated_drives dev=stdio: - - -2007.09.09.093535 [1021] -libburn/drive.c -libburn/libdax_msgs.h -cdrskin/cdrskin.1 -Called statvfs() for size estimation of regular stdio-files. - -2007.09.09.093637 [1022] -cdrskin/cdrskin.c -Fixed bug with dev=stdio: where path contains a digit - -2007.09.09.133136 [1023] -libburn/init.c -libburn/sg.h -libburn/sg-linux.c -libburn/sg-freebsd-port.c -libburn/sg-freebsd.c -Enabled os dependend stdio size estimation - -2007.09.09.133922 [1024] -libburn/drive.c -Made use of os dependend stdio size estimation - -2007.09.09.182827 [1026] -libburn/async.c -libburn/mmc.c -Ended falsely alleged erasability of DVD-RAM and DVD+RW - -2007.09.10.110050 [1028] -libburn/drive.c -Added forgotten return 0 to an error case - -2007.09.12.104626 [1032] -libburn/transport.h -libburn/libdax_msgs.h -libburn/write.c -libburn/drive.c -libburn/spc.c -libburn/sbc.c -libburn/mmc.c -libburn/sg-linux.c -libburn/sg-freebsd.c -Brought burn_stdio_write_track() onto sector_data() for outmost realism - -2007.09.12.115850 [1033] -libburn/mmc.c -libburn/spc.c -Reacted on compiler -O2 warnings - -2007.09.12.115946 [1034] -libburn/write.c -Implemented realistic speed simulation with stdio-drives - -2007.09.12.195206 [1039] -libburn/write.c -Implemented cache syncing for stdio-drives in burn_random_access_write() - -2007.09.12.200106 [1040] -cdrskin/cdrskin.c -Fixed bug with direct_write_amount=0 - -2007.09.14.122437 [1063] -libburn/write.c -Took into respect time granularity with stdio speed control - -2007.09.14.122531 [1064] -libburn/libburn.h -Documented burn_write_opts_set_multi @param opts - -14 Sep 2007 [1065] -src/burn_wrap.c -Changed include form of libisofs.h and libburn.h - -2007.09.15.112311 [1066] -libburn/libdax_msgs.h -libburn/libdax_msgs.c -Imported Range "vreixo" into libburn/libdax_msgs.h - -2007.09.15.171844 [1067] -libburn/libdax_msgs.h -Prepared for neat sed translation. Explained concept of libdax_msgs variants. - -15 Sep 2007 [1068] -libburn/libdax_msgs_to_xyz_msgs.sh -A sed converter which creates libiso_msgs.[ch] from libdax_msgs.[ch] - -2007.09.15.172141 [1069] -libburn/libburn.h -libburn/init.c -New API function burn_set_messenger() - -2007.09.15.204320 [1070] -libburn/libburn.h -libburn/libdax_msgs.h -libburn/libdax_msgs.c -libburn/init.c -Equipped libdax_msgs with reference counter. Completed its mutex protection. - ------------------------------------- cycle - cdrskin-0.3.9 - 2007.09.15.205752 - -16 Sep 2007 [1071] -cdrskin/changelog.txt -Next cdrskin-0.3.9 cycle - -2007.09.17.163735 [1072] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Implemented emulation for cdrecord options -inq , -format , -load - -2007.09.18.072234 [1073] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Learned helptexts for -inq, -format, -load from cdrecord (they are wrong, btw) - -2007.09.18.090713 [1074] -libburn/libburn.h -libburn/drive.c -New API function burn_drive_leave_locked() - -2007.09.18.090839 [1075] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Implemented emulation for cdrecord option -lock - -2007.09.18.130344 [1076] -libburn/mmc.c -Made use of Immed bit with 5Bh CLOSE TRACK/SESSION - -2007.09.18.200343 [1077] -libburn/mmc.c -libburn/spc.h -libburn/spc.c -libburn/sbc.c -libburn/libdax_msgs.h -Made use of Immed bit with 1Bh START STOP UNIT and 35h SYNCHRONIZE CACHE - -2007.09.18.200454 [1078] -cdrskin/cdrskin.c -Corrected an outdated HINT text - -2007.09.18.201556 [1079] -libburn/sbc.c -libburn/spc.c -Changed some comments, reacted on harmless compiler warning - -2007.09.18.204043 [1080] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Implemented emulation for cdrecord option -immed - -2007.09.19.094046 [1081] -cdrskin/cdrskin.c -Implemented emulation for cdrecord option -waiti - -19 Sep 2007 [1082] -cdrskin/cdrskin.1 -Did a little overhaul of general paragraphs, mentioned new option -waiti - - ------------------------------------- cycle - cdrskin-0.3.9 - 2007.09.19.112330 -* More cdrecord options supported: -format, -inq, -load, -lock, -immed, -waiti - -19 Sep 2007 [1083] -cdrskin/changelog.txt -cdrskin/cdrskin_eng.html -Next cdrskin-0.3.9 cycle - -2007.09.19.141650 [1084] -cdrskin/cdrskin.c -Made cdrskin/compile_cdrskin.sh -do_diet work again - -19 Sep 2007 [1085] -cdrskin/cdrskin.1 -Made minor corrections - -2007.09.19.212659 [1086] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -New option fallback_program= - -2007.09.20.125854 [1087] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Triggered fallback by unsuitable media, made -version report fallback program - -2007.09.21.120333 [1088] -libburn/sbc.c -libburn/spc.c -Had to revoke Immed bit on load command. LG GSA-4082B : premature "no media" - -2007.09.22.140613 [1096] -cdrskin/cdrskin.c -Updated list of unsupported cdrecord and wodim options - -2007.09.22.151712 [1097] -libburn/libburn.h -libburn/init.c -New API function burn_msgs_submit() - -2007.09.22.151712 [1101] -libburn/sbc.c -Reacted on compiler warning - -2007.09.23.163301 [1107] -libburn/libburn.h -libburn/drive.c -New API function burn_drive_equals_adr() - -2007.09.23.163419 [1108] -cdrskin/cdrskin.c -Made use of burn_drive_equals_adr() - -2007.09.23.163529 [1109] -libburn/sbc.c -Updated a comment about Immed and a debug message with tray loading - -2007.09.24.062354 [1110] -libburn/drive.c -Added forgotten handling of "sdtio:" with burn_drive_equals_adr() - -2007.09.24.135440 [1113] -libburn/libburn.h -libburn/transport.h -libburn/drive.h -libburn/drive.c -libburn/read.c -libburn/write.c -Implemented drive role 3, sequential write-only stdio drives (e.g. stdout) - -2007.09.24.135845 [1114] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Took into respect new drive role 3 - -2007.09.24.181340 [1115] -libburn/sg-linux.c -libburn/drive.c -Made stdio-drives work on readonly CD block devices - -24 Sep 2007 [1116] -test/libburner.c -Blocked against file descriptor drives. Too dangerous for a demo. - -2007.09.26.155301 [1123] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Disabled --allow_emulated_drives in setuid runs - -26 Sep 2007 [1124] -cdrskin/README -Streamlined and moved legal stuff to end of text - -2007.09.26.173840 [1125] -cdrskin/compile_cdrskin.sh -Made -O2 default if not -g is given - -2007.09.27.083351 [1126] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -cdrskin/convert_man_to_html.sh -cdrskin/README -Disallowed emulated drives for superuser, allowed stdio:/dev/null for all - -2007.09.27.093129 [1127] -cdrskin/cdrskin.c -Corrected announcement with dev=help about stdio: "Open via UNIX device" - - ------------------------------------- cycle - cdrskin-0.3.9 - 2007.09.27.093301 -* New option fallback_program= - - -27 Sep 2007 [1128] -cdrskin/changelog.txt -Next cdrskin-0.3.9 cycle - -28 Sep 2007 [1129] libisofs -libisofs/libiso_msgs.h -Removed apostrophes which my compiler does not like - -2007.09.29.185007 [1131] -libburn/transport.h -libburn/init.h -libburn/init.c -libburn/drive.h -libburn/drive.c -libburn/async.c -Trying to catch signals from within the writer thread - -2007.09.29.191558 [1132] -libburn/init.c -Added forgotten handling of non-writer-non-control threads - -2007.09.30.212517 [1135] -libburn/libburn.h -libburn/async.h -libburn/async.c -libburn/file.h -libburn/file.c -Implemented a simple fifo to decouple from burn_source signals - -30 Sep 2007 [1136] -test/telltoc.c -Disallowed --read_and_print raw:- , allowed to write to chardev+pipe+socket - -2007.10.02.120659 [1145] -libburn/write.c -Moved minimum tracksize padding out of TAO track closing. Now done before sync. - -2007.10.02.135538 [1146] -libburn/libburn.h -Clarified role of burn_source - -2007.10.02.180003 [1148] -libburn/write.c -Corrected error with revision 1145 - -2007.10.03.084206 [1150] -libburn/libburn.h -More documentation for burn_source - -2007.10.03.112547 [1151] -libburn/transport.h -libburn/mmc.c -libburn/write.c -libburn/drive.c -Ensured synchronize cache before release - -2007.10.03.115550 [1153] -libburn/libburn.h -More documentation for burn_source - -2007.10.03.223649 [1155] -libburn/file.h -libburn/file.c -libburn/async.c -Implemented the ring buffer of burn_fifo_source_new() object - -2007.10.03.223851 [1156] -libburn/libburn.h -More documentation for burn_source, new API call burn_fifo_inquire_status() - -3 Oct 2007 [1157] -test/libburner.c -Made use of 4 MB fifo - -2007.10.04.200221 [1158] -libburn/libburn.h -libburn/file.h -libburn/file.c -libburn/libdax_msgs.h -Inserted the necessary error messages and magic numbers - -4 Oct 2007 [1159] -test/libburner.c -Adjusted pacifier messages and change with burn_fifo_inquire_status() - -2007.10.04.210245 [1160] -libburn/libburn.h -Minor adjustments with comment text - -2007.10.04.213107 [1161] -libburn/drive.c -Corrected abort preventing bug introduced with revision 1131 - -2007.10.05.085929 [1162] -libburn/libburn.h -libburn/file.c -Revoked urge to have a magic[4] in burn_source (free_data is magic enough) - -2007.10.05.231712 [1163] -libburn/file.c -Fixed data spoiling bug with ring buffer introduced with rev 1155 - -2007.10.07.110506 [1164] -libburn/file.c -Corrected status reply for unstarted fifo - -2007.10.07.110644 [1165] -libburn/file.c -Corrected status reply for unstarted fifo (2nd try) - -7 Oct 2007 [1166] -test/libburner.c -Minor changes with waiting for drive and fifo status display - -2007.10.15.115448 [1179] -cdrskin/cdrskin.c -Corrected 4-byte buffer overflow (which did no detectable harm) - -2007.10.15.115728 [1180] -libburn/read.c -Made possible to silence error message about missing pseudo drive - -2007.10.15.115851 [1181] -libburn/drive.c -Corrected SIGSEGV with changing from one drive to the other - -2007.10.15.144050 [1182] -libburn/drive.c -Activated re-usal of disposed global drive_array slots - -2007.10.16.212205 [1189] -libburn/libburn.h -libburn/init.c -New API function burn_text_to_sev() - -18 Oct 2007 [1209] -test/telltoc.c -Calmed down hyperactive sleep interval with drive scanning - -2007.10.18.200336 [1210] -libburn/init.c -Prevented SIGSEGV with burn_msgs_obtain() on non-initialized library - -2007.10.19.115326 [1215] -libburn/async.c -libburn/libdax_msgs.h -Starting threads detached, providing two alternatives. But zombies still there. - -2007.10.19.132821 [1216] -libburn/init.c -Small change with debug verbosity of abort handler - -2007.10.19.133310 [1217] -libburn/async.c -Removed useless alternative after zombies turned out to be caused by gdb - ------------------------------------- cycle - cdrskin-0.3.9 - 2007.10.23.150436 - -2007.10.23.150436 [1240] -cdrskin/changelog.txt -Next cdrskin-0.3.9 cycle - -23 Oct 2007 [1241] -libcevap/main.c -Preparations for lowercase class and function names - -23 Oct 2007 [1242] -libcevap/libdax_model.txt -Work goes on - -23 Oct 2007 [1243] -libcevap/cgen.c -libcevap/ctyp.c -Fixed a bug about arrays - -2007.10.24.184233 [1248] branch/ZeroFourZero -Makefile.am -configure.ac -README -cdrskin/cdrskin.c -cdrskin/README -cdrskin/compile_cdrskin.sh -cdrskin/cdrskin_timestamp.h -cdrskin/wiki_plain.txt -cdrskin/cdrskin_eng.html -doc/comments -Made number transition to 0.4.0 - -25 Oct 2007 [1249] branch/ZeroFourZero -- cdrskin/add_ts_changes_to_libburn_0_3_8 -- cdrskin/add_ts_changes_to_libburn_0_3_9 -+ cdrskin/add_ts_changes_to_libburn_0_4_0 -+ cdrskin/add_ts_changes_to_libburn_0_4_1 -Updated cdrskin tarball generator - -2007.10.25.091106 [1250] -Makefile.am -configure.ac -README -cdrskin/cdrskin.c -cdrskin/README -cdrskin/compile_cdrskin.sh -cdrskin/cdrskin_timestamp.h -cdrskin/wiki_plain.txt -cdrskin/cdrskin_eng.html -doc/comments -Made number transition to 0.4.1 - -25 Oct 2007 [1251] -- cdrskin/add_ts_changes_to_libburn_0_3_8 -- cdrskin/add_ts_changes_to_libburn_0_3_9 -+ cdrskin/add_ts_changes_to_libburn_0_4_0 -+ cdrskin/add_ts_changes_to_libburn_0_4_1 -Updated cdrskin tarball generator - -25 Oct 2007 [1252] branch/ZeroFourZero -cdrskin/cdrskin.c -Added forgotten help text lines - -2007.10.25.131841 [1253] -cdrskin/cdrskin.c -Added forgotten help text lines - -2007.10.27.090421 [1254] [1256] branch/ZeroFourZero -libburn/sg-linux.c -Reacted on cdwrite@ message about INT_MAX in cdrom.h of kernel 2.6.23 - -2007.10.27.075309 [1255] -libburn/sg-linux.c -Reacted on cdwrite@ message about INT_MAX in cdrom.h of kernel 2.6.23 - -29 Oct 2007 [1272] -- cdrskin/add_ts_changes_to_libburn_0_3_9 -+ cdrskin/add_ts_changes_to_libburn_0_4_0 -Updated cdrskin release generator scripts - ------------------------------ release - cdrskin-0.4.0.pl00 - 2007.10.27.090421 -* New option direct_write_amount= -* New option --grow_overwriteable_iso -* New option --allow_emulated_drives dev=stdio: -* More cdrecord options supported: -format, -inq, -load, -lock, -immed, -waiti -* New option fallback_program= - ------------------------------------- cycle - cdrskin-0.4.1 - 2007.10.27.114207 - -2007.11.18.093952 [1307] -libburn/libburn.h -Marked loss of binary backward compatibility back in rev 655, libburn-0.3.1 - -18 Nov 2007 [1308] -cdrskin/cdrskin.1 -Corrected a typo in cdrskin man page - -2007.11.18.094209 [1309] -cdrskin/cdrskin.c -Reacted on build warnings on a 64 Bit system - -2007.11.26.154817 [1310] -libburn/libdax_audioxtr.c -Reacted on build warnings on another system - ------------------------------------- cycle - cdrskin-0.4.1 - 2007.11.27.214003 - -2007.11.29.185342 [1312] -libburn/drive.c -libburn/mmc.c -libburn/spc.c -libburn/libdax_msgs.h -Enabled reading of TOC from ROM drives (direly needed for xorriso) - -29 Nov 2007 [1313] -test/telltoc.c -Adjusted meaning of --read_and_print count= -1 - -2007.12.07.185030 [1323] -configure.ac -An attempt to rectify .so numbering: SONAME=10, REV=1, AGE=6 - -2007.12.07.185206 [1324] -libburn/async.c -Made postponed change in thread management - -8 Dec 2007 [1325] -configure.ac -Some changes in the comments - -24 Dec 2008 [1338] -libburn/libburn.h -libburn/source.h -libburn/source.c -libburn/file.c -libburn/write.c -libburn/sector.c -Implemented burn_source.cancel() in a binary backwards compatible way - -2008.01.17.185051 [1383] -libburn/libdax_msgs.h -libburn/libdax_msgs.c -Changed meaning of .driveno to .origin, introduced LIBDAX_MSGS_ORIGIN_* macros - -17 Jan 2008 [1384] -cdrskin/README -Removed a reference to future GPL versions - -2008.01.19.201702 [1396] -libburn/read.c -Fixed small bug about error messages with burn_read_data - -2008.01.23.193345 [1405] -libburn/read.c -Made burn_read_data() issue messages about hopeless drive access errors - -2008.01.23.193843 [1406] -libburn/libburn.h -libburn/libdax_msgs.h -libburn/libdax_msgs.c -Introduced message severity "FAILURE" - -2008.01.23.211731 [1408] -cdrskin/cdrskin.c -configure.ac -Implemented run time check of libburn version. - -2008.01.23.213607 [1409] -Makefile.am -Dynamic cdrskin linking patch by Simon Huggins. - -26 Jan 2008 [1420] -cdrskin/convert_man_to_html.sh -Adapted to man -H on my new system - -2008.01.26.123054 [1421] -libburn/libdax_msgs.h -Ported change in vreixo message range from isoburn_msgs - -2008.01.26.131519 [1422] -libburn/drive.c -Made a sudden end to all stdio drives in burn_abort() - -2008.01.26.180241 [1426] [branch 1427] -libburn/async.c -Disabled debugging messages about thread properties - -2008.01.26.200001 [branch 1428] -Makefile.am -configure.ac -libburn-5.pc.in -README -cdrskin/cdrskin.c -cdrskin/README -cdrskin/compile_cdrskin.sh -cdrskin/cdrskin_timestamp.h -cdrskin/wiki_plain.txt -cdrskin/cdrskin_eng.html -Made number transition to 0.4.2 , libburn.so.4.7.0 - -27 Jan [branch 1429] -cdrskin/cdrskin.c -cdrskin/cdrskin_eng.html -cdrskin/changelog.txt -Adjustments after first round of testing - -27 Jan [branch 1430] -cdrskin/README -cdrskin/cdrskin_eng.html -Adjustments after testing - -2008.01.27.143022 [1431] -Makefile.am -configure.ac -libburn-5.pc.in -README -cdrskin/cdrskin.c -cdrskin/README -cdrskin/compile_cdrskin.sh -cdrskin/cdrskin_timestamp.h -cdrskin/wiki_plain.txt -cdrskin/cdrskin_eng.html -cdrskin/changelog.txt -Made number transition to 0.4.3 , still libburn.so.4.7.0 - -27 Jan 2008 [branch 1433] [1432] -- cdrskin/add_ts_changes_to_libburn_0_4_0 -- cdrskin/add_ts_changes_to_libburn_0_4_1 -+ cdrskin/add_ts_changes_to_libburn_0_4_2 -+ cdrskin/add_ts_changes_to_libburn_0_4_3 -Updated cdrskin tarball generator - -2008.01.29.210821 [1442] -configure.ac -libburn/libburn.h -Moving the major.minor.micro definition from configure.ac to libburn.h - -2008.01.28.213001 [branch 1444] -libburn/libburn.h -Introduced copy of major.minor.micro definition in libburn.h of version 0.4.2 - -29 Jan 2008 [branch 1445] [branch 1447] -Corrected description of major.minor.micro definition in libburn.h of version 0.4.2 - -2008.01.29.214110 [1446] -libburn/libburn.h -Corrected description of major.minor.micro definition in libburn.h - -2008.01.31.111057 [1448] -cdrskin/cdrskin.c -Introduced compile time check of libburn header version - -2008.02.01.100302 [1451] [branch 1453] -- libburn-5.pc.in -+ libburn-1.pc.in -configure.ac -Makefile.am -Renamed libburn-5.pc to libburn-1.pc - -2008.02.01.100530 [1452] -cdrskin/cdrskin.c -Changed "libburn interface :" version message to libburn.h macros - - [branch ] -cdrskin/cdrskin_timestamp.h -cdrskin/changelog.txt -Updated changelog before release - ------------------------------ release - cdrskin-0.4.2.pl00 - 2008.02.01.100001 -* Safe dynamic linking possible with libburn.so.4 - ------------------------------------- cycle - cdrskin-0.4.3 - 2008.02.01.225039 - -2008.02.03.092013 [1463] -libburn/libdax_msgs.h -Registered error code range "libisofs-xorriso" - -2008.02.03.092134 [1464] -configure.ac -Incremented LT_* to get libburn.so.4.8.0 (forgot to do 4.7.1 anyway) - -2008.02.03.092509 [1465] -libburn/libburn.h -libburn/init.c -New API call burn_sev_to_text() - -4 Feb 2008 [1473] -README -Announced deprecation of libisofs-0.2.x, temporory employment of libisofs-0.6.1 - -2008.02.04.175209 [1474] -libburn/libdax_msgs.h -Registered range "libisoburn" 0x00060000 to 0x00006ffff - -2008.02.06.174009 [1482] -libburn/libdax_msgs.h -Re-instated range "vreixo" with old and new codes, adjusted severity definitions - -2008.02.06.182222 [1483] -libburn/libburn.h -Copied usage discussion about *_header_version_* from libisoburn - -2008.02.06.230041 [1488] -libburn/read.c -Installed a simple address logger in burn_read_data - -2008.02.07.232820 [1492] -libburn/read.c -Added debug message in case of burn_read_data() return 0 - -2008.02.08.073414 [1493] -libburn/mmc.c -Allowed DVD +/- DL for reading - -2008.02.11.190802 [1518] -libburn/libdax_msgs.h -libburn/libdax_msgs.c -Introduced LIBDAX_MSGS_SEV_MISHAP - -2008.02.14.074108 [1522] -libburn/libburn.h -Micro corrections in comment text - -14 Feb 2008 [1523] -COPYRIGHT -Updated year - -14 Feb 2008 [1524] -cdrskin/README -Pointed to ldconfig - -2008.02.16.121102 [1541] -configure.ac -Corrected typo in comment - -16 Feb 2008 [1542] -doc/comments -README -cdrskin/wiki_plain.txt -Updated project interrelations - -2008.02.21.200956 [1554] -libburn/sg-linux.c -Testwise inquiry of ioctl(CDROM_MEDIA_CHANGED) (disabled by default) - -21 Feb 2008 [1555] -test/libburner.c -Directed error message to proper output channel - -2008.02.21.201238 [1556] -libburn/libdax_msgs.h -libburn/libdax_msgs.c -Introduced severity ERRFILE - -2008.02.21.202216 [1557] -libburn/libdax_msgs.c -Mapped unknown severity text to ALL rather than NEVER - -2008.02.21.215250 [1560] -libburn/libdax_msgs.h -Weakened demand to print file path in following message - -2008.02.22.150939 [1562] -libburn/libdax_msgs.h -libburn/init.c -New error code 0x00040008 - -2008.02.22.213527 [1563] -libburn/libdax_msgs.h -libburn/libdax_msgs.c -Imported changes from libiso_msgs.h - -2008.02.22.213726 [1564] -libburn/init.c -Changed meaning of unrecognized severity texts from FATAL to ALL - -2008.02.28.123152 [1565] -libburn/libburn.h -libburn/spc.c -libburn/mmc.c -libburn/write.c -cdrskin/cdrskin.1 -Made support for DVD+R DL official, enabled untested support for BD-RE - -2008.02.28.132325 [1586] -libburn/mmc.c -cdrskin/README -cdrskin/cdrskin.c -cdrskin/cdrskin_eng.html -cdrskin/wiki_plain.txt -test/libburner.c -Mentioned support for DVD+R/DL. - ------------------------------------- cycle - cdrskin-0.4.3 - 2008.03.01.154319 -* Support for DVD+R/DL media is now official -* Experimental code for BD-RE with --allow_untested_media - -1 Mar 2008 [1595] -cdrskin/changelog.txt -Updated changelog - -2008.03.03.202930 [1598] -libburn/libburn.h -libburn/drive.c -libburn/read.c -Got rid of a cumbersome open-close cycle with burn_read_data() on stdio: - -2 Apr 2008 [1654] -COPYRIGHT -Corrected GPL version - ------------------------------------- cycle - cdrskin-0.4.3 - 2008.04.07.152331 -* libburn: Improved read performance from stdio: pseudo-drives - -2008.04.08.100001 [ZeroFourFour 1669] -Makefile.am -configure.ac -README -libburn/libburn.h (burn_header_version_*) -cdrskin/cdrskin.c -cdrskin/README -cdrskin/compile_cdrskin.sh -cdrskin/cdrskin_timestamp.h -cdrskin/wiki_plain.txt -cdrskin/cdrskin_eng.html -doc/comments -Made number transition and activated development documentation - -8 Apr 2008 [ZeroFourFour 1670] -- cdrskin/add_ts_changes_to_libburn_0_4_2 -- cdrskin/add_ts_changes_to_libburn_0_4_3 -+ cdrskin/add_ts_changes_to_libburn_0_4_4 -+ cdrskin/add_ts_changes_to_libburn_0_4_5 -Updated cdrskin tarball generator - -8 Apr 2008 [ZeroFourFour 1671] -cdrskin/changelog.txt -Documented changes and release timestamp - -2008.04.08.100001 [ZeroFourFour 1672] -libburn/util.c -Switched from configure.ac versioning to libburn.h versioning - -8 Apr 2008 [ZeroFourFour 1673] -cdrskin/changelog.txt -Documented last minute changes - ------------------------------ release - cdrskin-0.4.4.pl00 - 2008.04.08.100001 -* Support for DVD+R/DL media is now official -* Experimental code for BD-RE with --allow_untested_media -* libburn: Improved read performance from stdio: pseudo-drives - - -2008.04.08.132344 [1674] -Makefile.am -configure.ac -README -libburn/libburn.h (burn_header_version_*) -cdrskin/cdrskin.c -cdrskin/README -cdrskin/compile_cdrskin.sh -cdrskin/cdrskin_timestamp.h -cdrskin/wiki_plain.txt -cdrskin/cdrskin_eng.html -doc/comments -cdrskin/changelog.txt -Made number transition - -8 Apr 2008 [1675] -- cdrskin/add_ts_changes_to_libburn_0_4_2 -- cdrskin/add_ts_changes_to_libburn_0_4_3 -+ cdrskin/add_ts_changes_to_libburn_0_4_4 -+ cdrskin/add_ts_changes_to_libburn_0_4_5 -Updated cdrskin tarball generator - -2008.04.08.133452 [1676] -libburn/util.c -Switched from configure.ac versioning to libburn.h versioning - ------------------------------------- cycle - cdrskin-0.4.5 - 2008.04.08.134413 - -2008.04.10.211529 [1681] -libburn/mmc.c -libburn/drive.c -cdrskin/cdrskin.c -Trying to fix bugs about BD-RE, macro for simulating BD-RE on DVD-RAM - - ------------------------------------- cycle - cdrskin-0.4.5 - 2008.04.10.211529 - -2008.04.12.164244 [1683] -libburn/libburn.h -libburn/transport.h -libburn/options.h -libburn/options.c -libburn/write.c -libburn/drive.c -libburn/mmc.c -New API call burn_write_opts_set_stream_recording() - -2008.04.12.164606 [1684] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -cdrskin/cdrskin_eng.html -New option stream_recording=on|off - ------------------------------------- cycle - cdrskin-0.4.5 - 2008.04.12.164930 -* New option stream_recording=on can speed up DVD-RAM - - -2008.04.15.094133 [1685] -libburn/os-linux.h -libburn/write.c -Enforced tail padding with stream_recording, enlarged transport buffer - -15 Apr 2008 [1686] -cdrskin/cdrskin.1 -Some adjustments of cdrskin man page - ------------------------------------- cycle - cdrskin-0.4.5 - 2008.04.15.094545 - -2008.04.16.082208 [1687] -libburn/read.c -Made burn_read_data() obey its flag bit1 - -2008.04.18.092715 [1688] -libburn/libburn.h -libburn/async.c -libburn/drive.c -libburn/mmc.c -Began to implement formatting of DVD-RAM and experimentally of BD-RE - -2008.04.18.092816 [1689] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Began to implement formatting of DVD-RAM and experimentally of BD-RE - -2008.04.18.194602 [1691] -libburn/mmc.c -Adjustments with DVD-RAM formatting - -2008.04.22.161139 [1695] -libburn/libburn.h -libburn/transport.h -libburn/mmc.c -libburn/drive.c -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Adjustments with DVD-RAM formatting - -2008.04.22.200949 [1696] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -New option --list_formats - -2008.04.23.110116 [1697] -libburn/mmc.c -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -New blank type blank=format_by_index_ - -24 Apr 2008 [1698] -doc/cookbook.txt -Wrote down what was learned about DVD-RAM formatting - -24 Apr 2008 [1699] -cdrskin/cdrskin_eng.html -Mentioned new features - -2008.04.25.131531 [1700] -libburn/mmc.c -Preparations for formatting BD-RE - -2008.04.25.132353 [1701] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -Documented experimental support for BD-RE formatting - -25 Apr 2008 [1702] -configure.ac -Incremented LT_CURRENT and LT_AGE to reflect API enhancements - -25 Apr 2008 [1703] -cdrskin/cdrskin_eng.html -Documented newest enhancements - ------------------------------------- cycle - cdrskin-0.4.5 - 2008.04.25.134438 -* New blank type blank=format_defectmgt for DVD-RAM -* New option --list_formats -* New blank type blank=format_by_index_ -* Experimental support for formatting BD-RE - - -2008.04.26.150646 [1704] -libburn/libburn.h -libburn/mmc.c -libburn/drive.c -doc/cookbook.txt -Enabled quick formatting with DVD-RAM, made slow formatting default with BD-RE - -2008.04.26.150945 [1705] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -New blank subtypes format_defectmgt_cert_[on|off], on is default - -2008.04.27.084704 [1706] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -New blank type format_if_needed - -2008.04.27.140144 [1707] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -New blank type as_needed - -27 Apr 2008 [1708] -cdrskin/cdrskin_eng.html -Documented newest enhancements - ------------------------------------- cycle - cdrskin-0.4.5 - 2008.04.27.163625 -* New blank type blank=as_needed for automatic handling of media type and state - - -3 May 2008 [1723] -README -Updated project history - -2008.05.06.082429 [1729] -libburn/drive.c -Avoided to report negative burn_multi_caps.start_range_high with DVD-RW - -2008.05.06.084156 [1730] -libburn/mmc.c -Mapped undefined size to 0 with burn_disc_get_formats() and DVD-RW - -2008.05.06.180813 [1733] -libburn/libburn.h -libburn/drive.c -libburn/mmc.c -doc/cookbook.txt -doc/comments -test/libburner.c -Declared BD-RE to be supported - -2008.05.06.181100 [1734] -cdrskin/cdrskin.c -cdrskin/cdrskin.1 -cdrskin/wiki_plain.txt -Declared BD-RE to be supported - -2008.05.06.181723 [1735] -libburn/mmc.c -Declared BD-RE to be supported - -6 May 2008 [1736] -cdrskin/cdrskin_eng.html -cdrskin/cdrskin.1 -Declared BD-RE to be supported - ------------------------------------- cycle - cdrskin-0.4.5 - 2008.05.06.183436 -* Support for BD-RE media is now official - -2008.05.09.143130 [1748] -libburn/libburn.h -Documented read-only profiles CD-ROM and DVD-ROM - -2008.05.09.145205 [1749] -libburn/mmc.c -Allowed BD-ROM and BD-R for read-only purposes - -9 May 2008 [1750] -cdrskin/cdrskin.1 -Changed blank examples to blank=as_needed - - ------------------------------------- cycle - cdrskin-0.4.5 - 2008.05.09.151327 - -2008.05.10.080001 [1754] -Makefile.am -configure.ac -README -libburn/libburn.h (burn_header_version_*) -cdrskin/cdrskin.c -cdrskin/README -cdrskin/compile_cdrskin.sh -cdrskin/cdrskin_timestamp.h -cdrskin/wiki_plain.txt -cdrskin/cdrskin_eng.html -doc/comments -cdrskin/cdrskin.1 -Made number transition to 0.4.6 and activated development documentation - -10 May 2008 [1755] -cdrskin/README -Made number transition to 0.4.6 and activated development documentation - -10 May 2008 [1756] -- cdrskin/add_ts_changes_to_libburn_0_4_4 -- cdrskin/add_ts_changes_to_libburn_0_4_5 -+ cdrskin/add_ts_changes_to_libburn_0_4_6 -+ cdrskin/add_ts_changes_to_libburn_0_4_7 -Updated cdrskin tarball generator - -10 May 2008 [] -cdrskin/changelog.txt -Documented changes and release timestamp - - ------------------------------ release - cdrskin-0.4.6.pl00 - 2008.05.10.080001 -* Support for BD-RE media is now official -* New option stream_recording=on can speed up DVD-RAM and BD-RE -* New option --list_formats -* New blank types for expert formatting of DVD-RAM and BD-RE -* New blank type blank=as_needed for automatic handling of media type and state - - ------------------------------------- cycle - cdrskin-0.4.7 - ------------------------------------- cycle - cdrskin-0.4.7 - - -=============================================================================== - TODO -=============================================================================== - - ---------------------------------- bugs ------------------------------------- - - -- Why are DVD+R tracks labeled "invisible" by dvd+rw-mediainfo ? - Why does the DVD drive only show the first session ? -READ TRACK INFORMATION[#5]: - Track State: invisible - Track Start Address: 954960*2KB - Free Blocks: 0*2KB - Track Size: 22784*2KB - ROM Compatibility LBA: 265696 - - ------------------------------- end of bugs --------------------------------- - -@since tags - -Check all SORRY and FATAL errors whether they should become FAILUREs - -problem with telltoc: double descriptor list from before load and after load - - -What about cdrskin rc files ? Forward with fallback runs ? - -cdrskin/README -Thin out - - - [] -Emulate -dummy on overwriteables ? - - [] -Emulate -dummy on DVD+R ? - - - -What about minimum track sizes ? (POWER OFF/ON , BUS RESET ?) - - -After cooking: review of -do_diet ? - -growisofs.c : _LINUX_CAPABILITY_VERSION CAP_SYS_RAWIO SYS_capset ? - - -Rectify mmc_read_atip speed interpretation. 12x media are reported as 10x. I never heard of 6x media. - - ------------------------------------------ long term intentions: - - [] --reset: ioctl(fd,CDROMRESET) ioctl(fd,SG_SCSI_RESET,SG_SCSI_RESET_DEVICE) -http://developer.osdl.org/dev/robustmutexes/src/fusyn.hg/Documentation/ioctl/cdrom.txt - - - [] -Convert burn_print() into libdax_msgs_submit() - - [] -Test unlocking of all drives by burn_drive_info_free() -Test unlocking of single drive by burn_drive_grab(), burn_drive_release() - - [] -Clear outdated persistent read buffer after small CD image was read (ticket 57) - - -=============================================================================== - This is the dirty end of the todo list. - The recent changelog entries are above the headline "TODO". -=============================================================================== diff --git a/cdrskin/cleanup.c b/cdrskin/cleanup.c deleted file mode 100644 index fc92383..0000000 --- a/cdrskin/cleanup.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - cleanup.c , Copyright 2006 Thomas Schmitt - - A signal handler which cleans up an application and exits. - - Provided under GPL license within GPL projects, BSD license elsewise. -*/ - -/* - cc -g -o cleanup -DCleanup_standalonE cleanup.c -*/ - -#include -#include -#include -#include -#include -#include - -#include -typedef void (*sighandler_t)(int); - - -#include "cleanup.h" - - -#ifndef Cleanup_has_no_libburn_os_H - - -#include "../libburn/os.h" - -/* see os.h for name of particular os-*.h where this is defined */ -static int signal_list[]= { BURN_OS_SIGNAL_MACRO_LIST , -1}; -static char *signal_name_list[]= { BURN_OS_SIGNAL_NAME_LIST , "@"}; -static int signal_list_count= BURN_OS_SIGNAL_COUNT; -static int non_signal_list[]= { BURN_OS_NON_SIGNAL_MACRO_LIST, -1}; -static int non_signal_list_count= BURN_OS_NON_SIGNAL_COUNT; - - -#else /* ! Cleanup_has_no_libburn_os_H */ - - -/* Outdated. Linux only. For backward compatibility with pre-libburn-0.2.3 */ - -/* Signals to be caught */ -static int signal_list[]= { - SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, - SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, - SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN, - SIGTTOU, - SIGBUS, SIGPOLL, SIGPROF, SIGSYS, SIGTRAP, - SIGVTALRM, SIGXCPU, SIGXFSZ, -1 -}; -static char *signal_name_list[]= { - "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT", - "SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM", - "SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN", - "SIGTTOU", - "SIGBUS", "SIGPOLL", "SIGPROF", "SIGSYS", "SIGTRAP", - "SIGVTALRM", "SIGXCPU", "SIGXFSZ", "@" -}; -static int signal_list_count= 24; - -/* Signals not to be caught */ -static int non_signal_list[]= { - SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH, -1 -}; -static int non_signal_list_count= 5; - - -#endif /* Cleanup_has_no_libburn_os_H */ - - - -/* run time dynamic part */ -static char cleanup_msg[4096]= {""}; -static int cleanup_exiting= 0; -static int cleanup_has_reported= -1234567890; - -static void *cleanup_app_handle= NULL; -static Cleanup_app_handler_T cleanup_app_handler= NULL; -static int cleanup_perform_app_handler_first= 0; - - -static int Cleanup_handler_exit(int exit_value, int signum, int flag) -{ - int ret; - - if(cleanup_msg[0]!=0 && cleanup_has_reported!=signum) { - fprintf(stderr,"\n%s\n",cleanup_msg); - cleanup_has_reported= signum; - } - if(cleanup_perform_app_handler_first) - if(cleanup_app_handler!=NULL) { - ret= (*cleanup_app_handler)(cleanup_app_handle,signum,0); - if(ret==2 || ret==-2) - return(2); - } - if(cleanup_exiting) { - fprintf(stderr,"cleanup: ABORT : repeat by pid=%d, signum=%d\n", - getpid(),signum); - return(0); - } - cleanup_exiting= 1; - alarm(0); - if(!cleanup_perform_app_handler_first) - if(cleanup_app_handler!=NULL) { - ret= (*cleanup_app_handler)(cleanup_app_handle,signum,0); - if(ret==2 || ret==-2) - return(2); - } - exit(exit_value); -} - - -static void Cleanup_handler_generic(int signum) -{ - int i; - - sprintf(cleanup_msg,"UNIX-SIGNAL caught: %d errno= %d",signum,errno); - for(i= 0; imax_sig) - max_sig= signal_list[i]; - if(signal_list[i]=non_signal_list_count) { - if(i==SIGABRT && (flag&8)) - signal(i,Cleanup_handler_generic); - else - signal(i,sig_handler); - } - } - return(1); -} - - -#ifdef Cleanup_standalonE - -struct Demo_apP { - char *msg; -}; - - -int Demo_app_handler(struct Demo_apP *demoapp, int signum, int flag) -{ - printf("Handling exit of demo application on signal %d. msg=\"%s\"\n", - signum,demoapp->msg); - return(1); -} - - -main() -{ - struct Demo_apP demoapp; - - demoapp.msg= "Good Bye"; - Cleanup_set_handlers(&demoapp,(Cleanup_app_handler_T) Demo_app_handler,0); - - if(1) { /* change to 0 in order to wait for external signals */ - char *cpt= NULL,c; - printf("Intentionally provoking SIGSEGV ...\n"); - c= *cpt; - } else { - printf("killme: %d\n",getpid()); - sleep(3600); - } - - Cleanup_set_handlers(NULL,NULL,1); - exit(0); -} - -#endif /* Cleanup_standalonE */ diff --git a/cdrskin/cleanup.h b/cdrskin/cleanup.h deleted file mode 100644 index a9d3551..0000000 --- a/cdrskin/cleanup.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - cleanup.c , Copyright 2006 Thomas Schmitt - - A signal handler which cleans up an application and exits. - - Provided under GPL license within GPL projects, BSD license elsewise. -*/ - -#ifndef Cleanup_includeD -#define Cleanup_includeD 1 - - -/** Layout of an application provided cleanup function using an application - provided handle as first argument and the signal number as second - argument. The third argument is a flag bit field with no defined bits yet. - If the handler returns 2 or -2 then it has delegated exit() to some other - instance and the Cleanup handler shall return rather than exit. -*/ -typedef int (*Cleanup_app_handler_T)(void *, int, int); - - -/** Establish exiting signal handlers on (hopefully) all signals that are - not ignored by default or non-catchable. - @param handle Opaque object which knows how to cleanup application - @param handler Function which uses handle to perform application cleanup - @param flag Control Bitfield - bit0= reset to default signal handling -*/ -int Cleanup_set_handlers(void *handle, Cleanup_app_handler_T handler, - int flag); - - -#endif /* ! Cleanup_includeD */ - diff --git a/cdrskin/compile_cdrskin.sh b/cdrskin/compile_cdrskin.sh deleted file mode 100755 index c6623a0..0000000 --- a/cdrskin/compile_cdrskin.sh +++ /dev/null @@ -1,216 +0,0 @@ -#!/bin/sh - -# compile_cdrskin.sh -# Copyright 2005 - 2008 Thomas Schmitt, scdbackup@gmx.net, GPL version 2 -# to be executed within ./libburn-* resp ./cdrskin-* - -debug_opts="-O2" -def_opts= -largefile_opts="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1" -libvers="-DCdrskin_libburn_0_4_6" -cleanup_src_or_obj="libburn/cleanup.o" -libdax_msgs_o="libburn/libdax_msgs.o" -libdax_audioxtr_o="libburn/libdax_audioxtr.o" -do_strip=0 -static_opts= -warn_opts="-Wall" -fifo_source="cdrskin/cdrfifo.c" -compile_cdrskin=1 -compile_cdrfifo=0 -compile_dewav=0 - -for i in "$@" -do - if test "$i" = "-compile_cdrfifo" - then - compile_cdrfifo=1 - elif test "$i" = "-compile_dewav" - then - compile_dewav=1 - elif test "$i" = "-cvs_A60220" - then - libvers="-DCdrskin_libburn_cvs_A60220_tS" - libdax_audioxtr_o= - libdax_msgs_o="libburn/message.o" - cleanup_src_or_obj="-DCleanup_has_no_libburn_os_H cdrskin/cleanup.c" - elif test "$i" = "-libburn_0_4_6" - then - libvers="-DCdrskin_libburn_0_4_6" - 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_4_7" - libdax_audioxtr_o="libburn/libdax_audioxtr.o" - libdax_msgs_o="libburn/libdax_msgs.o" - cleanup_src_or_obj="libburn/cleanup.o" - elif test "$i" = "-newapi" -o "$i" = "-experimental" - then - def_opts="$def_opts -DCdrskin_new_api_tesT" - elif test "$i" = "-oldfashioned" - then - def_opts="$def_opts -DCdrskin_oldfashioned_api_usE" - cleanup_src_or_obj="-DCleanup_has_no_libburn_os_H cdrskin/cleanup.c" - elif test "$i" = "-no_largefile" - then - largefile_opts= - elif test "$i" = "-do_not_compile_cdrskin" - then - compile_cdrskin=0 - elif test "$i" = "-do_diet" - then - fifo_source= - def_opts="$def_opts -DCdrskin_extra_leaN" - warn_opts= - elif test "$i" = "-do_strip" - then - do_strip=1 - elif test "$i" = "-g" - then - debug_opts="-g" - elif test "$i" = "-help" -o "$i" = "--help" -o "$i" = "-h" - then - echo "cdrskin/compile_cdrskin.sh : to be executed within top level directory" - echo "Options:" - 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_4_6 set macro to match libburn-0.4.6." - 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." - echo " -experimental use newly introduced libburn features." - echo " -oldfashioned use pre-0.2.2 libburn features only." - echo " -do_diet produce capability reduced lean version." - echo " -do_strip apply program strip to compiled programs." - echo " -g produce debuggable programm." - echo " -static compile with cc option -static." - exit 0 - elif test "$i" = "-static" - then - static_opts="-static" - fi -done - - -timestamp="$(date -u '+%Y.%m.%d.%H%M%S')" -echo "Version timestamp : $(sed -e 's/#define Cdrskin_timestamP "//' -e 's/"$//' cdrskin/cdrskin_timestamp.h)" -echo "Build timestamp : $timestamp" - -if test "$compile_cdrskin" -then - echo "compiling program cdrskin/cdrskin.c $static_opts $debug_opts $libvers $def_opts $cleanup_src_or_obj" - cc -I. \ - $warn_opts \ - $static_opts \ - $debug_opts \ - $libvers \ - $largefile_opts \ - $def_opts \ - \ - -DCdrskin_build_timestamP='"'"$timestamp"'"' \ - \ - -o cdrskin/cdrskin \ - \ - cdrskin/cdrskin.c \ - $fifo_source \ - \ - $cleanup_src_or_obj \ - \ - libburn/async.o \ - libburn/debug.o \ - libburn/drive.o \ - libburn/file.o \ - libburn/init.o \ - libburn/options.o \ - libburn/source.o \ - libburn/structure.o \ - \ - libburn/sg.o \ - libburn/write.o \ - libburn/read.o \ - $libdax_audioxtr_o \ - $libdax_msgs_o \ - \ - libburn/mmc.o \ - libburn/sbc.o \ - libburn/spc.o \ - libburn/util.o \ - \ - libburn/sector.o \ - libburn/toc.o \ - \ - libburn/crc.o \ - libburn/lec.o \ - \ - -lpthread - - ret=$? - if test "$ret" = 0 - then - dummy=dummy - else - echo >&2 - echo "+++ FATAL : Compilation of cdrskin failed" >&2 - echo >&2 - exit 1 - fi -fi - -if test "$compile_cdrfifo" = 1 -then - echo "compiling program cdrskin/cdrfifo.c $static_opts $debug_opts" - cc $static_opts $debug_opts \ - -DCdrfifo_standalonE \ - -o cdrskin/cdrfifo \ - cdrskin/cdrfifo.c - - ret=$? - if test "$ret" = 0 - then - dummy=dummy - else - echo >&2 - echo "+++ FATAL : Compilation of cdrfifo failed" >&2 - echo >&2 - exit 2 - fi -fi - -if test "$compile_dewav" = 1 -then - echo "compiling program test/dewav.c -DDewav_without_libburN $static_opts $debug_opts" - cc $static_opts $debug_opts \ - -DDewav_without_libburN \ - -o test/dewav \ - test/dewav.c \ - libburn/libdax_audioxtr.o \ - libburn/libdax_msgs.o \ - \ - -lpthread - - ret=$? - if test "$ret" = 0 - then - dummy=dummy - else - echo >&2 - echo "+++ FATAL : Compilation of test/dewav failed" >&2 - echo >&2 - exit 2 - fi -fi - -if test "$do_strip" = 1 -then - echo "stripping result cdrskin/cdrskin" - strip cdrskin/cdrskin - if test "$compile_cdrfifo" = 1 - then - echo "stripping result cdrskin/cdrfifo" - strip cdrskin/cdrfifo - fi -fi - -echo 'done.' diff --git a/cdrskin/convert_man_to_html.sh b/cdrskin/convert_man_to_html.sh deleted file mode 100755 index 912b46a..0000000 --- a/cdrskin/convert_man_to_html.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/sh - -# -# convert_man_to_html.sh - ts A61214 -# -# Generates a HTML version of man page cdrskin.1 -# -# To be executed within the libburn toplevel directory (like ./libburn-0.2.7) -# - -# set -x - -man_dir=$(pwd)"/cdrskin" -export MANPATH="$man_dir" -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 -then - dummy=dummy -else - echo "Cannot find readable man page source $1" >&2 - exit 1 -fi - -if test -e "$man_dir"/man1 -then - dummy=dummy -else - ln -s . "$man_dir"/man1 -fi - -if test "$1" = "-work_as_filter" -then - -# set -x - - sed \ - -e 's///' \ - -e 's///' \ - -e 's/CDRSKIN<\/title>/<title>man 1 cdrskin<\/title>/' \ - -e 's/<h1 align=center>CDRSKIN<\/h1>/<h1 align=center>man 1 cdrskin<\/h1>/' \ - -e 's/<body>/<body BGCOLOR="#F5DEB3" TEXT=#000000 LINK=#0000A0 VLINK=#800000>/' \ - -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/<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/<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/^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/See section EXAMPLES/See section <A HREF="#EXAMPLES">EXAMPLES<\/A>/' \ - <"$2" >"$htmlpage" - - set +x - - chmod u+rw,go+r,go-w "$htmlpage" - echo "Emerged file:" - ls -lL "$htmlpage" - -else - - export BROWSER='cp "%s" '"$raw_html" - man -H "$manpage" - "$0" -work_as_filter "$raw_html" - rm "$raw_html" - rm "$man_dir"/man1 - -fi diff --git a/cdrskin/doener_150x200_tr.png b/cdrskin/doener_150x200_tr.png deleted file mode 100644 index bffad01..0000000 Binary files a/cdrskin/doener_150x200_tr.png and /dev/null differ diff --git a/cdrskin/doener_150x200_tr_octx.png b/cdrskin/doener_150x200_tr_octx.png deleted file mode 100644 index 7f8e983..0000000 Binary files a/cdrskin/doener_150x200_tr_octx.png and /dev/null differ diff --git a/cdrskin/make_timestamp.sh b/cdrskin/make_timestamp.sh deleted file mode 100755 index 957a2c4..0000000 --- a/cdrskin/make_timestamp.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -# Create version timestamp cdrskin/cdrskin_timestamp.h -# to be executed within ./libburn-* resp ./cdrskin-* - -timestamp="$(date -u '+%Y.%m.%d.%H%M%S')" -echo "Version timestamp : $timestamp" -echo '#define Cdrskin_timestamP "'"$timestamp"'"' >cdrskin/cdrskin_timestamp.h - diff --git a/cdrskin/wiki_plain.txt b/cdrskin/wiki_plain.txt deleted file mode 100644 index 567cb65..0000000 --- a/cdrskin/wiki_plain.txt +++ /dev/null @@ -1,318 +0,0 @@ --------------------------------------------------------------------------- - cdrskin Wiki - plain text copy --------------------------------------------------------------------------- -[[Image(source:/libburn/trunk/cdrskin/doener_150x200_tr.png)]] [http://en.wikipedia.org/wiki/D%C3%B6ner_kebab Doener] - -'''cdrskin is the cdrecord compatibility middleware of libburn.''' - -Its paragon, cdrecord, is a powerful GPL'ed burn program included in Joerg -Schilling's cdrtools. cdrskin strives to be a second source for the services -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 -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]. - -About libburn API for burning CD and DVD: http://api.libburnia-project.org - --------------------------------------------------------------------------- - -For yet unsupported media types see the advice to use dvd+rw-tools at -the end of this text. - --------------------------------------------------------------------------- - -About the command line options of cdrskin: - -They are described in detail in [http://scdbackup.sourceforge.net/man_1_cdrskin_devel.html#OPTIONS section OPTIONS] of -[http://scdbackup.sourceforge.net/man_1_cdrskin_devel.html man cdrskin] - -There are two families of options: cdrecord-compatible ones and options -which are specific to cdrskin. The latter are mostly used to configure -cdrskin for its task to emulate cdrecord. There are some, nevertheless, -which provide rather exotic unique features of cdrskin. - -The cdrecord-compatible options are listed in the output of -{{{ -cdrskin -help -}}} -where the option "help" has *one* dash. Online: [http://scdbackup.sourceforge.net/cdrskin_help_devel cdrskin -help] - -For these options you may expect program behavior that is roughly the -same as described in original man cdrecord . - -Online: http://cdrecord.berlios.de/old/private/man/cdrecord-2.0.html - -The cdrskin-specific options are listed by -{{{ -cdrskin --help -}}} -where the option "help" has *two* dashes. Online: [http://scdbackup.sourceforge.net/cdrskin__help_devel cdrskin --help] - -Some are very experimental and should only be -used in coordination with the libburnia developer team. -Some are of general user interest, though: - --------------------------------------------------------------------------- - ---devices allows the sysadmin to scan the system for possible drives -and displays their detected properties. -The drives are listed one per line, with fields: -libburn-drive-number, sysadmin-device-file, permissions, vendor, type -{{{ -0 dev='/dev/sr0' rwrw-- : 'HL-DT-ST' 'DVDRAM GSA-4082B' -}}} -This feature is valuable since cdrskin -scanbus will not give you -the device file name and its current permissions. -cdrskin will accept of course the proposed dev= option as address -for any usage of the drive. - -Different from cdrecord, cdrskin is intended to be run without special -privileges, i.e. no superuser setuid. It is intended that the sysadmin -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. - -Non-cdrecord blank mode blank=format_overwrite brings a DVD-RW -disc from its initial profile "Sequential Recording" into profile state -"Restricted Overwrite". -{{{ -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. -{{{ -cdrskin ... write_start_address=2412m ... -}}} - -Non-cdrecord blank mode blank=deformat_sequential brings an overwriteable -DVD-RW back into state "Sequential Recording" with the capability of doing -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. - -blank=deformat_sequential does minimal blanking of DVD-RW which usually yields -media incapable of "Incremental Streaming". - -Option --prodvd_cli_compatible activates blank=fast and blank=all for -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 -was used with the formatter program (e.g. mkisofs -C) matches the start block -address which will be used by the upcoming burn. - -E.g. cdrskin aborts with an error message if -{{{ -assert_write_lba=0 -}}} -is given but an appendable media is to be burned which would start at -block 68432. - - -An ISO-9660 file system image must be prepared according to a particular -block address on media. If the prepared address and the real address on media -do not match then the filesystem will not be mountable or may even cause system -trouble. - -A sequential archive format like afio or star will not necessarily need such -a coordination of addresses. It might nevertheless be confusing to a reader -if the archive does not start at block 0. - --------------------------------------------------------------------------- - -fifo_start_at=<num> is a throughput enhancer for unsteady data streams -like they are produced by a compressing archiver program when piping to -CD on-the-fly. It makes better use of the general property of a FIFO -buffer to transport surplus bandwidth into the future. Yep. A time machine. -One-way, i fear. - -FIFO originally was introduced by cdrecord's author Joerg Schilling in order -to protect mediocre burner hardware from suffering buffer underruns -and thus producing misburns (at 1x speed on CD-R media at the price of a -DVD-RAM nowadays). This purpose would not justify a fifo any more - -given the limited life time of burners and the seamless underrun protection -of contemporary consumer drives. - -With an unsteady data stream the task of the buffer is to soak up peak -performance and to release it steadily at the drive's maximum speed. -The larger the buffer the more reserves can be built up and the longer -input drought can be compensated. - -Original cdrecord has the historical property, though, to first wait until -the buffer is completely filled. Best practice for fighting drive -underruns, of course. -With a very fat fs=# buffer (128 MB for 12x CD is not unrealistic) this -can cause a big delay until burning finally starts and takes its due time. - -fifo_start_at=<num> makes cdrskin start burning after the given number of bytes -is read rather than waiting for the FIFO to be completely full resp. the data -stream to end. It risks a few drive buffer underruns at the beginning of burn -- but modern drives stand this. - -Usage examples: -{{{ -cdrskin ... fs=128m fifo_start_at=20m ... -cdrskin ... fifo_start_at=0 ... -}}} - -Note: no FIFO can give you better average throughput than the average -throughput of the data source and the throughput of the burner. -It can be used, though, to bring the effective throughput very close -to the theoretical limit. Especially with high speed media. - --------------------------------------------------------------------------- - ---no_rc allows you to surely ban influence from systemwide or user specific -default settings of cdrskin. Possible locations for such settings: - -/etc/default/cdrskin - -/etc/opt/cdrskin/rc - -/etc/cdrskin/cdrskin.conf - -$HOME/.cdrskinrc - --------------------------------------------------------------------------- - -dev_translation=<sep><from><sep><to> may be needed to foist cdrskin to -frontend programs of cdrecord which do *not* ask cdrecord -scanbus but -which make own assumptions and guesses about cdrecord's device addresses. - -Normally, cdrskin understands all addresses which are suitable for cdrecord -under Linux. See cdrskin/README, "Pseudo-SCSI Adresses". -This option is mainly for (yet unknown) exotic configurations or very -stubborn frontend programs. - -If a frontend refuses to work with cdrskin, look into the error protocol -of that frontend, look at the output of a run of cdrskin --devices and give -cdrskin the necessary hint. -Example: Your frontend insists in using "0,0,0" and --devices reported -dev='/dev/hdc' resp. cdrskin dev=ATA -scanbus reported "1,0,0" then this -would be the appropriate translation: -{{{ -dev_translation=+0,0,0+/dev/hdc -}}} -The "+" character is a separator to be choosen by you. -Currently i am not aware of the need to choose any other than "+" -unless you get playful with custom translations like -{{{ -dev_translation=-"cd+dvd"-1,0,0 -}}} -See http://scdbackup.sourceforge.net/k3b_on_cdrskin.html -for an illustrated example with K3b 0.10 . - --------------------------------------------------------------------------- - -DVD advise: - -For burning of DVD/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. - -http://fy.chalmers.se/~appro/linux/DVD+RW/tools - -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, 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]. - --------------------------------------------------------------------------- - diff --git a/configure.ac b/configure.ac deleted file mode 100644 index 905018e..0000000 --- a/configure.ac +++ /dev/null @@ -1,181 +0,0 @@ -AC_INIT([libburn], [0.4.6], [http://libburnia-project.org]) -AC_PREREQ([2.50]) -dnl AC_CONFIG_HEADER([config.h]) - -AC_CANONICAL_HOST -AC_CANONICAL_TARGET - -AM_INIT_AUTOMAKE([subdir-objects]) - -dnl Notes by ts A71207 - A80126 : -dnl -dnl Regrettably the meaning of the various version types was misunderstood -dnl before version 0.4.1. -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 -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=4 -BURN_MICRO_VERSION=6 -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_VERSION) - -dnl Libtool versioning -LT_RELEASE=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION -dnl -dnl ts A80510 -dnl This is the release version libburn-0.4.6 = libburn.so.4.11.0 -dnl ### This will be the development version after above release version -dnl LT_CURRENT++, LT_AGE++ has not yet happened. -dnl -dnl SONAME = 15 - 11 = 4 . Library name = libburn.so.4.11.0 -LT_CURRENT=15 -LT_REVISION=0 -LT_AGE=11 -LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE` - -AC_SUBST(LT_RELEASE) -AC_SUBST(LT_CURRENT) -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 - -AM_MAINTAINER_MODE - -AM_PROG_CC_C_O -AC_C_CONST -AC_C_INLINE -AC_C_BIGENDIAN - -dnl Large file support -AC_SYS_LARGEFILE -AC_FUNC_FSEEKO -AC_CHECK_FUNC([fseeko]) -if test ! $ac_cv_func_fseeko; then - AC_ERROR([Libburn requires largefile support.]) -fi - -AC_PROG_LIBTOOL -AC_SUBST(LIBTOOL_DEPS) -LIBTOOL="$LIBTOOL --silent" - -AC_PROG_INSTALL - -AC_CHECK_HEADERS() - -THREAD_LIBS=-lpthread -AC_SUBST(THREAD_LIBS) - -TARGET_SHIZZLE -AC_SUBST(ARCH) -AC_SUBST(LIBBURN_ARCH_LIBS) - -dnl Add compiler-specific flags - -dnl See if the user wants aggressive optimizations of the code -AC_ARG_ENABLE(debug, -[ --enable-debug Disable aggressive optimizations [default=yes]], - , enable_debug=yes) -if test x$enable_debug != xyes; then - if test x$GCC = xyes; then - CFLAGS="$CFLAGS -O3" - CFLAGS="$CFLAGS -fexpensive-optimizations" - fi - CFLAGS="$CFLAGS -DNDEBUG" -else - if test x$GCC = xyes; then - CFLAGS="$CFLAGS -g -pedantic -Wall" - fi - CFLAGS="$CFLAGS -DDEBUG" -fi - -AC_CONFIG_FILES([ - Makefile - doc/doxygen.conf - version.h - libburn-1.pc - ]) -AC_OUTPUT diff --git a/doc/Makefile b/doc/Makefile deleted file mode 100644 index 062350d..0000000 --- a/doc/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -all clean: - $(MAKE) -C .. -$(MAKEFLAGS) $@ - -.PHONY: all clean diff --git a/doc/comments b/doc/comments deleted file mode 100644 index 0b9d490..0000000 --- a/doc/comments +++ /dev/null @@ -1,180 +0,0 @@ -/** - @author Mario Danic, Thomas Schmitt - - @mainpage Libburnia Documentation Index - - @section intro Introduction - -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. - -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. - -The project comprises of several more or less interdependent parts which -together strive to be a usable foundation for application development. -These are libraries, language bindings, and middleware binaries which emulate -classical (and valuable) Linux tools. - -Our scope is currently Linux 2.4 and 2.6 only. For ports to other systems -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. - -@subsection components 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). - 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. - 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. - 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). - - - @section using Using the libraries - -Our build system is based on autotools. -User experience tells us that you will need at least autotools version 1.7. - -To build libburn and its subprojects it should be sufficient to go into -its toplevel directory and execute - -- ./bootstrap (needed if you downloaded from SVN) - -- ./configure - -- make - -To make the libraries accessible for running resp. developing applications - -- make install - -Both libraries are written in C language and get built by autotools. -Thus we expect them to be useable by a wide range of Linux-implemented -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 . -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. - -It's main purpose, nevertheless, is to show you how to use libburn and also -to serve the libburnia team as reference application. libburner does indeed -define the standard way how above three gestures can be implemented and -stay upward compatible for a good while. - - @subsection libburner-help Libburner --help -<pre> -Usage: test/libburner - [--drive <address>|<driveno>|"-"] [--audio] - [--blank_fast|--blank_full|--format_overwrite] - [--try_to_simulate] - [--multi] [<one or more imagefiles>|"-"] -Examples -A bus scan (needs rw-permissions to see a drive): - test/libburner --drive - -Burn a file to drive chosen by number, leave appendable: - test/libburner --drive 0 --multi my_image_file -Burn a file to drive chosen by persistent address, close: - test/libburner --drive /dev/hdc my_image_file -Blank a used CD-RW (is combinable with burning in one run): - test/libburner --drive /dev/hdc --blank_fast -Blank a used DVD-RW (is combinable with burning in one run): - test/libburner --drive /dev/hdc --blank_full -Format a DVD-RW to avoid need for blanking before re-use: - test/libburner --drive /dev/hdc --format_overwrite -Burn two audio tracks (to CD only): - lame --decode -t /path/to/track1.mp3 track1.cd - test/dewav /path/to/track2.wav -o track2.cd - test/libburner --drive /dev/hdc --audio track1.cd track2.cd -Burn a compressed afio archive on-the-fly: - ( cd my_directory ; find . -print | afio -oZ - ) | \ - test/libburner --drive /dev/hdc - -To be read from *not mounted* media via: afio -tvZ /dev/hdc -</pre> -libburner has two companions, telltoc and dewav, which help to perform some -peripheral tasks of burning. - -telltoc prints a table of content (sessions, tracks and leadouts), it tells -about type and state of media, and also is able to provide the necessary -multi-session information for program mkisofs option -C. Especially helpful -are its predictions with "Write multi" and "Write modes" where availability -of "TAO" indicates that tracks of unpredicted length can be written. -See: test/telltoc --help. - -dewav extracts raw byte-swapped audio data from files of format .wav (MS WAVE) -or .au (SUN Audio). See example in libburner --help. - - @subsection libburner-source Sourceode of libburner - -Click on blue names of functions, structures, variables, etc in oder to -get to the according specs of libburn API or libburner sourcecode. - -@include libburner.c -*/ diff --git a/doc/cookbook.txt b/doc/cookbook.txt deleted file mode 100644 index deb8a67..0000000 --- a/doc/cookbook.txt +++ /dev/null @@ -1,1201 +0,0 @@ -libburnia-project.org Optical Media Rotisserie Recipes as of April 2008 - -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) -- Sequential DVD-R[W] Cookbook -- DVD+R[/DL] Cookbook - -------------------------------------------------------------------------------- - TAO Multi-Session CD Cookbook -------------------------------------------------------------------------------- -Guided by reading mmc-r10a.pdf , O.8 "Write a Track" - from http://www.t10.org/ftp/t10/drafts/mmc/ -backed by reading mmc5r03c.pdf from http://www.t10.org/ftp/t10/drafts/mmc5/ -by reading spc3r23.pdf from http://www.t10.org/ftp/t10/drafts/spc3/ -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> - -------------------------------------------------------------------------------- - -Media type can be recognized by Current Profile from 46h GET CONFIGURATION. -(mmc5r03c.pdf 6.6.2.1) - -CD-R 0009h -CD-RW 000ah - -The following topics are covered in this text: -- About blank, appendable and finalized CD media -- Writing a session to CD in TAO mode -- Obtaining CD multi-session info for extending ISO-9660 filesystems -- Obtaining a Table Of Content from CD - - -------------------------------------------------------------------------------- -About blank, appendable and finalized CD media : - -CD media have to be blank or appendable in order to be writeable in TAO mode. -The according status may be inquired by 51h READ DISC INFORMATION requesting -Data Type 000b Standard Disc Information, where reply value Disc Status -indicates: - 00b blank - 01b appendable - 10b finalized - 11b others (unsuitable for this recipe) -(mmc5r03c.pdf 6.22.3.1.4) - -CD-RW which are finalized or appendable may be blanked by command A1h BLANK -with blanking types 000b "Blank the disc" or 001b "Minimally blank the disc". -The Start Address/Track Number will be ignored so it may well be 0. - -Because the operation is long running it is advised to set the Immed bit and to -watch the progress by commands 00h TEST UNIT READY and 03h REQUEST SENSE -with DESC bit set to 0 for fixed format reply. -It is done when 00h succeeds and 03h reports 0 in PROGRESS INDICATION -(byte 1+2 in Table 22 = byte 16+17 SENSE KEY SPECIFIC in table 26). -(mmc5r03c.pdf 6.2 BLANK) -(spc3r23.pdf 4.5.2.4.4 table 22, 4.5.3 table 26, - 6.27 REQUEST SENSE, 6.33 TEST UNIT READY) - - -------------------------------------------------------------------------------- -Writing a session to CD in TAO mode : - -The writing method for blank or appendable media is the same. A new session -will get created automatically by the first track when it is written. If the -media is blank then the new session will be the first and only one in the -table of content. If the media is appendable then a new session will be -appended to the existing sessions. In any case the new track will be the -first one in the new session. - -Speed may be set by BBh SET CD SPEED parameter Drive Write Speed. Note that -kbytes/sec means 1000 bytes/sec and not 1024/sec. Rotational control should -be set to 00b. 1x CD speed is 176.4 kbytes/sec. Speed is usually set to the -next lower possible value by the drive. So it is helpful to add a few -kbytes/sec just in case the drive has rounding problems. -(mmc5r03c.pdf 6.37) - -Before writing can occur, a Write Parameters mode page 05h has to be composed -and transmitted via 55h MODE SELECT. Mode page 05h describes several burn -parameters: - BUFE Buffer Underrun protection 0=off, 1=on - Test Write -dummy mode for writing 0=off, 1=on - Write Type Packet/TAO/SAO/RAW 01h = TAO - Multi-session Wether to keep appendable 00b = finalize - 11b = keep appendable - Track Mode Describes frame type 4 for data , 0 for audio - Data Block Type Layout of payload blocks 8 for 2048 byte data blocks - 0 for 2352 byte audio blocks - Audio Pause Length 150 = 2 seconds -Any other parameters may be set to 0. -Mode page data as of MMC-5 table 644 are preceded by a Mode Parameter Header -as of SPC-3 table 240. This 8-byte header may be filled with zeros. -(mmc5r03c.pdf 7.5.4 The Mode Page, 4.2.3.4 Table 17 CONTROL = Track Mode) -(spc3r23.pdf 6.8 MODE SELECT, 7.4.3 Mode parameter header formats) - - -Writing has to begin at the address returned by 52h READ TRACK INFORMATION -with Address/Number Type set to 01b and Logical Block Address/Track/Session -Number set to FFh. The Next Writeable Address as of table 500 is the number -to start writing with. -(mmc5r03c.pdf 6.27 ) - -Writing is performed by one or more 2Ah WRITE transactions with the Logical -Block Address counted up from the initial number in sync with the number of -blocks written. I.e the Transfer Length of the previous 2Ah WRITE has to be -added to the Logical Block Address for the next 2Ah WRITE. Only full blocks -can be written. -(mmc5r03c.pdf, 6.44) -When writing is done, it is mandatory to force the drive's buffer to media by -35h SYNCHRONIZE CACHE. -(mmc5r03c.pdf, 6.41) - -A track must at least contain 300 payload blocks: 4 seconds of audio or -600 KiB of data. -(mmc5r03c.pdf 6.3.3.1.2) - -The track has to be closed by 5Bh CLOSE TRACK SESSION Close Function 001b. -Older MMC specifies a valid Logical Track Number FFh to depict the open track. -MMC-5 is quite silent about this. FFh works for my drives. -(mmc5r03c.pdf 6.3.3.1.2) - -After that, a new track may be written beginning with sending the mode page 05h -again. It is not tested wether 05h can be omitted if Track Mode and Data Block -Type are the same as with the previous track. -The new track will be added to the session which was opened by the first track. - -After the last track of a session, 5Bh CLOSE TRACK SESSION Close Function 010b -with Logical Track Number 0 closes the session. It depends on the Multi-Session -value in mode page 05h wether the disc is finalized or stays appendable. -(mmc5r03c.pdf 6.3.3.1.3) - - -------------------------------------------------------------------------------- -Obtaining CD multi-session info for extending ISO-9660 filesystems : - -Program mkisofs expects two numbers with its option -C which describe the -situation on an appendable CD which already contains a ISO-9660 filesystem -in the first track of the last session. - -The first number is the Logical Block Address of that track containing the -existing ISO-9660 filesystem image. This number is needed for mkisofs option --M to connect to the existing image. The new image will refer to files in -the previously existing image. mkisofs option -M needs read access to the -CD or a blockwise copy of it on hard disk. -The number is gained by 43h READ TOC/PMA/ATIP. -(mmc5r03c.pdf 6.26) -Untested is Format 0001b which in table 478 promises quick access via -Start Address Of First Track In Last Session. -(mmc5r03c.pdf 6.26.2.5 table 478, 6.26.3.3.1) -libburn gets the number from its Table Of Content model which is obtained -by 43h READ TOC/PMA/ATIP, Format 0010b. See below. - -The second number is an exact prediction of the Logical Block Address of the -new track which will contain the newly generated ISO-9660 image. -Even without mkisofs option -M this second number is still needed to make the -inner block address pointers of the image match the Logical Block Addresses -on CD. For that one may inquire 52h READ TRACK INFORMATION with -Address/Number Type set to 01b and Logical Block Address/Track/Session -Number set to FFh. The Next Writeable Address as of table 500 is the number -to use. -(mmc5r03c.pdf 6.27 ) - - -------------------------------------------------------------------------------- -Obtaining a Table Of Content from CD : - -The structure of a CD is comprised of sessions. Each session contains one or -more tracks and is followed by a lead-out. A track has an address and a length. - -Table of content information is gained by 43h READ TOC/PMA/ATIP, Format 0010b. -(mmc5r03c.pdf 6.26.2.5 table 478) - -The number of sessions is given by Last Complete Session Number. -The number of TOC Track descriptors is: (TOC Data Length - 2)/11 . - -Each TOC Track Descriptor contains a Session Number. - -If POINT is >= 1 and <= 99 (63h) then the descriptor is about the track of -which POINT tells the number. -The start address of this track can be read from PMIN, PSEC, PFRAME where -it is encoded in MSF format: -blocks = frames - 150, 75 frames = 1 sec , 60 sec = 1 min. -The length of the track is given by MIN,SEC,FRAME in the same format. - -If POINT = A0h then the descriptor tells in PMIN the first track number of its -session. -POINT = A1h tells in PMIN the last track number of its session. -POINT = A2h describes in PMIN, PSEC, PFRAME the lead-out of a session, i.e the -first address after the session's end. (Next writeable address typically is -lead-out + 11400 after the first session, lead-out + 6900 after further -sessions.) -POINT = B0h tells in MIN,SEC,FRAME this next writeable address or FFh,FFh,FFh -for finalized disc. -(mmc5r03c.pdf 6.26.3.4 table 489, 4.2.3.7 Mode-1 Q, Mode-5 Q) - - -In libburn the address of the first track in the last session is obtained from -the last session's POINT = A0h and from the track descriptor with the POINT -value matching the PMIN value of the A0h descriptor. -Untested is wether POINT = B0h and 52h READ TRACK INFORMATION are always in -sync. libburn uses the info provided by 52h READ TRACK INFORMATION. - - -------------------------------------------------------------------------------- - -------------------------------------------------------------------------------- - SAO CD Cookbook -------------------------------------------------------------------------------- -Guided by reading libburn/* from http://icculus.org/burn -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> - -------------------------------------------------------------------------------- - -Recognition of media type and state (blank, appendable, finalized) is as -described in the TAO Multi-Session CD Cookbook. See there. - -The MMC specs do not give much hint about the combination of SAO and -multi-session. My drives refused not only on a few experiments which i did -in libburn but also failed with cdrecord -sao on an appendable CD. -So for now only blank CD seem to be suitable for SAO writing. - -Different from TAO mode, the whole session layout is announced to the drive by -sending a Cue Sheet. This implies that the sizes of the tracks have to be known -in advance, which is a heavy drawback when dealing with track data sources like -stdin, named pipes or sockets. -Nevertheless, SAO seems to be best writing mode for audio purposes, as our -audio expert Lorenzo Taylor found out. - -A SAO session in libburn may either consist entirely of audio tracks or -entirely of data tracks. For mixed sessions, only TAO is usable yet. - -- Composing a SAO CD Cue Sheet (either audio or data, but not mixed) -- Writing the prepared SAO CD session -- What is known about mixed mode sessions - - -------------------------------------------------------------------------------- -Composing a Cue Sheet (either audio or data, but not mixed) : - -The Cue Sheet will get submitted to the drive by 5Dh SEND CUE SHEET. -Each entry of the sheet is of 8 bytes size. Its fields are named -CTL|ADR, TNO, INDEX, DATA FORM, SCMS, MIN, SEC, FRAME . -(mmc5r03c.pdf 6.33) - -CTL is 40h for data and 00h for audio. -(mmc5r03c.pdf 6.33.3.4) -ADR is always 01h. -TNO is the track number (1 to 99). -INDEX is a subaddress within tracks. This recipe uses only INDEX 01h within -tracks. -(mmc5r03c.pdf 4.2.3.5.2) -DATA FORM is 00h for audio payload , 10h for data. (01h for audio pause is not -used in libburn). -(mmc5r03c.pdf 6.33.3.11 CD-DA Data Form, 6.33.3.12 CD-ROM mode 1 Form) -SCMS is always 00h. -MIN, SEC, FRAME give the MSF address where the described data entity starts. -LBA = frames - 150, 75 frames = 1 sec , 60 sec = 1 min. -This address must increase from entry to entry (or at least stay equal). - - -The first entry describes the Lead-in. Its content is -(CTL|ADR ,00h,00h,01h,00h,00h,00h,00h) -With the CTL|ADR for the first track: 41h for data, 01h for audio. - -The LBA for the first write is negative: -150. This corresponds to MSF address -00h:00h:00h. All addresses are to be given in MSF format. -The first information track on disc is preceded by a pause encoding of 2 sec: -(CTL|ADR,01h,00h, DATA FORM ,00h,00h,00h,00h) -with DATA FORM = 00h for audio and 10h for data. By those 2 seconds the MSF -address increases to 00h:02h:00h = LBA 0. - -Each track is represented by an entry -(CTL|ADR, TNO ,01h,DATA FORM,00h, MIN , SEC , FRAME) -TNO gives the track number. MIN, SEC, FRAME give the MSF address which becomes -the start address of the track. The MSF address is then increased by the size -of the track (to be used with next track or with lead-out). - -A track must at least contain 300 payload blocks: 4 seconds of audio or -600 KiB of data. -(mmc5r03c.pdf 6.33.3.6) - -At the end of the session there is a lead-out entry -(CTL|ADR,AAh,01h,01h,00h,MIN,SEC,FRAME) -marking the end of the last track. (With libburn CTL is as of the last track.) - - -------------------------------------------------------------------------------- -Writing the prepared session : - -Speed may be set by BBh SET CD SPEED parameter Drive Write Speed. Note that -kbytes/sec means 1000 bytes/sec and not 1024/sec. Rotational control should -be set to 00b. 1x CD speed is 176.4 kbytes/sec. Speed is usually set to the -next lower possible value by the drive. So it is helpful to add a few -kbytes/sec just in case the drive has rounding problems. -(mmc5r03c.pdf 6.37) - -A Write Parameters mode page 05h has to be composed and transmitted via -55h MODE SELECT. This page describes the following parameters: - BUFE Buffer Underrun protection 0=off, 1=on - Test Write -dummy mode for writing 0=off, 1=on - Write Type Packet/TAO/SAO/RAW 02h = SAO - Multi-session Wether to keep appendable 00b = finalize - 11b = keep appendable - Track Mode Describes frame type 0 (is ignored) - Data Block Type Layout of payload blocks 0 (is ignored) - Audio Pause Length 150 = 2 seconds (ignored ?) -Any other parameters may be set to 0. -Mode page data as of MMC-5 table 644 are preceded by a Mode Parameter Header -as of SPC-3 table 240. This 8-byte header may be filled with zeros. -(mmc5r03c.pdf 7.5.4 The Mode Page, 4.2.3.4 Table 17 CONTROL = Track Mode) -(spc3r23.pdf 6.8 MODE SELECT, 7.4.3 Mode parameter header formats) - -The Cue Sheet is submitted to the drive by 5Dh SEND CUE SHEET. Cue Sheet Size -is 8 times the number of entries. -(mmc5r03c.pdf 6.33) - -Writing is performed by multiple 2Ah WRITE transactions with the Logical -Block Address counted up from the initial number in sync with the number of -blocks written. I.e the Transfer Length of the previous 2Ah WRITE has to be -added to the Logical Block Address for the next 2Ah WRITE. Only full blocks -can be written. -(mmc5r03c.pdf, 6.44) -Writing begins at LBA -150 which is to be transmitted as 4-byte, Big-endian, -two's-complement. E.g: -150 = FFh FFh FFh 6Ah. This is the natural form found -with about any 32-bit processor, so only the endianness has to be taken into -respect when converting a 32-bit integer into a LBA for command 2Ah WRITE. - - -At first the mandatory pause preceding the first track has to be written as -150 blocks of the matching sector size: 2048 for data, 2352 for audio. -By this, the LBA increases from -150 to 0. - -Next the tracks' payload is sent. For each track exactly the number of blocks -has to be transmitted as is announced in the Cue Sheet by the difference -of the track's own start address and the start address of the next entry in -the Cue Sheet. After each write the LBA for the next write has to be increased -by the number of blocks transmitted. Just like with TAO writing. - -There is no separator between the tracks of a pure mode SAO session. -(If the session was mixed mode, there would be extended Pre-gaps and Post-gaps -between data mode tracks and audio mode tracks.) -(libburn sends its own buffer to the drive at the end of each track but does -not sync the drive's chache. It is unclear wether this separation of tracks -on the level of 2Ah WRITE is necessary with a pure mode session. It does not -harm in any case and would probably be unavoidable if audio and data tracks -were mixed.) - -When writing of all tracks is done, it is mandatory to force the drive's buffer -to media by 35h SYNCHRONIZE CACHE. -(mmc5r03c.pdf, 6.41) - -No further finalization is necessary. (I.e. no 5Bh CLOSE TRACK SESSION.) - - ----------------------------------------------------------------------------- -What is known about mixed mode sessions : - -For now, SAO sessions with a mix of data and audio are not supported in -libburn. Here are the reasons why. - -Obviously the code of http://icculus.org/burn is incomplete in this aspect. -In mmc5r03c.pdf comparison of table 555 and 6.33.3.18 seems self-contradicting. -(The second Pre-gap in table 555 does not match any of the criteria of -6.33.3.18. Also, there is no Post-gap shown in table 555 although 6.33.3.19 -would prescribe some.) - -If a data track follows an audio track then the data track gets a preceding -extended Pre-gap: -(CTL|ADR, TNO ,01h,DATA FORM,00h, MIN , SEC , FRAME) -with TNO already the number of the data track. The MSF address is to be -increased by 3 seconds. The first second of the extended Pre-gap needs to be -written in the audio track's mode and the other 2 seconds are to be written -in the data track's mode. -(libburn compares DATA FORM rather than burn_track.mode . Wrong ?) -(libburn currently does only 2 seconds and the second part of Pre-gap. There is -an issue with burn_track.pregap1 about this. Seems libburn mistakes the pause -preceding track 1 for a part 2 of an extended Pre-gap.) - -If a data track is followed by an audio track then it gets a Post-gap of at -least two seconds. -No example of Post-gap is given for Cue Sheet. Maybe it is to be added to the -track, or maybe it gets an own Cue Sheet entry ... who knows ? -(libburn contains write code for pregap1, pregap2 and postgap. But only -pregap2 ever gets activated. Once hackingly for the first 2 second pause, once -incompletely for a change of DATA FORM.) - -Seems nobody ever tested this. Libburnia simply knows no use case where the -correctness of Pre-gap and Post-gap would become evident. - - -------------------------------------------------------------------------------- - -------------------------------------------------------------------------------- - Overwriteable DVD Cookbook -------------------------------------------------------------------------------- -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. - -For libburnia-project.org by Thomas Schmitt <scdbackup@gmx.net> - -------------------------------------------------------------------------------- - -Media type can be recognized by Current Profile from 46h GET CONFIGURATION. -(mmc5r03c.pdf 6.6.2.1) - -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 -- 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 - -------------------------------------------------------------------------------- -Overwriting in general : - -Depending on media type, some kind of formatting has to have happened before -data can be written. Formatting may happen separately from writing or -simultaneously. See the particular recipes below. - -No Write Parameters mode page 05h is to be sent. Speed can be influenced by -B6h SET STREAMING , speed capabilities can be inquired by ACh GET PERFORMANCE. -It is advised to set only speeds and sizes which are returned by ACh. -(mmc5r03c.pdf 6.39 SET STREAMING, 6.8 GET PERFORMANCE) -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 -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. -(mmc5r03c.pdf, 6.44) -When writing is done, it is mandatory to force the drive's buffer to media by -35h SYNCHRONIZE CACHE. -(mmc5r03c.pdf, 6.41) - -The size of the formatted area can be inquired by 23h READ FORMAT CAPACITIES. -The Number Of Blocks value in the Current/Maximum Capacity Descriptor gives -this size in 2 KiB blocks. But this is true only if Descriptor Type is 10b -("Formatted Media"). -(mmc5r03c.pdf, 6.24.3.2.1, 6.24.3.2.3) - -Not yet formatted areas may be completely forbidden or they may be allowed for -sequential writing (DVD-RW Intermediate state) or they may be allowed for -random access only after the necessary waiting time for formatting to reach -the desired address (DVD+RW with background formatting active). - -Already written areas can be overwritten without special precaution. -Blanking a DVD-RW actually destroys its formatting. - - -Most of the concepts usually expressed in Write Parameters mode page 05h do not -apply to the recipes here: Test-Write, Buffer Underrun protection, -Multi-session, Write Type, Block Type, Track Mode, ... -There are hints for multi-session formats with DVD-RW but both of my drives -do not offer "Add Session" Format Types 12h or 14h. -(mmc5r03c.pdf 6.5.4.2.7 , 6.5.4.2.9) - - -Caution: Drive and media compatibility seems still to be quite an adventure. -If you experience problems, especially problems with readability, then try -different drives and media brands. Failure does not necessarily mean that the -software did anything wrong. - - -------------------------------------------------------------------------------- -DVD-RAM, fully formatted DVD+RW, DVD-RW, BD-RE : - -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. - -DVD+RW reaches this state if Background Formatting is allowed to finish without -being stopped by 5Bh CLOSE TRACK SESSION. -(mmc5r03c.pdf, 6.5 FORMAT UNIT, 6.5.4.2.14 Format Type = 26h) -The formatting state of a DVD+RW may be inquired by 51h READ DISC INFORMATION -requesting Data Type 000b "Standard Disc Information". In the reply, -BG Format 3 indicates fully formatted media. -(mmc5r03c.pdf 6.22.3.1.13) - -DVD-RW reaches this state either by Format Type 00h (or 10h) with maximum -size given as Number Of Blocks, or by writing sequentially until the disc is -completely full into an intermediate session opened by format 15h resp. 13h. -(mmc5r03c.pdf, 6.5 FORMAT UNIT, 6.5.4.2.1, 6.5.4.2.10, 6.5.4.2.8) -A fully formatted DVD-RW can be recognized by 23h READ FORMAT CAPACITIES. The -Descriptor Type of the Current/Maximum Capacity Descriptor is 10b ("Formatted -Media") and 0 blocks are offered with Format Types 13h or 11h. -(mmc5r03c.pdf, 6.24.3.2.1, 6.24.3.3) -See also discussion of unformatted or partially formatted DVD-RW below. - - -In fully formatted state there is no need for any formatting before writing nor -for any finalizing other than forcing the drive's buffer to media by -35h SYNCHRONIZE CACHE (which is mandatory for writing, anyway). -(mmc5r03c.pdf, 6.41) - -(It seems to do no harm to send to DVD+RW or DVD-RW a 5Bh CLOSE TRACK SESSION -with Close Function 010b despite there is no session open in this scenario.) - - -------------------------------------------------------------------------------- -Unformatted DVD+RW - -This is the state of previously unused DVD+RW media. - -The formatting state of a DVD+RW may be inquired by 51h READ DISC INFORMATION -requiring Data Type 000b "Standard Disc Information". -In the reply, BG Format 0 indicates unformatted media (or unsuitable media). -(mmc5r03c.pdf 6.22.3.1.13) - -Formatting has to be started by command 04h FORMAT UNIT, Format Type 26h. -Different from other format types, 26h allows to send a fantasy size of -0xffffffff blocks and does not require the caller to know the exact maximum -size offered with that format. -(mmc5r03c.pdf, 6.5 FORMAT UNIT, 6.5.4.2.14 Format Type = 26h) - -As its name suggests, one has not to wait for background formatting to end -but may very soon start writing as on formatted media. Random access to -yet unformatted areas can last long, though. - -If backup formatting has been started at the beginning of the session, then -it may get stopped after the final cache sync by 5Bh CLOSE TRACK SESSION -with Close Function 010b. -(mmc5r03c.pdf 6.3.3.6) - -Formatting of DVD+RW is called "de-icing" because unformatted areas offer -no hold for random access addressing and are thus slippery like ice. One can -also see a color change from shiny unformatted to more dull formatted media. - - -------------------------------------------------------------------------------- -Partly formatted DVD+RW : - -This state is achieved by stopping background formatting before the media -was completely formmatted. - -The formatting state of a DVD+RW is obtained by 51h READ DISC INFORMATION -requiring Data Type 000b "Standard Disc Information". -In the reply, BG Format 1 indicates partly formatted media. -(mmc5r03c.pdf 6.22.3.1.13) - -If the data of the session surely fit into the formatted area, then it would -be unnecessary to restart background formatting. -But in order to make the DVD+RW surely accept its maximum number of bytes, -formatting may be restarted by command 04h FORMAT UNIT, Format Type 26h, -with the Restart bit set and Number of Blocks set to 0xffffffff. -(mmc5r03c.pdf, 6.5 FORMAT UNIT, 6.5.4.2.14 Format Type = 26h) - -From then on, the same rules apply as for previously unformatted DVD+RW. - - -------------------------------------------------------------------------------- -Unformatted DVD-RW (media profile is 0014h) : - -This state is present with previously unused media. It is also present with -media blanked by programs cdrecord, wodim or dvd+rw-format and with media which -were sequentially written from blank state. -Profile transition from formatted 0013h to unformatted 0014h is done by -A1h BLANK. -(mmc5r03c.pdf, 6.2) -Experiments on my drives indicate that only Blanking Type 000b "Blank the disc" -achieves neat media. Media blanked via type 001b offer no feature 0021h and -stall cdrecord or libburn already when those media get examined. growisofs can -burn them - but only via DAO (feature 002Fh which prescribes Write Type 2). -(mmc5r03c.pdf 5.3.11, 5.3.25) - -For becoming overwriteable such media need to be treated by command 04h FORMAT -UNIT. -(mmc5r03c.pdf, 6.5) -The Format Type has to be chosen from the list replied by 23h READ FORMAT -CAPACITIES. Suitable are Format Types 00h, 10h, 15h. -(mmc5r03c.pdf 6.24) - -Format Types 00h and 10h provide a writeable area of a size given by Number of -Blocks. Type 00h seems to be the most traditional and complete one. It needs -no closing of a session at the end of writing. -The Number Of Blocks may be at most the value reported by 23h READ FORMAT -CAPACITIES in the entry for the desired format type. Full format is achieved -by sending exactly the reported value. -(mmc5r03c.pdf, 6.5.4.2.1 Format Type = 00h, 6.5.4.2.5 Format Type = 10h) - -Format Type 15h provides a writeable area of given size too, but this area can -be expanded by sequential writing and afterwards marked as overwriteable by -closing the session. It is even allowed to format with size 0 and to leave -the size claim entirely to a sequential write process beginning at LBA 0. -(mmc5r03c.pdf, 6.5.4.2.10 Format Type = 15h) -When writing is done and cache is synced, one should send 5Bh CLOSE TRACK -SESSION with Close Function 010b in order to bring the session out of -Intermediate state. -(mmc5r03c.pdf 6.3.3.2.3) -If not written up to the last 32 KiB block, the DVD-RW is only partly formatted -after that. - - -------------------------------------------------------------------------------- -Partly formatted DVD-RW (media profile is 0013h) : - -This state is achieved by formatting a DVD-RW with a number of blocks which -is less than offered for the Format Type by the drive's reply to 23h READ -FORMAT CAPACITIES. If the media was most recently formatted by Format Types -015h or 013h then it must have got written some bytes and afterwards treated -by 5Bh CLOSE TRACK SESSION, 010b in order to be partly formatted. -(mmc5r03c.pdf 6.3.3.2.3 CLOSE TRACK SESSION 010b, 6.24 READ FORMAT CAPACITIES) -Elsewise the media is in Intermediate state. See below. - -A partly formatted DVD-RW can be recognized by 23h READ FORMAT CAPACITIES. The -Descriptor Type of the Current/Maximum Capacity Descriptor is 10b ("Formatted -Media") and the Number Of Blocks with formats 00h, 10h or 15h is larger than the -currently formatted size, resp. more than 0 blocks are offered with Format -Types 13h or 11h. -(mmc5r03c.pdf, 6.24.3.2.1, 6.24.3.3) - -If the data of the session surely fit into the formatted area, then it would -be unnecessary to do any further formatting. -But in order to make the DVD-RW surely accept its maximum number of bytes, -partial formatting may be expanded by command 04h FORMAT UNIT, Format Type 13h, -which is supposed to be offered by the drive in this state. This brings the -session again into Intermediate state and thus allows expansion by sequential -writing. As with Format Type 15h it is ok to set Number Of Blocks to 0, so that -no fixed size formatting work is done and writing can begin soon after. -(mmc5r03c.pdf, 6.5.4.2.8 Format Type = 13h) - -When writing is done and cache is synced, one should send 5Bh CLOSE TRACK -SESSION with Close Function 010b in order to bring the session out of -Intermediate state. -(mmc5r03c.pdf 6.3.3.2.3) -If not written up to the last 32 KiB block, the DVD-RW is only partly formatted -after that. - -Format Type 13h has been tested only with expanding sessions formatted by 15h. -Nevertheless it is offered with sessions from 00h and 10h, too. -According to the specs, Format Type 11h would expand a session by a fixed -size. This has not been tested yet because it is less appealing than 13h. -(mmc5r03c.pdf, 6.5.4.2.6 Format Type = 11h) - - -------------------------------------------------------------------------------- -Intermediate state DVD-RW (media profile is 0013h) : - -This state is achieved by formatting a DVD-RW with Format Type 15h or 13h -without subsequentially writing data and sending 5Bh CLOSE TRACK SESSION -with Close Function 010b. -Such media behave very unpleasing with my DVD-ROM drive under Linux 2.4 ide-cd. -One should therefore better avoid to release media in this state. - -This state can be recognized by 23h READ FORMAT CAPACITIES. The Descriptor Type -of the Current/Maximum Capacity Descriptor is 11b ("Unknown Capacity") and -no formats 13h or 11h are offered. -(mmc5r03c.pdf, 6.24.3.2.1, 6.24.3.3) - -One may treat such media as if Format Type 15h or 13h had been freshly applied. -I.e. sequential writing from LBA 0. After cache sync bring the session out -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) - - -------------------------------------------------------------------------------- - -------------------------------------------------------------------------------- - Sequential DVD-R[W] Cookbook -------------------------------------------------------------------------------- -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> - -------------------------------------------------------------------------------- - -Media type can be recognized by Current Profile from 46h GET CONFIGURATION. -(mmc5r03c.pdf 6.6.2.1) -DVD-R 0011h -DVD-RW Restricted Overwrite 0013h -DVD-RW Sequential Recording 0014h -(DVD-R/DL Sequential Recording 0015h untested, might be single-session only) - -There are two approaches for writing to sequential DVD-R[W]: DAO and -Incremental. Not all media and drives offer Incremental which allows -multi-session as with CD media and does not demand a predicted track size. -DAO seems to be the older method. It allows only one single session and -track and it demands an exactly predicted track size. - -- About overwriteable, blank, appendable and finalized DVD-R[W] media -- Incremental writing -- DAO writing -- Obtaining DVD-R[W] multi-session info for extending ISO-9660 filesystems -- Obtaining a Table Of Content from DVD-R[W] -- Hearsay about DVD-R/DL (Dual Layer) - - -------------------------------------------------------------------------------- -About overwriteable, blank, appendable and finalized DVD-R[W] media : - -DVD-RW can be either in formatted state Restricted Overwrite or in unformatted -state Sequential Recording. Sequential media can be either blank, appendable -or finalized. - -Only blank and appendable media are sequentially writeable. For overwriteable -DVD-RW see the Overwriteable DVD Cookbook. - -Overwriteable DVD-RW can be detected by their profile number 0013h in contrast -to profile number 0014h for sequential DVD-RW. -The status of sequential media can be inquired like with CD by 51h READ DISC -INFORMATION requesting Data Type 000b Standard Disc Information, where reply -value Disc Status indicates: - 00b blank - 01b appendable - 10b finalized - 11b others (unsuitable for this recipe) -(mmc5r03c.pdf 6.22.3.1.4) - -Finalized, appendable or overwriteable DVD-RW can be brought into blank -sequential state by command A1h BLANK with blanking type 000b "Blank the disc". -See TAO Multi-Session CD Cookbook for details about blanking. - -After minimal blanking (type 001b) DVD-RW my two drives do not offer the -Incremental Streaming feature 0021h the media any more. Full blanking (000b) -brings back this feature. -(mmc5r03c.pdf 6.2) - - -------------------------------------------------------------------------------- -Incremental writing : - -Incremental writing allows to produce multi-session DVDs. It is indicated -by feature 0021h being marked current in the reply of 46h GET CONFIGURATION. -growisofs inquires 0021h by setting Starting Feature Number to 0x21 and -Allocation Length to 16 in order to get only this one. The feature descriptor -begins at byte 8 of the reply. Its availability is indicated by the Current -Bit. libburn obtains the full feature list for this and other info. -(mmc5r03c.pdf 5.2.2. Feature Descriptor format, 5.3.11 Feature 0021h, - 6.2 46h GET CONFIGURATION, ) -In mode page 05h this method is selected by Write Type 00h. - -Speed can be influenced by B6h SET STREAMING , speed capabilities can be -inquired by ACh GET PERFORMANCE. It is advised to set only speeds and sizes -which are returned by ACh. -(mmc5r03c.pdf 6.39 SET STREAMING, 6.8 GET PERFORMANCE) - -growisofs fetches a mode page 05h template by MODE SENSE and inserts its own -parameters. It sets Multi-session to 11b, unless dvd_compat is nonzero. -libburn composes its mode page 05h from zero and allows control of -Multi-Session by the application. - BUFE Buffer Underrun protection 0=off, 1=on - LS_V Link size valid 1=true - Test Write -dummy mode for writing 0=off, 1=on - Write Type Packet/TAO/SAO/RAW 00h = Incremental (Packet) - Multi-session Wether to keep appendable 00b = finalize - 11b = keep appendable - Track Mode Describes frame type 5 [*1] - Data Block Type Layout of payload blocks 8 [*2] - Link Size ??? 16 [*3] - FP Fixed Packet Size Bit 1 - Packet Size 16 [*4] -(mmc5r03c.pdf 7.5.4 The Mode Page, 4.2.3.4 Table 17 CONTROL = Track Mode) -(spc3r23.pdf 6.8 MODE SELECT, 7.4.3 Mode parameter header formats) -[*1:] -growisofs takes the Track Mode from 52h READ TRACK INFORMATION, Address/Number -Type 1, Track 1, Track Information Block byte 5 & 0xf. -(mmc5r03.pdf 6.27) -The specs predict that this will be Track Mode 4 (6.27.3.8) and also state that -default is 5 (7.5.4.12). 4 means: uninterrupted, do not copy. 5 means -increment, do not copy. -[*2:] -8 means: 2048 byte data blocks. growisofs sets this value if Data Mode from -above 52h READ TRACK INFORMATION is 1 or Fh, which is predicted by the specs -to be always true. -(mmc5r03.pdf 6.27.3.10) -[*3:] -growisofs (transport.hxx) sets Link Size to 16 for profiles 0011h and 0014h. -libburn now records the first link size from feature 0021h in its burn_drive -structure. If another link size item is 16, then 16 is used. -[*4:] -growisofs takes Packet Size from 52h. Specs predict it will be 16 (= 32 kiB). -(mmc5r03.pdf 7.5.4.16) - -The writing process is much like in "Writing a session to CD in TAO mode" : -Next Writeable Address is fetched from the reply of 52h READ TRACK INFORMATION. -libburn writes full 32 kiB buffers via 2Ah WRITE. -(mmc5r03c.pdf, 6.27 READ TRACK INFORMATION, 6.44 WRITE) -When writing is done, it is mandatory to force the drive's buffer to media by -35h SYNCHRONIZE CACHE. -(mmc5r03c.pdf, 6.41) - -The track has to be closed by 5Bh CLOSE TRACK SESSION Close Function 001b. -growisofs uses the logical track number for that and not FFh like libburn -does with TAO CD. So libburn obtains the Last Track Number in Last Session -from the reply of 51h READ DISC INFORMATION requesting Data Type 000b -"Standard Disc Information". -(mmc5r03c.pdf 6.3.3.2.2 CLOSE TRACK, 6.22.3.1.) - -Multiple tracks are permissible in a single session. After all of them have -been written, 5Bh CLOSE TRACK SESSION Close Function 010b with Logical Track -Number 0 closes the session. It depends on the Multi-Session value in mode -page 05h wether the disc is finalized or stays appendable. -(mmc5r03c.pdf 6.3.3.2.3) - - -------------------------------------------------------------------------------- -DAO writing : - -DAO is the mode described by feature 002Fh. This feature also gives information -about capabilities for Burnfree (BUF), Test Write and DVD-RW. -(mmc5r03c.pdf 5.3.25) -Experiments with growisofs showed that the track size needs to be predicted -and may not be exceeded during the write process. (growisofs ran into SCSI -errors with piped non-ISO-9660 images and with piped ISO-9660 which have -trailing data.) - -Speed can be influenced by B6h SET STREAMING , speed capabilities can be -inquired by ACh GET PERFORMANCE. It is advised to set only speeds and sizes -which are returned by ACh. -(mmc5r03c.pdf 6.39 SET STREAMING, 6.8 GET PERFORMANCE) - -The mode page 05h to be sent : - BUFE Buffer Underrun protection 0=off, 1=on - LS_V Link size valid 0=false [*3] - Test Write -dummy mode for writing 0=off, 1=on - Write Type Packet/TAO/SAO/RAW 02h = DAO (same code as SAO) - Multi-session Wether to keep appendable 00b = finalize - Track Mode Describes frame type 5 [*1] - Data Block Type Layout of payload blocks 8 [*2] - Link Size ??? 0 [*3] - FP Fixed Packet Size Bit 0 [*3] - Packet Size 0 [*3] -(mmc5r03c.pdf 7.5.4 The Mode Page, 4.2.3.4 Table 17 CONTROL = Track Mode) -(spc3r23.pdf 6.8 MODE SELECT, 7.4.3 Mode parameter header formats) -[*1:] -growisofs takes the Track Mode from 52h READ TRACK INFORMATION, Address/Number -Type 1, Track 1, Track Information Block byte 5 & 0xf. -(mmc5r03.pdf 6.27) -[*2:] -8 means: 2048 byte data blocks. growisofs sets this value if Data Mode from -above 52h READ TRACK INFORMATION is 1 or Fh, which is predicted by the specs -to be always true. (If not: growisofs aborts.) -(mmc5r03.pdf 6.27.3.10) -[*3:] -Link Size, Packet Size and their companions only apply to Write Type 00h. - -The session layout must be described by 53h RESERVE TRACK, RMZ=ARSV=0. -Reservation size should better already be aligned to 32 KiB. It has not been -tested yet, what happens if not enough data get written. -(mmc5r03c.pdf 6.31) - -Next Writeable Address is fetched from the reply of 52h READ TRACK INFORMATION. -The reply is supposed to be 0. libburn writes full 32 kiB buffers via -2Ah WRITE. -(mmc5r03c.pdf, 6.27 READ TRACK INFORMATION, 6.44 WRITE) -If the track source delivers less than the announced size then libburn pads up -by zeros. -When writing is done, it is mandatory to force the drive's buffer to media by -35h SYNCHRONIZE CACHE. -(mmc5r03c.pdf, 6.41) - -No further finalization is necessary. (I.e. no 5Bh CLOSE TRACK SESSION.) - - -------------------------------------------------------------------------------- -Obtaining DVD-R[W] multi-session info for extending ISO-9660 filesystems : -(valid for DVD+R too) - -Like with CD it is necessary to obtain the two numbers for mkisofs option -C -in order to prepare a ISO-9660 filesystem image which by its inner pointers -matches the block addresses of the future location on media. -These are the start address of the first track in the last complete session -and the predicted start address of the track which will host the new image. -See TAO Multi-Session CD Cookbook for some more info about mkisofs aspects. - - -The first number may be gained by 43h READ TOC/PMA/ATIP Format 0001b which in -table 478 promises quick access via Start Address Of First Track In Last -Session. -(mmc5r03c.pdf 6.26.2.5 table 478, 6.26.3.3.1) -Regrettably the MMC-5 specs still define a useless reply for non-CD media -which obviously stems from MMC-3 times when no multi-session was possible -with non-CD. -(mmc5r03c.pdf 6.26.3.3.3) -Both my drives do give a useful reply with the correct number for appendable -DVD-RW. But not being backed by the specs this method appears unappealing . - -Another approach would be a formatted Table of Content, obtained by 43h READ -TOC/PMA/ATIP Format 0000b. The specs do not totally outrule that this returns -useful data with non-CD but they define a crippled TOC for multi-session. -(mmc5r03c.pdf 6.26.3.2.4) -My LG drive returns a more detailed TOC, my NEC drive stays with the rather -suboptimal specs. So one would get different TOCs on different drives. -Nevertheless, the MMC-5 compliant TOC would return the desired number in -the Track Start address of the track with the highest number before AAh. - -Most stable seems the approach to obtain the desired number from the reply -of 52h READ TRACK INFORMATION, Address/Number Type 01b. The field Logical Block -Address/Track/Session has to bear the track number of the first track in the -last complete session. To determine this number one has to determine the -number of the last session and the number of the last track from 51h READ DISC -INFORMATION and to iterate over the tracknumber by 52h READ TRACK INFORMATION -until the first track with the desired session number appears and reveils -its start address. -(mmc5r03c.pdf 6.22 51h DISC, 6.27 52h TRACK) -This method is very near to fabricating an own TOC. So libburn does this -when inspecting the media. If the first number for -C is needed, libburn -inquires its TOC model for the address of the first track in the last -complete session. See below for a detailed description of TOC fabrication. - - -The second -C number is the exact prediction of future track start address. It -is gained like with CD by 52h READ TRACK INFORMATION Type 01b. Different from -CD one may not use track number FFh but has to use the Last Track in Last -Session from 51h READ DISC INFORMATION. -(mmc5r03c.pdf 6.22 51h DISC, 6.27 52h TRACK) - - -------------------------------------------------------------------------------- -Obtaining a Table Of Content from DVD-R[W]: -(valid for DVD+R too) - -The raw TOC entries from 43h READ TOC/PMA/ATIP Format 0010b as described with -CD media are not available with non-CD. -There is a Format 0000b "Formatted TOC" but this is with non-CD a fictional -information much at the discretion of the drive. Two drives with the same disc -may well return different Formatted TOC. They are supposed to be consistent -only about the last complete session and even there the MMC-5 specification -6.26.3.2.5 seems to prescribe a structure which does not match the true -structure of incremental writing to sequential DVD-R[W]. -(mmc5r03c.pdf 6.26.3.2) -So i prefer not to use this method of getting a TOC. - - -The alternative is to produce an own TOC from information gained by 51h READ -DISC INFORMATION and by 52h READ TRACK INFORMATION which reveil a CD-like -structure of sessions and 1:n related tracks. - -51h READ DISC INFORMATION Data Type 000b, fields Number of Sessions (Least -Significant Byte) and Number of Sessions (Most Significant Byte) give the -number of sessions. The last complete session number of an appendable disc -is one less because there is an incomplete session at its end. libburn only -records complete sessions in its TOC model. -libburn uses Last Track in Last Session as a hint for the range of track -numbers. -(mmc5r03c.pdf 6.22) - -Next step is to iterate from 1 up to the last track number and to obtain -the according track info by 52h READ TRACK INFORMATION. Each track tells its -Session Number (LSB at byte 2, MSB at 33), its Logical Track Start Address, -its Logical Track Size, and much more which is not needed for a fake CD TOC. -One may analyze the track info more finely but for this special purpose -it is enough to discard the tracks which do not belong to complete sessions. -(mmc5r03c.pdf 6.27) - -At the end of each session libburn inserts fake leadout entries into its TOC -model. Their start address is computed from the start and size of the last -track of the session. - - -------------------------------------------------------------------------------- -Hearsay about DVD-R/DL (Dual Layer) : - -DVD-R/DL can assume profile 0015h DVD-R Dual Layer Sequential which is supposed -to behave like DVD-R or 0016h DVD-R Dual Layer Jump which has no counterpart -with DVD-R. - -A half-sentence in mmc5r03c.pdf 6.3.3.3.3 might indicate that closing a session -by 5Bh CLOSE TRACK SESSION Close Function 010b overrides the multi-session bits -in mode page 05h. -growisofs applies this function in case of not DAO, though. A comment in -growisofs_mmc.cpp states: "// DVD-R DL Seq has no notion of multi-session". -I am not reading this from the specs - but not explicitely the contrary either. - -For now libburn will close the session but there is a macro prepared in -libburn/write.c Libburn_dvd_r_dl_multi_no_close_sessioN which will suppress -close session if multi-session is demanded. - - -------------------------------------------------------------------------------- - -------------------------------------------------------------------------------- - DVD+R[/DL] 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> - -------------------------------------------------------------------------------- - -Media type can be recognized by Current Profile from 46h GET CONFIGURATION. -(mmc5r03c.pdf 6.6.2.1) -DVD+R 001bh -DVD+R/DL 002bh - -- About empty, appendable and finalized DVD+R -- Writing a Pseudo Session to DVD+R -- DVD+R/DL (Dual Layer - -The following two chapters of the Sequential DVD-R[W] Cookbook are valid for -DVD+R media too: -- Obtaining DVD-R[W] multi-session info for extending ISO-9660 filesystems -- Obtaining a Table Of Content from DVD-R[W] - -------------------------------------------------------------------------------- -About blank, appendable and finalized DVD+R : - -In the beginning a DVD+R holds an empty session and the Incomplete Fragment. -From these one may spawn reserved fragments or one may write directly to -the incomplete fragment. As soon as this is done the empty session becomes the -open session which finally needs to get closed. By closing fragments and -session a new empty session with empty Incomplete Fragment gets spawned. -So the disc stays appendable. - -A DVD+R may hold 153 closed sessions with a single track each. -The open session may hold up to 15 open fragments. But on closure of the -session those fragments together form a single logical track. So one will -usually only use a single fragment for sequential writing. -(mmc5r03c.pdf 4.3.6.2) - -The disc may get finalized by another close command so that no more data can -be written. -(mmc5r03c.pdf 6.3.3.4.4) - - -------------------------------------------------------------------------------- -Writing a Pseudo Session to DVD+R : - -Session writing has to be pseudo because only one logical track per session -can be distinguished. So actually there have to be written multiple sessions -to mark multiple tracks. The pseudo session cannot get marked on disc and thus -the tracks of a pseudo session cannot be grouped accordingly in a TOC. - -Speed can be influenced by B6h SET STREAMING , speed capabilities can be -inquired by ACh GET PERFORMANCE. It is advised to set only speeds and sizes -which are returned by ACh. -(mmc5r03c.pdf 6.39 SET STREAMING, 6.8 GET PERFORMANCE) - -No mode page 05h is to be sent. -growisofs sends a page but the specs clearly state that one shall not do. -(mmc5r03c.pdf 7.5.3) - -It is optional wether a track size is reserved in advance or not. Eventually -this is done by 53h RESERVE TRACK, RMZ=ARSV=0. Reservation size should better -already be aligned to 32 KiB. -(mmc5r03c.pdf 6.31) -The specs promise to pad up the track if not enough data get written. -(mmc5r03c.pdf 6.3.3.4.2) - -Next Writeable Address is fetched from the reply of 52h READ TRACK INFORMATION -with track number FFh. -(mmc5r03c.pdf 6.27) -Since the fixely set write type is 16-block packet, full 32 kiB buffers have -to be transmitted via 2Ah WRITE. -(mmc5r03c.pdf 4.3.6.2.2) - -When writing is done, it is mandatory to force the drive's buffer to media by -35h SYNCHRONIZE CACHE. -(mmc5r03c.pdf 6.41) - -The written fragment (i.e. track-to-be) has to be closed by 5Bh CLOSE TRACK -SESSION Close Function 001b. -(mmc5r03c.pdf 6.3.3.4.2) -libburn obtains the necessary logical track number from Last Track Number in -Last Session from the reply of 51h READ DISC INFORMATION requesting -Data Type 000b. -(mmc5r03c.pdf 6.22) - -After each track 5Bh CLOSE TRACK SESSION Close Function 010b with Logical Track -Number 0 closes the DVD+R session but keeps the media appendable. -(mmc5r03c.pdf 6.3.3.4.3) -If the media shall not stay appendable then the last DVD+R session is to be -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. - - -------------------------------------------------------------------------------- -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 . - -------------------------------------------------------------------------------- - diff --git a/doc/ddlp.txt b/doc/ddlp.txt deleted file mode 100644 index 9211ea5..0000000 --- a/doc/ddlp.txt +++ /dev/null @@ -1,388 +0,0 @@ -------------------------------------------------------------------------------- - -Users of modern desktop Linux installations report misburns with CD/DVD -recording due to concurrency problems. - -This text describes two locking protocols which have been developed by our -best possible effort. But finally they rather serve as repelling example of -what would be needed in user space to achieve an insufficient partial solution. - -Ted Ts'o was so friendly to help as critic with his own use cases. It turned -out that we cannot imagine a way in user space how to cover reliably the needs -of callers of libblkid and the needs of our burn programs. - -------------------------------------------------------------------------------- -Content: - -The "Delicate Device Locking Protocol" shall demonstrate our sincere -consideration of the problem. - -"What are the Stumble Stones ?" lists reasons why the effort finally failed. - ------------------------------------------------------------------------------ - - - Delicate Device Locking Protocol - (a joint sub project of cdrkit and libburnia) - (contact: scdbackup@gmx.net ) - -Our projects provide programs which allow recording of data on CD or DVD. -We encounter an increasing number of bug reports about spoiled burn runs and -wasted media which obviously have one common cause: interference by other -programs which access the drive's device files. -There is some riddling about which gestures exactly are dangerous for -ongoing recordings or can cause weirdly misformatted drive replies to MMC -commands. -We do know, nevertheless, that these effects do not occur if no other program -accesses a device file of the drive while our programs use it. - -DDLP shall help to avoid collisions between programs in the process of -recording to a CD or DVD drive and other programs which access that drive. -The protocol intends to provide advisory locking. So any good-willing program -has to take some extra precautions to participate. - -If a program does not feel vulnerable to disturbance, then the precautions -impose much less effort than if the program feels the need for protection. - -Two locking strategies are specified: -DDLP-A operates on device files only. It is very Linux specific. -DDLP-B adds proxy lock files, inspired by FHS /var/lock standard. - - - DDLP-A - -This protocol relies on the hardly documented feature open(O_EXCL | O_RDWR) -with Linux device files and on POSIX compliant fcntl(F_SETLK). - -Other than the original meaning of O_EXCL with creating regular files, the -effect on device files is mutual exclusion of access. I.e. if one -filedescriptor is open on that combination of major-minor device number, then -no other open(O_EXCL) will succeed. But open() without O_EXCL would succeed. -So this is advisory and exclusive locking. -With kernel 2.6 it seems to work on all device drivers which might get used -to access a CD/DVD drive. - -The vulnerable programs shall not start their operation before they occupied a -wide collection of drive representations. -Non-vulnerable programs shall take care to detect the occupation of _one_ such -representation. - - So for Friendly Programs - -A program which does not feel vulnerable to disturbance is urged to access -CD/DVD drives by opening a file descriptor which will uphold the lock -as long as it does not get closed. There are two alternative ways to achieve -this. -Very reliable is - - open( some_path , O_EXCL | ...) - -But O_EXCL imposes restrictions and interferences: -- O_EXCL | O_RDONLY does not succeed with /dev/sg* ! -- O_EXCL cannot provide shared locks for programs which only want to lock - against burn programs but not against their own peers. -- O_EXCL keeps from obtaining information by harmless activities. -- O_EXCL already has a meaning with devices which are mounted as filesystems. - This priority meaning is more liberal than the one needed for CD/DV recording - protection. - -So it may be necessary to use a cautious open() without O_EXCL and to aquire -a POSIX lock via fcntl(). "Cautious" means to add O_NDELAY to the flags of -open(), because this is declared to avoid side effects within open(). - -With this gesture it is important to use the paths expected by our burn -programs: /dev/sr[0..255] /dev/scd[0..255] /dev/sg[0..255] /dev/hd[a..z] -because fcntl(F_SETLK) does not lock the device but only a device-inode. - - std_path = one of the standard device files: - /dev/sr[0..255] /dev/scd[0..255] /dev/sg[0..255] /dev/hd[a..z] - or a symbolic link pointing to one of them. - open( std_path , ... | O_NDELAY) - fcntl(F_SETLK) and close() on failure - ... eventually disable O_NDELAY by fcntl(F_SETFL) ... - -There is a pitfall mentioned in man 2 fcntl : - "locks are automatically released [...] if it closes any file descriptor - referring to a file on which locks are held. This is bad [...]" -So you may have to re-lock after some temporary fd got closed. - - - Vulnerable Programs - -For programs which do feel vulnerable, O_EXCL would suffice for the /dev/hd* -device file family and their driver. But USB and SATA recorders appear with -at least two different major-minor combinations simultaneously. -One as /dev/sr* alias /dev/scd*, the other as /dev/sg*. -The same is true for ide-scsi or recorders attached to SCSI controllers. - -So, in order to lock any access to the recorder, one has to open(O_EXCL) -not only the device file that is intended for accessing the recorder but also -a device file of any other major-minor representation of the recorder. -This is done via the SCSI address parameter vector (Host,Channel,Id,Lun) -and a search on standard device file paths /dev/sr* /dev/scd* /dev/sg*. -In this text the alternative device representations are called "siblings". - -For finding them, it is necessary to apply open() to many device files which -might be occupied by delicate operations. On the other hand it is very -important to occupy all reasonable representations of the drive. -So the reading of the (Host,Channel,Id,Lun) parameters demands an -open(O_RDONLY | O_NDELAY) _without_ fcntl() in order to find the outmost -number of representations among the standard device files. Only ioctls -SCSI_IOCTL_GET_IDLUN and SCSI_IOCTL_GET_BUS_NUMBER are applied. -Hopefully this gesture is unable to cause harmful side effects on kernel 2.6. - -At least one file of each class sr, scd and sg should be found to regard -the occupation as satisfying. Thus corresponding sr-scd-sg triplets should have -matching ownerships and access permissions. -One will have to help the sysadmins to find those triplets. - -A spicy detail is that sr and scd may be distinct device files for the same -major-minor combination. In this case fcntl() locks on both are needed -but O_EXCL can only be applied to one of them. - - -An open and free implementation ddlpa.[ch] is provided as - http://libburnia.pykix.org/browser/libburn/trunk/libburn/ddlpa.h?format=txt - http://libburnia.pykix.org/browser/libburn/trunk/libburn/ddlpa.c?format=txt -The current version of this text is - http://libburnia.pykix.org/browser/libburn/trunk/doc/ddlp.txt?format=txt - -Put ddlpa.h and ddlpa.c into the same directory and compile as test program by - cc -g -Wall -DDDLPA_C_STANDALONE -o ddlpa ddlpa.c - -Use it to occupy a drive's representations for a given number of seconds - ./ddlpa /dev/sr0 300 - -It should do no harm to any of your running activities. -If it does: Please, please alert us. - -Your own programs should not be able to circumvent the occupation if they -obey above rules for Friendly Programs. -Of course ./ddlpa should be unable to circumvent itself. - -A successfull occupation looks like - DDLPA_DEBUG: ddlpa_std_by_rdev("/dev/scd0") = "/dev/sr0" - DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/sr0" - DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/scd0" - DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/sg0" - DDLPA_DEBUG: ddlpa_occupy() : '/dev/scd0' - DDLPA_DEBUG: ddlpa_occupy() O_EXCL : '/dev/sg0' - DDLPA_DEBUG: ddlpa_occupy() O_EXCL : '/dev/sr0' - ---------------------------------------------- Lock gained - ddlpa: opened /dev/sr0 - ddlpa: opened siblings: /dev/scd0 /dev/sg0 - slept 1 seconds of 300 - -Now an attempt via device file alias /dev/NEC must fail: - DDLPA_DEBUG: ddlpa_std_by_rdev("/dev/NEC") = "/dev/sg0" - DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/sr0" - DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/scd0" - DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/sg0" - Cannot exclusively open '/dev/sg0' - Reason given : Failed to open O_RDWR | O_NDELAY | O_EXCL : '/dev/sr0' - Error condition : 16 'Device or resource busy' - -With hdc, of course, things are trivial - DDLPA_DEBUG: ddlpa_std_by_rdev("/dev/hdc") = "/dev/hdc" - DDLPA_DEBUG: ddlpa_occupy() O_EXCL : '/dev/hdc' - ---------------------------------------------- Lock gained - ddlpa: opened /dev/hdc - slept 1 seconds of 1 - - -Ted Ts'o provided program open-cd-excl which allows to explore open(2) on -device files with combinations of read-write, O_EXCL, and fcntl(). -(This does not mean that Ted endorsed our project yet. He helps exploring.) - -Friendly in the sense of DDLP-A would be any run which uses at least one of -the options -e (i.e. O_EXCL) or -f (i.e. F_SETLK, applied to a file -descriptor which was obtained from a standard device file path). -The code is available under GPL at - http://libburnia.pykix.org/browser/libburn/trunk/test/open-cd-excl.c?format=txt -To be compiled by - cc -g -Wall -o open-cd-excl open-cd-excl.c - -Options: - -e : open O_EXCL - -f : aquire lock by fcntl(F_SETLK) after sucessful open - -i : do not wait in case of success but exit 0 immediately - -r : open O_RDONLY , with -f use F_RDLCK - -w : open O_RDWR , with -f use F_WRLCK - plus the path of the devce file to open. - -Friendly Programs would use gestures like: - ./open-cd-excl -e -r /dev/sr0 - ./open-cd-excl -e -w /dev/sg1 - ./open-cd-excl -e -w /dev/black-drive - ./open-cd-excl -f -r /dev/sg1 - ./open-cd-excl -e -f -w /dev/sr0 - -Ignorant programs would use and cause potential trouble by: - ./open-cd-excl -r /dev/sr0 - ./open-cd-excl -w /dev/sg1 - ./open-cd-excl -f -w /dev/black-drive -where "/dev/black-drive" is _not_ a symbolic link to -any of /dev/sr* /dev/scd* /dev/sg* /dev/hd*, but has an own inode. - -Prone to failure without further reason is: - ./open-cd-excl -e -r /dev/sg1 - - ----------------------------------------------------------------------------- - - DDLP-B - -This protocol relies on proxy lock files in some filesystem directory. It can -be embedded into DDLP-A or it can be used be used standalone, outside DDLP-A. - -DDLP-A shall be kept by DDLP-B from trying to access any device file which -might already be in use. There is a problematic gesture in DDLP-A when SCSI -address parameters are to be retrieved. For now this gesture seems to be -harmless. But one never knows. -Vice versa DDLP-B may get from DDLP-A the service to search for SCSI device -file siblings. So they are best as a couple. - -But they are not perfect. Not even as couple. fcntl() locking is flawed. - - -There is a proxy file locking protocol described in FHS: - http://www.pathname.com/fhs/pub/fhs-2.3.html#VARLOCKLOCKFILES - -But it has shortcommings (see below). Decisive obstacle for its usage are the -possibility for stale locks and the lack of shared locks. - -DDLP-B rather defines a "path prefix" which is advised to be - /tmp/ddlpb-lock- -This prefix will get appended "device specific suffixes" and then form the path -of a "lockfile". -Not the existence of a lockfile but its occupation by an fcntl(F_SETLK) will -constitute a lock. Lockfiles may get prepared by the sysadmin in directories -where normal users are not allowed to create new files. Their rw-permissions -then act as additional access restriction to the device files. -The use of fcntl(F_SETLK) will prevent any stale locks after the process ended. -It will also allow to obtain shared locks as well as exclusive locks. - -There are two classes of device specific suffixes: - -- Device file path suffix. Absolute paths only. "/" gets replaced by "_-". - Eventual "_-" in path gets replaced by "_-_-". The leading group of "_-" - is always interpreted as a group of "/", though. E.g.: - /dev/sr0 <-> "_-dev_-sr0" - /mydevs/burner/nec <-> "_-mydevs_-burners_-nec" - /dev/rare_-name <-> "_-dev_-rare_-_-name" - ///strange/dev/x <-> "_-_-_-strange_-dev_-x" - -- st_rdev suffix. A hex representation of struct stat.st_rdev. Capital letters. - The number of characters is pare with at most one leading 0. I.e. bytewise - printf("%2.2X") beginning with the highest order byte that is not zero. - E.g. : "0B01", "2200", "01000000000004001" - -If a lockfile does not exist and cannot be created then this shall not keep -a program from working on a device. But if a lockfile exists and if permissions -or locking state do not allow to obtain a lock of the appropirate type, then -this shall prevent any opening of device file in question resp. shall cause -immediate close(2) of an already opened device file. - -The vulnerable programs shall not start their operation before they locked a -wide collection of drive representations. - -Non-vulnerable programs shall take care to lock the suffix resulting from the -path they will be using and the suffix from the st_rdev from that path. -The latter is to be obtained by call stat(2). - -Locks get upheld as long as their file descriptor is not closed or no other -incident as described in man 2 fcntl releases the lock. - -So with shared locks there are no imandatory further activities after they -have been obtained. - -In case of exclusive locks, the file has to have been opened for writing and -must be truncated to 0 bytes length immediately after obtaining the lock. -When releasing an exclusive lock it is a nice gesture to -already do this truncation. -Then a /var/lock/ compatible first line has to be written. -E.g. by: printf("%10u\n",(unsigned) getpid()) yielding " 1230\n". - -Any further lines are optional. They shall have the form Name=Value and must -be printable cleartext. If such further lines exist, then the last one must -have the name "endmark". -Defined Names are: - hostid =hostname of the machine where the process number of line 1 is valid - start =start time of lock in seconds since 1970. E.g: 1177147634.592410 - program =self chosen name of the program which obtained the lock - argv0 =argv[0] of that program - mainpath =device file path which will be used for operations by that program - path =device file path which lead to the lock - st_rdev =st_rdev suffix which is associated with path - scsi_hcil=eventual SCSI parameters Host,Channel,Id,Lun - scsi_bus =eventual SCSI parameter Bus - endmark =declares the info as complete. -Any undefined name or a line without "=" shall be handled as comment. -"=" in the value is allowed. Any line beginning with an "=" character is an -extension of the previous value. - -If programs encounter an exclusive lock, they are invited to read the content -of the lockfile anyway. But they should be aware that the info might be in the -progress of emerging. There is a race condition possible in the short time -between obtaining the exclusive lock and erasing the file content. -If it is not crucial to obtain most accurate info then one may take the newline -of the first line as indicator of a valid process number and the "endmark" -name as indicator that the preceding lines are valid. -Very cautious readers should obtain the info twice with a decent waiting period -inbetween. Only if both results are identical they should be considered valid. - - -There is no implementation of DDLP-B yet. - - - ----------------------------------------------------------------------------- -What are the Stumble Stones ? ----------------------------------------------------------------------------- - -Any of the considered locking mechanisms has decisive shortcommings -which keeps it from being the solution to all known legitimate use cases. - -The attempt has failed to compose a waterproof locking mechanism from means of -POSIX, FHS and from hardly documented Linux open(O_EXCL) on device files. -The resulting mechanisms would need about 1000 lines of code and still do -not close all gaps resp. cover the well motivated use cases. -This attempt you see above: DDLP-A and DDLP-B. - - -Summary of the reasons why the established locking mechanisms do not suffice: - -None of the mechanisms can take care of the double device driver identity -sr versus sg. To deduce the one device file from the other involves the need -to open many other (possibly unrelated) device files with the risk to disturb -them. -This hard to solve problem is aggravated by the following facts. - -Shortcommings of Linux specific open(O_EXCL) : - -- O_EXCL | O_RDONLY does not succeed with /dev/sg* -- O_EXCL cannot provide shared locks for programs which only want to lock - against burn programs but not against their own peers. -- O_EXCL keeps from obtaining information by harmless activities. -- O_EXCL already has a meaning with devices which are mounted as filesystems. - This priority meaning is more liberal than the one needed for CD/DV recording - protection. - -Shortcommings of POSIX fcntl(F_SETLK) : - -- fcntl() demands an open file descriptor. open(2) might have side effects. -- fcntl() locks can be released inadvertedly by submodules which just open and - close the same file (inode ?) without refering to fcntl locks in any way. - See man 2 fcntl "This is bad:". - Stacking of software modules is a widely used design pattern. But fcntl() - cannot cope with that. - -Shortcommings of FHS /var/lock/ : - -- Stale locks are possible. -- It is necessary to create a file (using the _old_ meaning of O_EXCL flag ?) - but /var/lock/ might not be available early during system start and it often - has restrictive permission settings. -- There is no way to indicate a difference between exclusive and shared locks. -- The FHS prescription relies entirely on the basename of the device file path. - diff --git a/doc/doxygen.conf.in b/doc/doxygen.conf.in deleted file mode 100644 index e36d601..0000000 --- a/doc/doxygen.conf.in +++ /dev/null @@ -1,1300 +0,0 @@ -# Doxyfile 1.5.3 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file that -# follow. The default is UTF-8 which is also the encoding used for all text before -# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into -# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of -# possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = @PACKAGE_NAME@ - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = @PACKAGE_VERSION@ - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, -# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, -# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, -# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = @top_srcdir@ - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = YES - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = YES - -# If the DETAILS_AT_TOP tag is set to YES then Doxygen -# will output the detailed description near the top, like JavaDoc. -# If set to NO, the detailed description appears after the member -# documentation. - -DETAILS_AT_TOP = YES - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 4 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = YES - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for Java. -# For instance, namespaces will be presented as packages, qualified scopes -# will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to -# include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = YES - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = YES - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = YES - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be extracted -# and appear in the documentation as a namespace called 'anonymous_namespace{file}', -# where file will be replaced with the base name of the file that contains the anonymous -# namespace. By default anonymous namespace are hidden. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = NO - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from the -# version control system). Doxygen will invoke the program by executing (via -# popen()) the command <command> <input-file>, where <command> is the value of -# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = YES - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text " - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = libburn \ - doc \ - test - -# This tag can be used to specify the character encoding of the source files that -# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default -# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. -# See http://www.gnu.org/software/libiconv for the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py - -FILE_PATTERNS = libburn.h \ - comments \ - libburner.c - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = NO - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the output. -# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, -# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = test - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command <filter> <input-file>, where <filter> -# is the value of the INPUT_FILTER tag, and <input-file> is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH -# then you must also enable this option. If you don't then doxygen will produce -# a warning and turn it on anyway - -SOURCE_BROWSER = YES - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = YES - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = NO - -# If the REFERENCED_BY_RELATION tag is set to YES (the default) -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = YES - -# If the REFERENCES_RELATION tag is set to YES (the default) -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = YES - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. Otherwise they will link to the documentstion. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = NO - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = OB \ - OTK \ - _ - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = doc/html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be -# generated containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, -# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are -# probably better off using the HTML help feature. - -GENERATE_TREEVIEW = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 200 - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = letter - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = YES - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = NO - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. This is useful -# if you want to understand what is going on. On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = DOXYGEN - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to -# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to -# specify the directory where the mscgen tool resides. If left empty the tool is assumed to -# be found in the default search path. - -MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = YES - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will -# generate a call dependency graph for every global function or class method. -# Note that enabling this option will significantly increase the time of a run. -# So in most cases it will be better to enable call graphs for selected -# functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will -# generate a caller dependency graph for every global function or class method. -# Note that enabling this option will significantly increase the time of a run. -# So in most cases it will be better to enable caller graphs for selected -# functions only using the \callergraph command. - -CALLER_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = NO - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the number -# of direct children of the root node in a graph is already larger than -# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, which results in a white background. -# Warning: Depending on the platform used, enabling this option may lead to -# badly anti-aliased labels on the edges of a graph (i.e. they become hard to -# read). - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = NO - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO diff --git a/libburn-1.pc.in b/libburn-1.pc.in deleted file mode 100644 index e3bf784..0000000 --- a/libburn-1.pc.in +++ /dev/null @@ -1,12 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: libburn -Description: Library to read/write optical discs -Version: @VERSION@ -Requires: -Libs: -L${libdir} -lburn -Libs.private: @THREAD_LIBS@ @LIBBURN_ARCH_LIBS@ -Cflags: -I${includedir}/libburn diff --git a/libburn/Makefile b/libburn/Makefile deleted file mode 100644 index 062350d..0000000 --- a/libburn/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -all clean: - $(MAKE) -C .. -$(MAKEFLAGS) $@ - -.PHONY: all clean diff --git a/libburn/Makefile.am b/libburn/Makefile.am deleted file mode 100644 index 144ece7..0000000 --- a/libburn/Makefile.am +++ /dev/null @@ -1,65 +0,0 @@ -pkgconfigdir=$(libdir)/pkgconfig -libincludedir=$(includedir)/libburn - -lib_LTLIBRARIES = libburn.la - -libburn_la_SOURCES = \ - async.c \ - async.h \ - crc.c \ - crc.h \ - debug.c \ - debug.h \ - drive.c \ - drive.h \ - file.c \ - file.h \ - init.c \ - init.h \ - lec.c \ - lec.h \ - message.c \ - message.h \ - mmc.c \ - mmc.h \ - null.c \ - null.h \ - options.c \ - options.h \ - read.c \ - read.h \ - sbc.c \ - sbc.h \ - sector.c \ - sector.h \ - sg.c \ - sg.h \ - spc.c \ - spc.h \ - source.h \ - source.c \ - structure.c \ - structure.h \ - toc.c \ - toc.h \ - transport.h \ - util.c \ - util.h \ - write.c \ - write.h - -libinclude_HEADERS = libburn.h - -## ========================================================================= ## -indent_files = $(libburn_la_SOURCES) - -indent: $(indent_files) - indent -bad -bap -nbbb -nbbo -nbc -bli0 -br -bls \ - -cdw -ce -cli0 -ncs -nbfda -i8 -l79 -lc79 \ - -lp -saf -sai -nprs -npsl -saw -sob -ss -ut \ - -sbi0 -nsc -ts8 -npcs -ncdb -fca \ - $^ - -.PHONY: indent - -## ========================================================================= ## diff --git a/libburn/asserts.txt b/libburn/asserts.txt deleted file mode 100644 index b079158..0000000 --- a/libburn/asserts.txt +++ /dev/null @@ -1,792 +0,0 @@ -List of assert() calls in libburn. 6 Oct 2006. - -Format: - ------------------------------------------------------------------------------- - - Number) grep'ed line - (++ before number means: is fully done, + means is done so far ) -function(): -Description of abort condition. - -Possible callers and their relation to the abort condition. - -: Error Evaluation -=> Consequences - -Eventual implementation timestamp - ------------------------------------------------------------------------------- - -++ 1) libburn/async.c: assert(a != NULL); /* wasn't found.. this should not be possible */ -static remove_worker(): -A thread describing structure (struct w_list) could not be found in -order to be released. - -Called by API burn_drive_scan() -Called by static erase_worker_func() , thread under API burn_disc_erase() -Called by static write_disc_worker_func(), thread under API burn_disc_write() -All three want to clean up after they are done. - -: Severe Libburn Error -=> issue LIBDAX_MSGS_SEV_WARNING - -ts A61006 - ------------------------------------------------------------------------------- - -++ 2) libburn/async.c: assert(!(workers && workers->drive)); -API burn_drive_scan(): -Before spawning a thread, the function refuses work because another -drive activity is going on. - -: Severe Application Error -=> return -1; redefine @return in API , issue LIBDAX_MSGS_SEV_SORRY - -ts A61006 - ------------------------------------------------------------------------------- - -+ 3) libburn/async.c: assert(workers == NULL); -API burn_drive_scan(): -After thread is done and remover_worker() succeeded, there is still a -worker registered. Shall probably detect roguely appeared burn or -erase runs. (I consider to install a mutex shielded function for that.) - -: Severe Libburn Error -=> Same as 1) - -ts A61006 - ------------------------------------------------------------------------------- - -++ 4) libburn/async.c: assert(drive); - libburn/async.c: assert(!SCAN_GOING()); - libburn/async.c: assert(!find_worker(drive)); -API burn_disc_erase(): -Wants to see a drive (assumes NULL == 0), wants to see no scan and -wants to see no other worker on that drive. I.e. this would tolerate -a parallel activity on another drive. - -: Severe Application Error -=> (no return value), issue LIBDAX_MSGS_SEV_SORRY - -ts A61006 - ------------------------------------------------------------------------------- - -++ 5) libburn/async.c: assert(!SCAN_GOING()); - libburn/async.c: assert(!find_worker(opts->drive)); -API burn_disc_write(): -Same as 4) - -: Severe Application Error -=> Same as 4) - -ts A61006 - ---------------------------------------------------------------------- - -++ 6) libburn/drive.c: assert(d->busy == BURN_DRIVE_IDLE); -API burn_drive_release(): -A drive is not idle on release. - -: Severe Application Error -=> Same as 4) - -ts A61007 - ------------------------------------------------------------------------------- - -++ 7) libburn/drive.c: assert(d->released); -burn_wait_all() -A drive is found grabbed. - -Called by burn_drive_scan_sync(), thread under API burn_drive_scan() -Called by API burn_finish - -: Severe Application Error -=> rename and redefine burn_wait_all() : now burn_drives_are_clear() -=> change all use of burn_wait_all() -=> Move tests up to burn_drive_scan() -=> There: return -1; issue LIBDAX_MSGS_SEV_SORRY - -ts A61007 - ------------------------------------------------------------------------------- - -++ 8) libburn/drive.c: assert(!d->released); -API burn_disc_get_status() -Attempt to read status of non-grabbed drive. - -: Severe Application Error -=> extend enum burn_disc_status by BURN_DISC_UNGRABBED -=> return BURN_DISC_UNGRABBED, issue LIBDAX_MSGS_SEV_SORRY - -ts A61007 - ------------------------------------------------------------------------------- - -++ 9) libburn/drive.c: assert( /* (write_type >= BURN_WRITE_PACKET) && */ -burn_drive_get_block_types(): -Will not work on BURN_WRITE below BURN_WRITE_RAW. - -Called by -nobody- ? - -: Severe Application Error -=> inactivate unused function - -ts A61007 - ------------------------------------------------------------------------------- - -++ 10) libburn/drive.c: assert(d->idata); - libburn/drive.c: assert(d->mdata); -static drive_getcaps(): -sg.c:enumerate_common() did not succeed in creating a proper struct burn_drive -Called by burn_drive_scan_sync() - -: Severe System Error -=> This could possibly really stay an abort() because the reason is - a plain failure of the system's memory management. -=> Detect this failure already in enumerate_common(), - issue LIBDAX_MSGS_SEV_FATAL, return - -ts A61007 - ------------------------------------------------------------------------------- - -++ 11) libburn/drive.c: assert(burn_running); -burn_drive_scan_sync(): -The library was not initialized. - -Called as thread by API burn_drive_scan() - -: Severe Application Error -=> Move this test up to burn_drive_scan() -=> There: return -1; redefine @return in API , issue LIBDAX_MSGS_SEV_FATAL - -ts A61007 - ------------------------------------------------------------------------------- - -++ 12) libburn/drive.c: assert(d->released == 1); -burn_drive_scan_sync(): -Inactivated - -: (Severe Application Error) -=> throw out inactivated code - -ts A61007 - ------------------------------------------------------------------------------- - -++ 13) libburn/drive.c: assert(strlen(d->devname) < BURN_DRIVE_ADR_LEN); -burn_drive_raw_get_adr(): -An enumerated device address is longer than the API's maximum length - -Called by API burn_drive_get_adr() -Called by API burn_drive_obtain_scsi_adr() - -: Severe Libburn Error -=> return -1; in all three functions, enhance burn_drive_get_adr @return docs -=> issue LIBDAX_MSGS_SEV_SORRY - -ts A61007 - ------------------------------------------------------------------------------- - -++ 14) libburn/drive.c: assert(drive_info->drive!=NULL); -API burn_drive_get_adr(): -Drive info has no drive attached. - -: Severe Libburn Error (unlikely, will eventually SIGSEGV on NULL) -=> delete assert - -ts A61007 - ------------------------------------------------------------------------------- - -++ 15) libburn/init.c: assert(burn_running); -API burn_finish(): -The library is not initialized - -: Severe Application Error -=> return (assume no msg system) - -ts A61007 - ------------------------------------------------------------------------------- - -++ 16) libburn/init.c: assert(burn_running); -API burn_preset_device_open(): -The library is not initialized - -: Severe Application Error -=> return (assume no msg system) - -ts A61007 - ------------------------------------------------------------------------------- - -++ 17) libburn/mmc.c: assert(o->drive == d); -mmc_close_disc(): -alias: struct burn_drive.close_disc() -Parameters struct burn_drive and struct burn_write_opts do not match - -Called by -nobody- ? - -( => Disable unused function ? ) -=> removed redundant parameter struct burn_drive - -ts A61009 - ------------------------------------------------------------------------------- - -++ 18) libburn/mmc.c: assert(o->drive == d); -mmc_close_session(): -Same as 17) -alias: struct burn_drive.close_session() - -Called by -nobody- ? - -( => Disable unused function ? ) -=> removed redundant parameter struct burn_drive - -ts A61009 - ------------------------------------------------------------------------------- - -++ 19) libburn/mmc.c: assert(buf->bytes >= buf->sectors); /* can be == at 0... */ -mmc_write_12(): -- Unclear what .bytes and .sectors mean in struct buffer - - -Called by -nobody- ? - -=> problems with filling the write buffer have to be handled by callers -=> delete assert - -ts A61009 - ------------------------------------------------------------------------------- - -++ 20) libburn/mmc.c: assert(buf->bytes >= buf->sectors); /* can be == at 0... */ -mmc_write(): -- Unclear what .bytes and .sectors mean in struct buffer - - -libburn/mmc.c: c.page->sectors = errorblock - start + 1; -mmc_read_sectors() by toc_find_modes() by mmc_read_toc() alias drive.read_toc() -by burn_drive_grab() -This seems to be unrelated to mmc_write(). - -libburn/sector.c: out->sectors++; -get_sector() -Seems to hand out sector start pointer in opts->drive->buffer -and to count reservation transactions as well as reserved bytes. -Ensures out->bytes >= out->sectors - - -libburn/mmc.c: c.page->bytes = s->count * 8; -mmc_send_cue_sheet() -Does not use mmc_write() but directly (sg_)issue_command() - -libburn/sector.c: out->bytes += seclen; -get_sector() -See above -Ensures out->bytes >= out->sectors - -libburn/spc.c: c.page->bytes = 8 + 2 + d->mdata->retry_page_length; -spc_select_error_params() -Does not use mmc_write() but directly (sg_)issue_command() - -libburn/spc.c: c.page->bytes = 8 + 2 + d->mdata->write_page_length; -spc_select_error_params() -Does not use mmc_write() but directly (sg_)issue_command() - -libburn/spc.c: c.page->bytes = 8 + 2 + 0x32; -spc_probe_write_modes() -Does not use mmc_write() but directly (sg_)issue_command() - -alias struct burn_drive.write() -Called by static get_sector, by many -Called by burn_write_flush -Called by burn_write_track - -=> problems with filling the write buffer have to be handled by callers -=> delete assert - -ts A61009 - ------------------------------------------------------------------------------- - -++ 21) libburn/mmc.c: assert(((dlen - 2) % 11) == 0); -mmc_read_toc(): -- Is defunct - - -=> :) - -ts A61009 - ------------------------------------------------------------------------------- - -++ 22) libburn/mmc.c: assert(len >= 0); -mmc_read_sectors(): -Catches a bad parameter - -alias: struct burn_drive.read_sectors() -Called by API burn_disc_read() , - is defunct -, one could catch the problem -Called by toc_find_modes(), problem cannot occur: mem.sectors = 1; - -: Severe Libburn Error -(=> in burn_disc_read() check page.sectors before d->read_sectors() ) -=> :) - -ts A61009 - ------------------------------------------------------------------------------- - -++ 23) libburn/mmc.c: assert(d->busy); -mmc_read_sectors(): -Catches use of a drive that is not marked as busy - -alias: struct burn_drive.read_sectors() -Called by API burn_disc_read() , - is defunct -, busy = BURN_DRIVE_READING; -Called by toc_find_modes(), does the same assert. To be solved there. - -: Severe Libburn Error -=> :) - -ts A61009 - ------------------------------------------------------------------------------- - -++ 24) libburn/options.c: assert(0); -API burn_write_opts_set_write_type(): -Detects unsuitable enum burn_write_types write_type and int block_type. -API promises return 0 on failure - -: Severe Application Error -=> issue LIBDAX_MSGS_SEV_SORRY -=> should also detect problem of 26) : wrong write_type,block_type combination - by calling sector_get_outmode() and checking for -1 -=> should also detect problem of 41) : unknown block_type - by spc_block_type() and checking for -1 -=> delete assert(0) - -ts A61007 - ------------------------------------------------------------------------------- - -++ 25) libburn/read.c: assert((o->version & 0xfffff000) == (OPTIONS_VERSION & 0xfffff000)); - libburn/read.c: assert(!d->busy); - libburn/read.c: assert(d->toc->valid); - libburn/read.c: assert(o->datafd != -1); -API burn_disc_read(): -- ? - - -burn_disc_read() is defunct -OPTIONS_VERSION does not occur outside this line - -( => one would return ) -( 22) => catch page.sectors<0 before d->read_sectors() ) -( 37) => catch ! d->mdata->valid ) -=> :) - -ts A61007 - ------------------------------------------------------------------------------- - -++ 26) libburn/sector.c: assert(0); /* return BURN_MODE_UNIMPLEMENTED :) */ -static get_outmode(): -burn_write_opts is wrongly programmed with .write_type and .block_type - -: Severe Application Error -=> This gets handled by burn_write_opts_set_write_type() - ts A61007 by new semi-public sector_get_outmode() -=> delete assert() - -ts A61007 - ------------------------------------------------------------------------------- - -++ 27) libburn/sector.c: assert(outlen >= inlen); - libburn/sector.c: assert(outmode & BURN_MODE_RAW); - libburn/sector.c: assert(offset != -1); -static convert_data(): -Several unacceptable settings within struct burn_write_opts - -Called by sector_toc() sector_pregap() sector_postgap() sector_lout() - sector_data() - -: Severe Application Error -=> change return type of convert_data() -=> all callers interpret return value and eventually return failure - -ts A61007 - ------------------------------------------------------------------------------- - -++ 28) libburn/sector.c: assert(0); -static char_to_isrc(): -Called by subcode_user() with data set by API burn_track_set_isrc() -Some character conversion fails on wrong input - -: Severe Application Error -=> burn_track_set_isrc() has to make sure that only good data are set -=> char_to_isrc() returns 0 as default -=> delete assert() - -ts A61008 - ------------------------------------------------------------------------------- - -++ 29) libburn/sector.c: assert(qmode == 1 || qmode == 2 || qmode == 3); -subcode_user(): -- can not happen - - -: Unknown reason of assert() -=> remove assert() - -ts A61010 - ------------------------------------------------------------------------------- - -++ 30) libburn/sector.c: assert(modebyte == 1); -sector_headers(): -Does only accept modes BURN_AUDIO, BURN_MODE1 or write_type BURN_WRITE_SAO - -Called by sector_toc() sector_pregap() sector_postgap() sector_lout() - sector_data() - -: Severe Libburn Error -=> new functions sector_headers_is_ok(), burn_disc_write_is_ok() - help to catch problem in API burn_disc_write() -=> issue LIBDAX_MSGS_SEV_FATAL - -ts A61009 - ------------------------------------------------------------------------------- - -++ 31) libburn/sector.c: assert(0); -process_q() -- defunct - - -=> :) - -ts A61009 - ------------------------------------------------------------------------------- - -++ 32) libburn/sg.c: assert("drive busy" == "non fatal"); -sg_handle_busy_device(): -Intentional abort preset by the app - -=> change to abort() - -ts A61007 - ------------------------------------------------------------------------------- - -++ 33) libburn/sg.c: assert(fd != -1337); -sg_grab(): -The drive device file could not be opened - -:Severe External Problem -=> obsolete by normal drive open failure handling - -ts A61007 - ------------------------------------------------------------------------------- - -++ 34) libburn/sg.c: assert(!c->page); -sg_issue_command(): -An SCSI command of direction NO_TRANSFER may not have a .page != NULL. - -Since it is about exposing a libburn detail towards the sg driver, i believe -it is sufficient to just not use it. - -: Libburn Error -=> enhance internal logics of sg_issue_command() - -ts A61007 - ------------------------------------------------------------------------------- - -++ 35) libburn/sg.c: assert(c->page->bytes > 0); -sg_issue_command(): -An SCSI command of direction TO_DRIVE wants to transfer 0 bytes. - -: Severe Libburn Error -=> set command.error = 1 and return 0 - -ts A61010 - ------------------------------------------------------------------------------- - -++ 36) libburn/sg.c: assert(err != -1); -sg_issue_command(): -The transfer of the command via ioctl() failed - -: Severe Transport Level Problem -=> close drive fd, set idle and released -=> set command.error = 1 and return -1 - -ts A61010 - ------------------------------------------------------------------------------- - -++ 37) libburn/spc.c: assert(d->mdata->valid); -spc_select_error_params(): -Drive was not properly programmed - -alias struct burn_drive.send_parameters() -Called by burn_disc_read, - defunct - - -: Severe Application Error -=> moved up as mangled assert to burn_disc_read() - -ts A61007 - ------------------------------------------------------------------------------- - -++ 38) libburn/spc.c: assert(d->mdata->cdr_write || d->mdata->cdrw_write || -spc_sense_write_params(): -Drive does not offer write of any known media type - -alias struct burn_drive.read_disc_info() -Called by API burn_drive_grab (assert test made there in soft) - -: Severe Command Level Problem -=> remove assert() - -ts A61007 - ------------------------------------------------------------------------------- - -++ 39) libburn/spc.c: assert(o->drive == d); -spc_select_write_params(): -Drive does not match struct burn_write_opts - -alias struct burn_drive.send_write_parameters() -Called by mmc_close_disc() (-defunct- ?), mmc_close_session() (-defunct- ?), - burn_write_track() (d = o->drive;), - burn_disc_write_sync() d = (o->drive;) - -: Severe Libburn Error -=> remove assert() - -ts A61007 - ------------------------------------------------------------------------------- - -++ 40) libburn/spc.c: assert(d->mdata->valid); -spc_select_write_params(): -Drive was not properly programmed - -Called by (see 39) - burn_write_track() by burn_write_session() by burn_disc_write_sync() - burn_disc_write_sync() indirectly by API burn_disc_write() - -: Severe Libburn Error -=> caught in burn_disc_write() now - -ts A61007 - ------------------------------------------------------------------------------- - -++ 41) libburn/spc.c: assert(0); -spc_block_type(): -Unknown value with enum burn_block_types - -Called by spc_select_write_params, uses burn_write_opts.block_type, - set by API burn_write_opts_set_write_type() - -: Severe Application Error -=> catch in API burn_write_opts_set_write_type - by calling spc_block_type() -=> delete assert - -ts A61007 - ------------------------------------------------------------------------------- - -++ 42) libburn/structure.c: assert(!(pos > BURN_POS_END));\ -macro RESIZE -An illegal list index is given by the app. - -( TO->NEW##s obviusly means to append "s" to cpp result of TO->NEW ) -Used by API burn_session_add_track() and API burn_disc_add_session() - -: Severe Application Error -=> replace assert by if-and-return-0 - -ts A61008 - ------------------------------------------------------------------------------- - -++ 43) libburn/structure.c: assert(s->track != NULL); -API burn_session_remove_track() -An application supplied pointer is NULL - -: Severe Application Error -=> replace by if-and-return-0 - -ts A61008 - ------------------------------------------------------------------------------- - -++ 44) libburn/structure.c: assert((country[i] >= '0' || country[i] < '9') && - libburn/structure.c: assert((owner[i] >= '0' || owner[i] < '9') && - libburn/structure.c: assert(year <= 99); - libburn/structure.c: assert(serial <= 99999); -API burn_track_set_isrc(): -Illegal texts supplied by application. -The logical expression is always true ! - -: Severe Application Error -=> issue LIBDAX_MSGS_SEV_SORRY and return -=> delete assert -=> delete assert 28) in char_to_isrc() - -ts A61008 - ------------------------------------------------------------------------------- - -++ 45) libburn/toc.c: assert(0); /* unhandled! find out ccd's -static write_clonecd2(): - - - defunct -, - unused - - -=> mangle assert - -ts A61008 - ------------------------------------------------------------------------------- - -++ 46) libburn/toc.c: assert(d->busy); -toc_find_modes(): -The drive to work on is not marked busy - -Called by mmc_read_toc() alias read_toc() by ... burn_drive_grab() - -: Severe Libburn Error -=> to be prevented on the higher levels -=> delete assert - -ts A61008 - ------------------------------------------------------------------------------- - -++ 47) libburn/util.c: assert(s); -burn_strdup() -Abort on NULL string which would elsewise cause a SIGSEGV - -Used once in enumerate_common() with a string that worked with open(2) before - -: Severe Libburn Error -=> delete assert - -ts A61008 - ------------------------------------------------------------------------------- - -++ 48) libburn/util.c: assert(s); -burn_strndup(): - unused - -Same as 47 - -: Severe Libburn Error -=> return NULL -=> delete assert - -ts A61008 - ------------------------------------------------------------------------------- - -++ 49) libburn/util.c: assert(n > 0); -burn_strndup(): - unused - -Prevent problems by negative copy length - -: Severe Libburn Error -=> return NULL -=> delete assert - -ts A61008 - ------------------------------------------------------------------------------- - -++ 50) libburn/write.c: assert(0); -static type_to_ctrl(): -Unsuitable mode to be converted into "ctrl" -Called by static type_to_form() finally burn_create_toc_entries() - -: Severe Application Error -=> to be caught in burn_track_define_data by calling for test type_to_form() -=> return -1; - -ts A61008 - ------------------------------------------------------------------------------- - -++ 51) libburn/write.c: assert(0); - libburn/write.c: assert(0); /* XXX someone's gonna want this sometime */ -static type_to_form(): -Does not like BURN_MODE0 or BURN_MODE2 but tolerates unknown modes - -Called by static burn_create_toc_entries() by burn_disc_write_sync() - -: Undocumented Libburn Restriction -=> set *form = -1 , *ctladr = 0xff , return -=> make function non-static -=> call for test in API burn_track_define_data() - -ts A61009 - ------------------------------------------------------------------------------- - -++ 52) libburn/write.c: assert(ptr); -static add_cue(): -realloc() failed - -Called by burn_create_toc_entries() by burn_disc_write_sync() -(burn_create_toc_entries is ignorant towards own potential memory problems) -(This could possibly really stay an abort() because the reason is - a plain failure of the system's memory management.) - -: Severe System Error -=> change return type of add_cue to int -=> react on return -1 in burn_create_toc_entries, return NULL on failure -=> abort burn_disc_write_sync() on NULL return - -ts A61009 - ------------------------------------------------------------------------------- - -++ 53) libburn/write.c: assert(d->toc_entry == NULL); -burn_create_toc_entries(): -Multiple usage of struct burn_drive.toc_entry - -Called by burn_disc_write_sync() -This will probably trigger an abort with disc->sessions > 1 -(disc->sessions is incremented in macro RESIZE() as "NEW##s") - -: Design Problem -( => ? disallow multiple sessions ? ) -=> replace assert by soft means and wait what happens - -ts A61009 - ------------------------------------------------------------------------------- - -++ 54) libburn/write.c: assert(0); -burn_sector_length(): -Only BURN_AUDIO, BURN_MODE_RAW, BURN_MODE1 are allowed - -Called by get_sector(), convert_data(), ... - -=> call burn_sector_length() for test in API burn_track_define_data() -=> replace assert by -1 - -ts A61009 - ------------------------------------------------------------------------------- - diff --git a/libburn/async.c b/libburn/async.c deleted file mode 100644 index 4881d64..0000000 --- a/libburn/async.c +++ /dev/null @@ -1,545 +0,0 @@ -/* -*- 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" -#include "write.h" -#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> - -/* -#include <a ssert.h> -*/ -#include "libdax_msgs.h" -extern struct libdax_msgs *libdax_messenger; - -#define SCAN_GOING() (workers && !workers->drive) - -typedef void *(*WorkerFunc) (void *); - -struct scan_opts -{ - struct burn_drive_info **drives; - unsigned int *n_drives; - - int done; -}; - -struct erase_opts -{ - struct burn_drive *drive; - int fast; -}; - -/* ts A61230 */ -struct format_opts -{ - struct burn_drive *drive; - off_t size; - int flag; -}; - -struct write_opts -{ - struct burn_drive *drive; - struct burn_write_opts *opts; - struct burn_disc *disc; -}; - -struct fifo_opts -{ - struct burn_source *source; - int flag; -}; - - -struct w_list -{ - struct burn_drive *drive; - pthread_t thread; - - struct w_list *next; - - union w_list_data - { - struct scan_opts scan; - 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 *find_worker(struct burn_drive *d) -{ - struct w_list *a; - - for (a = workers; a; a = a->next) - if (a->drive == d) - return a; - return NULL; -} - -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->drive = d; - a->u = *(union w_list_data *)data; - - /* insert at front of the list */ - a->next = workers; - tmp = workers; - workers = a; - - if (d != NULL) - 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)) { - 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; - } - - /* ts A61006 */ - /* a ssert(a != NULL);/ * wasn't found.. this should not be possible */ - if (a == NULL) - libdax_msgs_submit(libdax_messenger, -1, 0x00020101, - LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH, - "remove_worker() cannot find given worker item", 0, 0); -} - -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; - return NULL; -} - -int burn_drive_scan(struct burn_drive_info *drives[], unsigned int *n_drives) -{ - struct scan_opts o; - int ret = 0; - - /* ts A61006 : moved up from burn_drive_scan_sync , former Assert */ - if (!burn_running) { - libdax_msgs_submit(libdax_messenger, -1, 0x00020109, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "Library not running (on attempt to scan)", 0, 0); - *drives = NULL; - *n_drives = 0; - return -1; - } - - /* cant be anything working! */ - - /* ts A61006 */ - /* a ssert(!(workers && workers->drive)); */ - if (workers != NULL && workers->drive != NULL) { -drive_is_active:; - libdax_msgs_submit(libdax_messenger, -1, 0x00020102, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "A drive operation is still going on (want to scan)", - 0, 0); - *drives = NULL; - *n_drives = 0; - return -1; - } - - if (workers == NULL) { - /* 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)) - goto drive_is_active; - *drives = NULL; - *n_drives = 0; - - o.drives = drives; - o.n_drives = n_drives; - o.done = 0; - add_worker(NULL, (WorkerFunc) scan_worker_func, &o); - } else if (workers->u.scan.done) { - /* its done */ - ret = workers->u.scan.done; - remove_worker(workers->thread); - - /* ts A61006 */ - /* a ssert(workers == NULL); */ - if (workers != NULL) { - libdax_msgs_submit(libdax_messenger, -1, 0x00020101, - LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH, - "After scan a drive operation is still going on", - 0, 0); - return -1; - } - - } else { - /* still going */ - } - return ret; -} - -static void *erase_worker_func(struct w_list *w) -{ - burn_disc_erase_sync(w->u.erase.drive, w->u.erase.fast); - remove_worker(pthread_self()); - return NULL; -} - -void burn_disc_erase(struct burn_drive *drive, int fast) -{ - struct erase_opts o; - - /* ts A61006 */ - /* a ssert(drive); */ - /* a ssert(!SCAN_GOING()); */ - /* a ssert(!find_worker(drive)); */ - if((drive == NULL)) { - libdax_msgs_submit(libdax_messenger, drive->global_index, - 0x00020104, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "NULL pointer caught in burn_disc_erase", 0, 0); - return; - } - if ((SCAN_GOING()) || find_worker(drive)) { - libdax_msgs_submit(libdax_messenger, drive->global_index, - 0x00020102, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "A drive operation is still going on (want to erase)", - 0, 0); - return; - } - /* 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 && - drive->status != BURN_DISC_FULL) - || - (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, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Drive and media state unsuitable for blanking", - 0, 0); - return; - } - - o.drive = drive; - o.fast = fast; - add_worker(drive, (WorkerFunc) erase_worker_func, &o); -} - - -/* ts A61230 */ -static void *format_worker_func(struct w_list *w) -{ - burn_disc_format_sync(w->u.format.drive, w->u.format.size, - w->u.format.flag); - remove_worker(pthread_self()); - return NULL; -} - - -/* ts A61230 */ -void burn_disc_format(struct burn_drive *drive, off_t size, int flag) -{ - struct format_opts o; - int ok = 0; - char msg[160]; - - if ((SCAN_GOING()) || find_worker(drive)) { - libdax_msgs_submit(libdax_messenger, drive->global_index, - 0x00020102, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "A drive operation is still going on (want to format)", - 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 */ - - if (drive->current_profile == 0x14) - ok = 1; /* DVD-RW sequential */ - else if (drive->current_profile == 0x13 && (flag & 16)) - ok = 1; /* DVD-RW Restricted Overwrite with force bit */ - else if (drive->current_profile == 0x1a) { - ok = 1; /* DVD+RW */ - 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) { - sprintf(msg,"Will not format media type %4.4Xh", - drive->current_profile); - libdax_msgs_submit(libdax_messenger, drive->global_index, - 0x00020129, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - drive->cancel = 1; - return; - } - o.drive = drive; - o.size = size; - o.flag = flag; - 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 - */ - burn_write_opts_free(w->u.write.opts); - - remove_worker(pthread_self()); - return NULL; -} - -void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc) -{ - struct write_opts o; - char reasons[BURN_REASONS_LEN+80]; - - /* ts A61006 */ - /* a ssert(!SCAN_GOING()); */ - /* a ssert(!find_worker(opts->drive)); */ - if ((SCAN_GOING()) || find_worker(opts->drive)) { - libdax_msgs_submit(libdax_messenger, opts->drive->global_index, - 0x00020102, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "A drive operation is still going on (want to write)", - 0, 0); - return; - } - - /* For the next lines any return indicates failure */ - opts->drive->cancel = 1; - - /* ts A70203 : people have been warned in API specs */ - if (opts->write_type == BURN_WRITE_NONE) - return; - - if (opts->drive->drive_role == 0) { - 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); - return; - } - - /* ts A61007 : obsolete Assert in spc_select_write_params() */ - if (opts->drive->drive_role == 1 && !opts->drive->mdata->valid) { - libdax_msgs_submit(libdax_messenger, - opts->drive->global_index, 0x00020113, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Drive capabilities not inquired yet", 0, 0); - return; - } - - /* ts A70219 : intended to replace all further tests here and many - tests in burn_*_write_sync() - */ - strcpy(reasons, "Write job parameters are unsuitable:\n"); - if (burn_precheck_write(opts, disc, reasons + strlen(reasons), 1) - == BURN_WRITE_NONE) { - libdax_msgs_submit(libdax_messenger, - opts->drive->global_index, 0x00020139, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - reasons, 0, 0); - return; - } - - opts->drive->cancel = 0; /* End of the return = failure area */ - - o.drive = opts->drive; - o.opts = opts; - o.disc = disc; - - opts->refcount++; - - 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(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; - - while (workers) - pthread_join(workers->thread, &ret); -} - -#endif /* Libburn_has_burn_async_join_alL */ - - diff --git a/libburn/async.h b/libburn/async.h deleted file mode 100644 index 9a6b514..0000000 --- a/libburn/async.h +++ /dev/null @@ -1,14 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef BURN__ASYNC_H -#define BURN__ASYNC_H - -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 */ diff --git a/libburn/back_hacks.h b/libburn/back_hacks.h deleted file mode 100644 index b086620..0000000 --- a/libburn/back_hacks.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - - This file bundles variables which disable changes in libburn which are - not yet completely accepted. - - The use of these variables is *strongly discouraged* unless you have sincere - reason and are willing to share your gained knowledge with the libburn - developers. - - Do *not silently rely* on these variables with your application. Tell us - that you needed one or more of them. They are subject to removal as soon - as consense has been found about correctness of the change they revoke. - - Value 0 means that the new behavior is enabled. Any other value enables - the described old time behavior. - - If you doubt one of the changes here broke your application, then do - *in your application*, *not here* : - - - #include "libburn/back_hacks.h" like you include "libburn/libburn.h" - - - Set the libburn_back_hack_* variable of your choice to 1. - In your app. Not here. - - - Then start and use libburn as usual. Watch out for results. - - - If you believe to have detected a flaw in our change, come forward - and report it to the libburn developers. Thanks in advance. :) - -*/ - -/** Do not define this macro in your application. Only libburn/init.c is - entitled to set it. -*/ -#ifdef BURN_BACK_HACKS_INIT - - -/** Corresponds to http://libburn.pykix.org/ticket/42 - Reinstates the old ban not to blank appendable CD-RW. We see no reason - for this ban yet. It appears unusual. But maybe it patches a bug. -*/ -int libburn_back_hack_42= 0; - - -#else /* BURN_BACK_HACKS_INIT */ - -/* Note: no application programmer info beyond this point */ - - -extern int libburn_back_hack_42; - -#endif /* ! BURN_BACK_HACKS_INIT */ - - diff --git a/libburn/cleanup.c b/libburn/cleanup.c deleted file mode 100644 index fc92383..0000000 --- a/libburn/cleanup.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - cleanup.c , Copyright 2006 Thomas Schmitt <scdbackup@gmx.net> - - A signal handler which cleans up an application and exits. - - Provided under GPL license within GPL projects, BSD license elsewise. -*/ - -/* - cc -g -o cleanup -DCleanup_standalonE cleanup.c -*/ - -#include <sys/types.h> -#include <stdlib.h> -#include <unistd.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include <signal.h> -typedef void (*sighandler_t)(int); - - -#include "cleanup.h" - - -#ifndef Cleanup_has_no_libburn_os_H - - -#include "../libburn/os.h" - -/* see os.h for name of particular os-*.h where this is defined */ -static int signal_list[]= { BURN_OS_SIGNAL_MACRO_LIST , -1}; -static char *signal_name_list[]= { BURN_OS_SIGNAL_NAME_LIST , "@"}; -static int signal_list_count= BURN_OS_SIGNAL_COUNT; -static int non_signal_list[]= { BURN_OS_NON_SIGNAL_MACRO_LIST, -1}; -static int non_signal_list_count= BURN_OS_NON_SIGNAL_COUNT; - - -#else /* ! Cleanup_has_no_libburn_os_H */ - - -/* Outdated. Linux only. For backward compatibility with pre-libburn-0.2.3 */ - -/* Signals to be caught */ -static int signal_list[]= { - SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, - SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, - SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN, - SIGTTOU, - SIGBUS, SIGPOLL, SIGPROF, SIGSYS, SIGTRAP, - SIGVTALRM, SIGXCPU, SIGXFSZ, -1 -}; -static char *signal_name_list[]= { - "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT", - "SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM", - "SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN", - "SIGTTOU", - "SIGBUS", "SIGPOLL", "SIGPROF", "SIGSYS", "SIGTRAP", - "SIGVTALRM", "SIGXCPU", "SIGXFSZ", "@" -}; -static int signal_list_count= 24; - -/* Signals not to be caught */ -static int non_signal_list[]= { - SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH, -1 -}; -static int non_signal_list_count= 5; - - -#endif /* Cleanup_has_no_libburn_os_H */ - - - -/* run time dynamic part */ -static char cleanup_msg[4096]= {""}; -static int cleanup_exiting= 0; -static int cleanup_has_reported= -1234567890; - -static void *cleanup_app_handle= NULL; -static Cleanup_app_handler_T cleanup_app_handler= NULL; -static int cleanup_perform_app_handler_first= 0; - - -static int Cleanup_handler_exit(int exit_value, int signum, int flag) -{ - int ret; - - if(cleanup_msg[0]!=0 && cleanup_has_reported!=signum) { - fprintf(stderr,"\n%s\n",cleanup_msg); - cleanup_has_reported= signum; - } - if(cleanup_perform_app_handler_first) - if(cleanup_app_handler!=NULL) { - ret= (*cleanup_app_handler)(cleanup_app_handle,signum,0); - if(ret==2 || ret==-2) - return(2); - } - if(cleanup_exiting) { - fprintf(stderr,"cleanup: ABORT : repeat by pid=%d, signum=%d\n", - getpid(),signum); - return(0); - } - cleanup_exiting= 1; - alarm(0); - if(!cleanup_perform_app_handler_first) - if(cleanup_app_handler!=NULL) { - ret= (*cleanup_app_handler)(cleanup_app_handle,signum,0); - if(ret==2 || ret==-2) - return(2); - } - exit(exit_value); -} - - -static void Cleanup_handler_generic(int signum) -{ - int i; - - sprintf(cleanup_msg,"UNIX-SIGNAL caught: %d errno= %d",signum,errno); - for(i= 0; i<signal_list_count; i++) - if(signum==signal_list[i]) { - sprintf(cleanup_msg,"UNIX-SIGNAL: %s errno= %d", - signal_name_list[i],errno); - break; - } - Cleanup_handler_exit(1,signum,0); -} - - -int Cleanup_set_handlers(void *handle, Cleanup_app_handler_T handler, int flag) -/* - bit0= set to default handlers - bit1= set to ignore - bit2= set cleanup_perform_app_handler_first - bit3= set SIGABRT to handler (makes sense with bits 0 or 1) -*/ -{ - int i,j,max_sig= -1,min_sig= 0x7fffffff; - sighandler_t sig_handler; - - cleanup_msg[0]= 0; - cleanup_app_handle= handle; - cleanup_app_handler= handler; - - /* <<< make cleanup_exiting thread safe to get rid of this */ - if(flag&4) - cleanup_perform_app_handler_first= 1; - - - if(flag&1) - sig_handler= SIG_DFL; - else if(flag&2) - sig_handler= SIG_IGN; - else - sig_handler= Cleanup_handler_generic; - /* set all signal numbers between the lowest and highest in the list - except those in the non-signal list */ - for(i= 0; i<signal_list_count; i++) { - if(signal_list[i]>max_sig) - max_sig= signal_list[i]; - if(signal_list[i]<min_sig) - min_sig= signal_list[i]; - } - for(i= min_sig; i<=max_sig; i++) { - for(j= 0; j<non_signal_list_count; j++) - if(i==non_signal_list[j]) - break; - if(j>=non_signal_list_count) { - if(i==SIGABRT && (flag&8)) - signal(i,Cleanup_handler_generic); - else - signal(i,sig_handler); - } - } - return(1); -} - - -#ifdef Cleanup_standalonE - -struct Demo_apP { - char *msg; -}; - - -int Demo_app_handler(struct Demo_apP *demoapp, int signum, int flag) -{ - printf("Handling exit of demo application on signal %d. msg=\"%s\"\n", - signum,demoapp->msg); - return(1); -} - - -main() -{ - struct Demo_apP demoapp; - - demoapp.msg= "Good Bye"; - Cleanup_set_handlers(&demoapp,(Cleanup_app_handler_T) Demo_app_handler,0); - - if(1) { /* change to 0 in order to wait for external signals */ - char *cpt= NULL,c; - printf("Intentionally provoking SIGSEGV ...\n"); - c= *cpt; - } else { - printf("killme: %d\n",getpid()); - sleep(3600); - } - - Cleanup_set_handlers(NULL,NULL,1); - exit(0); -} - -#endif /* Cleanup_standalonE */ diff --git a/libburn/cleanup.h b/libburn/cleanup.h deleted file mode 100644 index a9d3551..0000000 --- a/libburn/cleanup.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - cleanup.c , Copyright 2006 Thomas Schmitt <scdbackup@gmx.net> - - A signal handler which cleans up an application and exits. - - Provided under GPL license within GPL projects, BSD license elsewise. -*/ - -#ifndef Cleanup_includeD -#define Cleanup_includeD 1 - - -/** Layout of an application provided cleanup function using an application - provided handle as first argument and the signal number as second - argument. The third argument is a flag bit field with no defined bits yet. - If the handler returns 2 or -2 then it has delegated exit() to some other - instance and the Cleanup handler shall return rather than exit. -*/ -typedef int (*Cleanup_app_handler_T)(void *, int, int); - - -/** Establish exiting signal handlers on (hopefully) all signals that are - not ignored by default or non-catchable. - @param handle Opaque object which knows how to cleanup application - @param handler Function which uses handle to perform application cleanup - @param flag Control Bitfield - bit0= reset to default signal handling -*/ -int Cleanup_set_handlers(void *handle, Cleanup_app_handler_T handler, - int flag); - - -#endif /* ! Cleanup_includeD */ - diff --git a/libburn/crc.c b/libburn/crc.c deleted file mode 100644 index fddc5b4..0000000 --- a/libburn/crc.c +++ /dev/null @@ -1,122 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#include "crc.h" - -static unsigned short ccitt_table[256] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, - 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, - 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, - 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, - 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, - 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, - 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, - 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, - 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, - 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, - 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, - 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, - 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, - 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, - 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, - 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, - 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, - 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, - 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, - 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, - 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, - 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, - 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 -}; - -unsigned long crc32_table[256] = { - 0x00000000L, 0x90910101L, 0x91210201L, 0x01B00300L, - 0x92410401L, 0x02D00500L, 0x03600600L, 0x93F10701L, - 0x94810801L, 0x04100900L, 0x05A00A00L, 0x95310B01L, - 0x06C00C00L, 0x96510D01L, 0x97E10E01L, 0x07700F00L, - 0x99011001L, 0x09901100L, 0x08201200L, 0x98B11301L, - 0x0B401400L, 0x9BD11501L, 0x9A611601L, 0x0AF01700L, - 0x0D801800L, 0x9D111901L, 0x9CA11A01L, 0x0C301B00L, - 0x9FC11C01L, 0x0F501D00L, 0x0EE01E00L, 0x9E711F01L, - 0x82012001L, 0x12902100L, 0x13202200L, 0x83B12301L, - 0x10402400L, 0x80D12501L, 0x81612601L, 0x11F02700L, - 0x16802800L, 0x86112901L, 0x87A12A01L, 0x17302B00L, - 0x84C12C01L, 0x14502D00L, 0x15E02E00L, 0x85712F01L, - 0x1B003000L, 0x8B913101L, 0x8A213201L, 0x1AB03300L, - 0x89413401L, 0x19D03500L, 0x18603600L, 0x88F13701L, - 0x8F813801L, 0x1F103900L, 0x1EA03A00L, 0x8E313B01L, - 0x1DC03C00L, 0x8D513D01L, 0x8CE13E01L, 0x1C703F00L, - 0xB4014001L, 0x24904100L, 0x25204200L, 0xB5B14301L, - 0x26404400L, 0xB6D14501L, 0xB7614601L, 0x27F04700L, - 0x20804800L, 0xB0114901L, 0xB1A14A01L, 0x21304B00L, - 0xB2C14C01L, 0x22504D00L, 0x23E04E00L, 0xB3714F01L, - 0x2D005000L, 0xBD915101L, 0xBC215201L, 0x2CB05300L, - 0xBF415401L, 0x2FD05500L, 0x2E605600L, 0xBEF15701L, - 0xB9815801L, 0x29105900L, 0x28A05A00L, 0xB8315B01L, - 0x2BC05C00L, 0xBB515D01L, 0xBAE15E01L, 0x2A705F00L, - 0x36006000L, 0xA6916101L, 0xA7216201L, 0x37B06300L, - 0xA4416401L, 0x34D06500L, 0x35606600L, 0xA5F16701L, - 0xA2816801L, 0x32106900L, 0x33A06A00L, 0xA3316B01L, - 0x30C06C00L, 0xA0516D01L, 0xA1E16E01L, 0x31706F00L, - 0xAF017001L, 0x3F907100L, 0x3E207200L, 0xAEB17301L, - 0x3D407400L, 0xADD17501L, 0xAC617601L, 0x3CF07700L, - 0x3B807800L, 0xAB117901L, 0xAAA17A01L, 0x3A307B00L, - 0xA9C17C01L, 0x39507D00L, 0x38E07E00L, 0xA8717F01L, - 0xD8018001L, 0x48908100L, 0x49208200L, 0xD9B18301L, - 0x4A408400L, 0xDAD18501L, 0xDB618601L, 0x4BF08700L, - 0x4C808800L, 0xDC118901L, 0xDDA18A01L, 0x4D308B00L, - 0xDEC18C01L, 0x4E508D00L, 0x4FE08E00L, 0xDF718F01L, - 0x41009000L, 0xD1919101L, 0xD0219201L, 0x40B09300L, - 0xD3419401L, 0x43D09500L, 0x42609600L, 0xD2F19701L, - 0xD5819801L, 0x45109900L, 0x44A09A00L, 0xD4319B01L, - 0x47C09C00L, 0xD7519D01L, 0xD6E19E01L, 0x46709F00L, - 0x5A00A000L, 0xCA91A101L, 0xCB21A201L, 0x5BB0A300L, - 0xC841A401L, 0x58D0A500L, 0x5960A600L, 0xC9F1A701L, - 0xCE81A801L, 0x5E10A900L, 0x5FA0AA00L, 0xCF31AB01L, - 0x5CC0AC00L, 0xCC51AD01L, 0xCDE1AE01L, 0x5D70AF00L, - 0xC301B001L, 0x5390B100L, 0x5220B200L, 0xC2B1B301L, - 0x5140B400L, 0xC1D1B501L, 0xC061B601L, 0x50F0B700L, - 0x5780B800L, 0xC711B901L, 0xC6A1BA01L, 0x5630BB00L, - 0xC5C1BC01L, 0x5550BD00L, 0x54E0BE00L, 0xC471BF01L, - 0x6C00C000L, 0xFC91C101L, 0xFD21C201L, 0x6DB0C300L, - 0xFE41C401L, 0x6ED0C500L, 0x6F60C600L, 0xFFF1C701L, - 0xF881C801L, 0x6810C900L, 0x69A0CA00L, 0xF931CB01L, - 0x6AC0CC00L, 0xFA51CD01L, 0xFBE1CE01L, 0x6B70CF00L, - 0xF501D001L, 0x6590D100L, 0x6420D200L, 0xF4B1D301L, - 0x6740D400L, 0xF7D1D501L, 0xF661D601L, 0x66F0D700L, - 0x6180D800L, 0xF111D901L, 0xF0A1DA01L, 0x6030DB00L, - 0xF3C1DC01L, 0x6350DD00L, 0x62E0DE00L, 0xF271DF01L, - 0xEE01E001L, 0x7E90E100L, 0x7F20E200L, 0xEFB1E301L, - 0x7C40E400L, 0xECD1E501L, 0xED61E601L, 0x7DF0E700L, - 0x7A80E800L, 0xEA11E901L, 0xEBA1EA01L, 0x7B30EB00L, - 0xE8C1EC01L, 0x7850ED00L, 0x79E0EE00L, 0xE971EF01L, - 0x7700F000L, 0xE791F101L, 0xE621F201L, 0x76B0F300L, - 0xE541F401L, 0x75D0F500L, 0x7460F600L, 0xE4F1F701L, - 0xE381F801L, 0x7310F900L, 0x72A0FA00L, 0xE231FB01L, - 0x71C0FC00L, 0xE151FD01L, 0xE0E1FE01L, 0x7070FF00L -}; - -unsigned short crc_ccitt(unsigned char *q, int len) -{ - unsigned short crc = 0; - - while (len-- > 0) - crc = ccitt_table[(crc >> 8 ^ *q++) & 0xff] ^ (crc << 8); - return ~crc; -} -unsigned int crc_32(unsigned char *data, int len) -{ - unsigned int crc = 0; - - while (len-- > 0) - crc = crc32_table[(crc ^ *data++) & 0xffL] ^ (crc >> 8); - return crc; -} diff --git a/libburn/crc.h b/libburn/crc.h deleted file mode 100644 index a4846a3..0000000 --- a/libburn/crc.h +++ /dev/null @@ -1,9 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef BURN__CRC_H -#define BURN__CRC_H - -unsigned short crc_ccitt(unsigned char *, int len); -unsigned int crc_32(unsigned char *, int len); - -#endif /* BURN__CRC_H */ diff --git a/libburn/ddlpa.c b/libburn/ddlpa.c deleted file mode 100644 index b58e021..0000000 --- a/libburn/ddlpa.c +++ /dev/null @@ -1,614 +0,0 @@ - -/* ddlpa - Implementation of Delicate Device Locking Protocol level A. - Copyright (C) 2007 Thomas Schmitt <scdbackup@gmx.net> - Provided under any of the following licenses: GPL, LGPL, BSD. Choose one. - - - Compile as test program: - - cc -g -Wall \ - -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE \ - -DDDLPA_C_STANDALONE -o ddlpa ddlpa.c - - The system macros enable 64-bit off_t and open(2) flag O_LARGEFILE, which - are not absolutely necessary but explicitely take into respect that - our devices can offer more than 2 GB of addressable data. - - Run test program: - - ./ddlpa /dev/sr0 15 - ./ddlpa 0,0,0 15 - -*/ - -#include <stdio.h> -#include <sys/types.h> -#include <unistd.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/ioctl.h> -#include <scsi/scsi.h> - - -/* All callers of ddlpa must do this */ -#include "ddlpa.h" - - -/* 1 = Enable progress message on stderr, 0 = normal silent operation */ -static int ddlpa_debug_mode = 1; - - -/* #define _GNU_SOURCE or _LARGEFILE64_SOURCE to get real O_LARGEFILE */ -#ifndef O_LARGEFILE -#define O_LARGEFILE 0 -#endif - - -/* ----------------------- private -------------------- */ - - -static int ddlpa_new(struct ddlpa_lock **lck, int o_flags, int ddlpa_flags) -{ - int i; - struct ddlpa_lock *o; - - o = *lck = (struct ddlpa_lock *) malloc(sizeof(struct ddlpa_lock)); - if (o == NULL) - return ENOMEM; - for (i = 0; i < sizeof(struct ddlpa_lock); i++) - ((char *) o)[i] = 0; - o->path = NULL; - o->fd = -1; - for (i = 0; i < DDLPA_MAX_SIBLINGS; i++) - o->sibling_fds[i] = -1; - o->errmsg = NULL; - - o->o_flags = o_flags; - o->ddlpa_flags = ddlpa_flags; - return 0; -} - - -static int ddlpa_enumerate(struct ddlpa_lock *o, int *idx, - char path[DDLPA_MAX_STD_LEN + 1]) -{ - if (*idx < 0) - *idx = 0; - - if (*idx < 26) - sprintf(path, "/dev/hd%c", 'a' + *idx); - else if (*idx < 256 + 26) - sprintf(path, "/dev/sr%d", *idx - 26); - else if (*idx < 2 * 256 + 26) - sprintf(path, "/dev/scd%d", *idx - 256 - 26); - else if (*idx < 3 * 256 + 26) - sprintf(path, "/dev/sg%d", *idx - 2 * 256 - 26); - else - return 1; - (*idx)++; - return 0; -} - - -static int ddlpa_std_by_rdev(struct ddlpa_lock *o) -{ - int idx = 0; - char try_path[DDLPA_MAX_STD_LEN+1]; - struct stat path_stbuf, try_stbuf; - - if (!o->path_is_valid) - return EFAULT; - if (stat(o->path, &path_stbuf) == -1) - return errno; - - while (ddlpa_enumerate(o, &idx, try_path) == 0) { - if (stat(try_path, &try_stbuf) == -1) - continue; - if (path_stbuf.st_rdev != try_stbuf.st_rdev) - continue; - strcpy(o->std_path, try_path); - - if (ddlpa_debug_mode) - fprintf(stderr, - "DDLPA_DEBUG: ddlpa_std_by_rdev(\"%s\") = \"%s\"\n", - o->path, o->std_path); - - return 0; - } - return ENOENT; -} - - -/* Caution : these tests are valid only with standard paths */ - -static int ddlpa_is_scsi(struct ddlpa_lock *o, char *path) -{ - return (strncmp(path, "/dev/s", 6) == 0); -} - -static int ddlpa_is_sg(struct ddlpa_lock *o, char *path) -{ - return (strncmp(path, "/dev/sg", 7) == 0); -} - -static int ddlpa_is_sr(struct ddlpa_lock *o, char *path) -{ - return (strncmp(path, "/dev/sr", 7) == 0); -} - -static int ddlpa_is_scd(struct ddlpa_lock *o, char *path) -{ - return (strncmp(path, "/dev/scd", 8) == 0); -} - - -static int ddlpa_fcntl_lock(struct ddlpa_lock *o, int fd, int l_type) -{ - struct flock lockthing; - int ret; - - memset(&lockthing, 0, sizeof(lockthing)); - lockthing.l_type = l_type; - lockthing.l_whence = SEEK_SET; - lockthing.l_start = 0; - lockthing.l_len = 0; - ret = fcntl(fd, F_SETLK, &lockthing); - if (ret == -1) - return EBUSY; - return 0; -} - - -static int ddlpa_occupy(struct ddlpa_lock *o, char *path, int *fd, - int no_o_excl) -{ - int ret, o_flags, o_rw, l_type; - char *o_rwtext; - - o_flags = o->o_flags | O_NDELAY; - if(!no_o_excl) - o_flags |= O_EXCL; - o_rw = (o_flags) & (O_RDONLY | O_WRONLY | O_RDWR); - o_rwtext = (o_rw == O_RDONLY ? "O_RDONLY" : - (o_rw == O_WRONLY ? "O_WRONLY" : - (o_rw == O_RDWR ? "O_RDWR " : "O_?rw-mode?"))); - - *fd = open(path, o_flags); - if (*fd == -1) { - o->errmsg = malloc(strlen(path)+160); - if (o->errmsg) - sprintf(o->errmsg, - "Failed to open %s | O_NDELAY %s: '%s'", - o_rwtext, - (o_flags & O_EXCL ? "| O_EXCL " : ""), path); - return (errno ? errno : EBUSY); - } - if (o_rw == O_RDWR || o_rw == O_WRONLY) - l_type = F_WRLCK; - else - l_type = F_RDLCK; - ret = ddlpa_fcntl_lock(o, *fd, l_type); - if (ret) { - o->errmsg = malloc(strlen(path)+160); - if (o->errmsg) - sprintf(o->errmsg, - "Failed to lock fcntl(F_WRLCK) : '%s'",path); - close(*fd); - *fd = -1; - return ret; - } - if (ddlpa_debug_mode) - fprintf(stderr, "DDLPA_DEBUG: ddlpa_occupy() %s %s: '%s'\n", - o_rwtext, - (no_o_excl ? " " : "O_EXCL "), path); - return 0; -} - - -static int ddlpa_obtain_scsi_adr(struct ddlpa_lock *o, char *path, - int *bus, int *host, int *channel, int *id, int *lun) -{ - int fd, ret, open_mode = O_RDONLY | O_NDELAY; - struct my_scsi_idlun { - int x; - int host_unique_id; - }; - struct my_scsi_idlun idlun; - - fd = open(path, open_mode); - if (fd == -1) - return (errno ? errno : EBUSY); - if (ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, bus) == -1) - *bus = -1; - ret = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &idlun); - close(fd); - if (ret == -1) - return (errno ? errno : EIO); - *host = (idlun.x >> 24) & 255; - *channel = (idlun.x >> 16) & 255; - *id = (idlun.x) & 255; - *lun = (idlun.x >> 8 ) & 255; - return 0; -} - - -static int ddlpa_collect_siblings(struct ddlpa_lock *o) -{ - int idx = 0, ret, have_sg = 0, have_sr = 0, have_scd = 0; - dev_t path_dev; - ino_t path_inode; - struct stat stbuf; - char *path, try_path[DDLPA_MAX_STD_LEN+1]; - int t_bus, t_host, t_channel, t_id, t_lun; - - if (o->ddlpa_flags & DDLPA_OPEN_GIVEN_PATH) - path = o->path; - else - path = o->std_path; - if (path[0] == 0 || o->num_siblings != 0) - return EFAULT; - if (!ddlpa_is_scsi(o, o->std_path)) - return EFAULT; - - if (stat(path, &stbuf) == -1) - return errno; - path_inode = stbuf.st_ino; - path_dev = stbuf.st_dev; - o->rdev = stbuf.st_rdev; - o->dev = stbuf.st_dev; - o->ino = stbuf.st_ino; - ret = ddlpa_obtain_scsi_adr(o, path, - &(o->bus), &(o->host), &(o->channel), - &(o->id), &(o->lun)); - if (ret) { - o->errmsg = strdup( - "Cannot obtain SCSI parameters host,channel,id,lun"); - return ret; - } - o->hcilb_is_valid = 1; - - while (ddlpa_enumerate(o, &idx, try_path) == 0) { - if (!ddlpa_is_scsi(o, try_path)) - continue; - if (stat(try_path, &stbuf) == -1) - continue; - ret = ddlpa_obtain_scsi_adr(o, try_path, - &t_bus, &t_host, &t_channel, &t_id, &t_lun); - if (ret) { - - /* >>> interpret error, memorize busy, no permission */ - - continue; - } - if (t_host != o->host || t_channel != o->channel || - t_id != o->id || t_lun != o->lun) - continue; - - if (o->num_siblings >= DDLPA_MAX_SIBLINGS) { - o->errmsg = - strdup("Too many matching device files found"); - return ERANGE; - } - if (ddlpa_is_sg(o, try_path)) - have_sg = 1; - else if (ddlpa_is_sr(o, try_path)) - have_sr = 1; - else if (ddlpa_is_scd(o, try_path)) - have_scd = 1; - strcpy(o->sibling_paths[o->num_siblings], try_path); - o->sibling_rdevs[o->num_siblings] = stbuf.st_rdev; - o->sibling_devs[o->num_siblings] = stbuf.st_dev; - o->sibling_inodes[o->num_siblings] = stbuf.st_ino; - - if (ddlpa_debug_mode) - fprintf(stderr, - "DDLPA_DEBUG: ddlpa_collect_siblings() found \"%s\"\n", - try_path); - - (o->num_siblings)++; - } - if (have_sg && have_sr && have_scd) - return 0; - if (o->ddlpa_flags & DDLPA_ALLOW_MISSING_SGRCD) - return 0; - - o->errmsg = strdup("Did not find enough siblings"); - - /* >>> add more info about busy and forbidden paths */ - - return EBUSY; -} - - -static int ddlpa_std_by_btl(struct ddlpa_lock *o) -{ - int idx = 0, ret; - char try_path[DDLPA_MAX_STD_LEN+1]; - int t_bus, t_host, t_channel, t_id, t_lun; - - if (!o->inbtl_is_valid) - return EFAULT; - - while (ddlpa_enumerate(o, &idx, try_path) == 0) { - if (!ddlpa_is_sr(o, try_path)) - continue; - ret = ddlpa_obtain_scsi_adr(o, try_path, - &t_bus, &t_host, &t_channel, &t_id, &t_lun); - if (ret) { - - /* >>> interpret error, memorize busy, no permission */ - - continue; - } - if (t_bus != o->in_bus || t_id != o->in_target || - t_lun != o->in_lun) - continue; - strcpy(o->std_path, try_path); - - if (ddlpa_debug_mode) - fprintf(stderr, - "DDLPA_DEBUG: ddlpa_std_by_btl(%d,%d,%d) = \"%s\"\n", - t_bus, t_id, t_lun, o->std_path); - - return 0; - } - - /* >>> add more info about busy and forbidden paths */ - - return ENOENT; -} - - -static int ddlpa_open_all(struct ddlpa_lock *o) -{ - int i, j, ret, no_o_excl; - - if (ddlpa_is_scsi(o, o->std_path)) { - ret = ddlpa_collect_siblings(o); - if (ret) - return ret; - for (i = 0; i < o->num_siblings; i++) { - - /* Watch out for the main personality of the drive. */ - /* No need to occupy identical path or softlink path */ - if (o->sibling_devs[i] == o->dev && - o->sibling_inodes[i] == o->ino) - continue; - /* There may be the same rdev but different inode. */ - no_o_excl = (o->sibling_rdevs[i] == o->rdev); - - /* Look for multiply registered device drivers with - distinct inodes. */ - for (j = 0; j < i; j++) { - if (o->sibling_devs[j] == o->sibling_devs[i] && - o->sibling_inodes[j] == o->sibling_inodes[i]) - break; - if (o->sibling_rdevs[j] == o->sibling_rdevs[i]) - no_o_excl = 1; - } - if (j < i) - continue; /* inode is already occupied */ - - ret = ddlpa_occupy(o, o->sibling_paths[i], - &(o->sibling_fds[i]), no_o_excl); - if (ret) - return ret; - } - } - - if (o->ddlpa_flags & DDLPA_OPEN_GIVEN_PATH) - ret = ddlpa_occupy(o, o->path, &(o->fd), 0); - else - ret = ddlpa_occupy(o, o->std_path, &(o->fd), 0); - if (ret) - return ret; - - /* >>> use fcntl() to adjust O_NONBLOCK */; - - return 0; -} - - -/* ----------------------- public -------------------- */ - - -int ddlpa_destroy(struct ddlpa_lock **lockbundle) -{ - struct ddlpa_lock *o; - int i; - - o= *lockbundle; - if (o == NULL) - return 0; - for (i = 0; i < o->num_siblings; i++) - if (o->sibling_fds[i] != -1) - close(o->sibling_fds[i]); - if(o->fd != -1) - close(o->fd); - if (o->path != NULL) - free(o->path); - if (o->errmsg != NULL) - free(o->errmsg); - free((char *) o); - *lockbundle = NULL; - return 0; -} - - -int ddlpa_lock_path(char *path, int o_flags, int ddlpa_flags, - struct ddlpa_lock **lockbundle, char **errmsg) -{ - struct ddlpa_lock *o; - int ret; - - *errmsg = NULL; - if (ddlpa_new(&o, o_flags, ddlpa_flags)) - return ENOMEM; - *lockbundle = o; - - o->path = strdup(path); - if (o->path == NULL) - return ENOMEM; - o->path_is_valid = 1; - - ret = ddlpa_std_by_rdev(o); - if (ret) { - *errmsg = strdup( - "Cannot find equivalent of given path among standard paths"); - return ret; - } - ret = ddlpa_open_all(o); - if (ret) { - *errmsg = o->errmsg; - o->errmsg = NULL; - ddlpa_destroy(&o); - } - return ret; -} - - -int ddlpa_lock_btl(int bus, int target, int lun, - int o_flags, int ddlpa_flags, - struct ddlpa_lock **lockbundle, char **errmsg) -{ - struct ddlpa_lock *o; - int ret; - - *errmsg = NULL; - ddlpa_flags &= ~DDLPA_OPEN_GIVEN_PATH; - if (ddlpa_new(&o, o_flags, ddlpa_flags)) - return ENOMEM; - *lockbundle = o; - - o->in_bus = bus; - o->in_target = target; - o->in_lun = lun; - o->inbtl_is_valid = 1; - ret = ddlpa_std_by_btl(o); - if (ret) { - *errmsg = strdup( - "Cannot find /dev/sr* with given Bus,Target,Lun"); - return ret; - } - ret = ddlpa_open_all(o); - if (ret) { - *errmsg = o->errmsg; - o->errmsg = NULL; - ddlpa_destroy(&o); - return ret; - } - return 0; -} - - -#ifdef DDLPA_C_STANDALONE - -/* ----------------------------- Test / Demo -------------------------- */ - - -int main(int argc, char **argv) -{ - struct ddlpa_lock *lck = NULL; - char *errmsg = NULL, *opened_path = NULL, *my_path = NULL; - int i, ret, fd = -1, duration = -1, bus = -1, target = -1, lun = -1; - - if (argc < 3) { -usage:; - fprintf(stderr, "usage: %s device_path duration\n", argv[0]); - exit(1); - } - my_path = argv[1]; - sscanf(argv[2], "%d", &duration); - if (duration < 0) - goto usage; - - - /* For our purpose, only O_RDWR is a suitable access mode. - But in order to allow experiments, o_flags are freely adjustable. - - Warning: Do _not_ set an own O_EXCL flag with the following calls ! - - (This freedom to fail may get removed in a final version.) - */ - if (my_path[0] != '/' && my_path[0] != '.' && - strchr(my_path, ',') != NULL) { - /* - cdrecord style dev=Bus,Target,Lun - */ - - sscanf(my_path, "%d,%d,%d", &bus, &target, &lun); - ret = ddlpa_lock_btl(bus, target, lun, O_RDWR | O_LARGEFILE, - 0, &lck, &errmsg); - } else { - /* - This substitutes for: - fd = open(my_path, O_RDWR | O_EXCL | O_LARGEFILE); - - */ - - ret = ddlpa_lock_path(my_path, O_RDWR | O_LARGEFILE, - 0, &lck, &errmsg); - } - if (ret) { - fprintf(stderr, "Cannot exclusively open '%s'\n", my_path); - if (errmsg != NULL) - fprintf(stderr, "Reason given : %s\n", - errmsg); - free(errmsg); - fprintf(stderr, "Error condition : %d '%s'\n", - ret, strerror(ret)); - exit(2); - } - fd = lck->fd; - - printf("---------------------------------------------- Lock gained\n"); - - - /* Use fd for the usual operations on the device depicted by my_path. - */ - - - /* This prints an overview of the impact of the lock */ - if (lck->ddlpa_flags & DDLPA_OPEN_GIVEN_PATH) - opened_path = lck->path; - else - opened_path = lck->std_path; - printf("ddlpa: opened %s", opened_path); - - if (strcmp(opened_path, lck->std_path) != 0) - printf(" (an alias of '%s')", lck->std_path); - printf("\n"); - if (lck->num_siblings > 0) { - printf("ddlpa: opened siblings:"); - for (i = 0; i < lck->num_siblings; i++) - if (lck->sibling_fds[i] != -1) - printf(" %s", lck->sibling_paths[i]); - printf("\n"); - } - - - /* This example waits a while. So other lock candidates can collide. */ - for (i = 0; i < duration; i++) { - sleep(1); - fprintf(stderr, "\rslept %d seconds of %d", i + 1, duration); - } - fprintf(stderr, "\n"); - - - /* When finally done with the drive, this substitutes for: - close(fd); - */ - if (ddlpa_destroy(&lck)) { - /* Well, man 2 close says it can fail. */ - exit(3); - } - exit(0); -} - - -#endif /* DDLPA_C_STANDALONE */ - diff --git a/libburn/ddlpa.h b/libburn/ddlpa.h deleted file mode 100644 index 6b057c9..0000000 --- a/libburn/ddlpa.h +++ /dev/null @@ -1,107 +0,0 @@ - -/* ddlpa - Implementation of Delicate Device Locking Protocol level A. - Copyright (C) 2007 Thomas Schmitt <scdbackup@gmx.net> - Provided under any of the following licenses: GPL, LGPL, BSD. Choose one. - - See ../doc/ddlp.txt for a description of the protocol. -*/ - -#ifndef DDLPA_H_INCLUDED -#define DDLPA_H_INCLUDED 1 - - -/* An upper limit for the length of standard paths and sibling paths */ -#define DDLPA_MAX_STD_LEN 15 - -/* An upper limit for the number of siblings */ -#define DDLPA_MAX_SIBLINGS 5 - -struct ddlpa_lock { - - /* Recorded input parameters of locking call */ - char *path; - int path_is_valid; - int in_bus, in_target, in_lun; - int inbtl_is_valid; - int ddlpa_flags; - int o_flags; - - /* Result of locking call */ - char std_path[DDLPA_MAX_STD_LEN + 1]; - int fd; - dev_t rdev; - dev_t dev; - ino_t ino; - int host, channel, id, lun, bus; - int hcilb_is_valid; - int num_siblings; - char sibling_paths[DDLPA_MAX_SIBLINGS][DDLPA_MAX_STD_LEN + 1]; - int sibling_fds[DDLPA_MAX_SIBLINGS]; - dev_t sibling_rdevs[DDLPA_MAX_SIBLINGS]; - dev_t sibling_devs[DDLPA_MAX_SIBLINGS]; - ino_t sibling_inodes[DDLPA_MAX_SIBLINGS]; - - /* Is NULL if all goes well. Else it may contain a text message. */ - char *errmsg; -}; - - - -/** Lock a recorder by naming a device file path. Allocate a new container. - @param path Gives the file system path of the recorder - as known to the calling program. - @param o_flags flags for open(2). Do not use O_EXCL here because this - is done automatically whenever appropriate. - Advised is O_RDWR | O_LARGEFILE, eventually | O_NDELAY. - @param ddlpa_flags 0 = default behavior: the standard path will be opened - and treated by fcntl(F_SETLK) - DDLPA_OPEN_GIVEN_PATH causes the input parameter "path" - to be used with open(2) and fcntl(2). - DDLPA_ALLOW_MISSING_SGRCD allows to grant a lock - although not all three, a sg, a sr and a scd device - file have been found during sibling search. Normally - this is counted as failure due to EBUSY. - @param lockbundle gets allocated and then represents the locking state - @param errmsg if *errmsg is not NULL after the call, it contains an - error message. Then to be released by free(3). - It is NULL in case of success or lack of memory. - @return 0=success , else an errno compatible error number -*/ -int ddlpa_lock_path(char *path, int o_flags, int ddlpa_flags, - struct ddlpa_lock **lockbundle, char **errmsg); - - -/** Lock a recorder by naming a Bus,Target,Lun number triple. - Allocate a new container. - @param bus parameter to match ioctl(SCSI_IOCTL_GET_BUS_NUMBER) - @param target parameter to match ioctl(SCSI_IOCTL_GET_IDLUN) &0xff - @param lun parameter to match ioctl(SCSI_IOCTL_GET_IDLUN) &0xff00 - @param o_flags see ddlpa_lock_path(). - @param ddlpa_flags see ddlpa_lock_path(). Flag DDLPA_OPEN_GIVEN_PATH - will be ignored. - @param lockbundle see ddlpa_lock_path(). - @param errmsg see ddlpa_lock_path(). - @return 0=success , else an errno compatible error number -*/ -int ddlpa_lock_btl(int bus, int target, int lun, - int o_flags, int ddlpa_flags, - struct ddlpa_lock **lockbundle, char **errmsg); - - -/** Release the lock by closing all filedescriptors and freeing memory. - @param lockbundle the lock which is to be released. - *lockbundle will be set to NULL by this call. - @return 0=success , 1=failure -*/ -int ddlpa_destroy(struct ddlpa_lock **lockbundle); - - - -/** Definitions of macros used in above functions */ - -#define DDLPA_OPEN_GIVEN_PATH 1 -#define DDLPA_ALLOW_MISSING_SGRCD 2 - - -#endif /* DDLPA_H_INCLUDED */ diff --git a/libburn/debug.c b/libburn/debug.c deleted file mode 100644 index b4abab7..0000000 --- a/libburn/debug.c +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifdef WIN32 -#include <windows.h> -#endif - -#include <stdarg.h> -#include <stdio.h> -#include "libburn.h" -#include "debug.h" - -static int burn_verbosity = 0; - -void burn_set_verbosity(int v) -{ - burn_verbosity = v; -} - -void burn_print(int level, const char *a, ...) -{ -#ifdef WIN32 - char debug_string_data[256]; -#endif - va_list vl; - - if (level <= burn_verbosity) { - va_start(vl, a); -#ifdef WIN32 - vsprintf(debug_string_data, a, vl); - OutputDebugString(debug_string_data); -#else - vfprintf(stderr, a, vl); -#endif - } -} diff --git a/libburn/debug.h b/libburn/debug.h deleted file mode 100644 index b566de0..0000000 --- a/libburn/debug.h +++ /dev/null @@ -1,8 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef BURN__DEBUG_H -#define BURN__DEBUG_H - -void burn_print(int level, const char *a, ...); - -#endif /* BURN__DEBUG_H */ diff --git a/libburn/drive.c b/libburn/drive.c deleted file mode 100644 index c29d247..0000000 --- a/libburn/drive.c +++ /dev/null @@ -1,2469 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#include <sys/types.h> -#include <sys/stat.h> - -/* #include <m alloc.h> ts A61013 : not in Linux man 3 malloc */ - -#include <stdlib.h> -#include <unistd.h> -#include <signal.h> - -/* ts A61007 */ -/* #include <a ssert.h> */ - -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <pthread.h> -#include <errno.h> -#include "libburn.h" -#include "init.h" -#include "drive.h" -#include "transport.h" -#include "debug.h" -#include "init.h" -#include "toc.h" -#include "util.h" -#include "sg.h" -#include "structure.h" - -/* ts A70107 : to get BE_CANCELLED */ -#include "error.h" - -/* ts A70219 : for burn_disc_get_write_mode_demands() */ -#include "options.h" - -/* A70225 : to learn about eventual Libburn_dvd_r_dl_multi_no_close_sessioN */ -#include "write.h" - -/* A70903 : for burn_scsi_setup_drive() */ -#include "spc.h" - -#include "libdax_msgs.h" -extern struct libdax_msgs *libdax_messenger; - -static struct burn_drive drive_array[255]; -static int drivetop = -1; - -/* ts A80410 : in init.c */ -extern int burn_support_untested_profiles; - -/* ts A61021 : the unspecific part of sg.c:enumerate_common() -*/ -int burn_setup_drive(struct burn_drive *d, char *fname) -{ - d->devname = burn_strdup(fname); - memset(&d->params, 0, sizeof(struct params)); - d->idata = NULL; - d->mdata = NULL; - d->toc_entry = NULL; - d->released = 1; - d->stdio_fd = -1; - d->status = BURN_DISC_UNREADY; - d->do_stream_recording = 0; - return 1; -} - - -/* ts A70903 */ -void burn_drive_free_subs(struct burn_drive *d) -{ - if (d->idata != NULL) - free((void *) d->idata); - d->idata = NULL; - if (d->mdata != NULL) { - burn_mdata_free_subs(d->mdata); - free((void *) d->mdata); - } - d->mdata = NULL; - if(d->toc_entry != NULL) - free((void *) d->toc_entry); - d->toc_entry = NULL; - if (d->devname != NULL) - free(d->devname); - d->devname = NULL; - if (d->stdio_fd >= 0) - close (d->stdio_fd); - d->stdio_fd = -1; -} - - -/* ts A60904 : ticket 62, contribution by elmom */ -/* splitting former burn_drive_free() (which freed all, into two calls) */ -void burn_drive_free(struct burn_drive *d) -{ - if (d->global_index == -1) - return; - /* ts A60822 : close open fds before forgetting them */ - if (d->drive_role == 1) - if (burn_drive_is_open(d)) { - d->unlock(d); - d->release(d); - } - burn_drive_free_subs(d); - d->global_index = -1; -} - -void burn_drive_free_all(void) -{ - int i; - - for (i = 0; i < drivetop + 1; i++) - burn_drive_free(&(drive_array[i])); - drivetop = -1; - memset(drive_array, 0, sizeof(drive_array)); -} - - -/* ts A60822 */ -int burn_drive_is_open(struct burn_drive *d) -{ - if (d->drive_role != 1) - return (d->stdio_fd >= 0); - /* ts A61021 : moved decision to sg.c */ - return d->drive_is_open(d); -} - - -/* ts A60906 */ -int burn_drive_force_idle(struct burn_drive *d) -{ - d->busy = BURN_DRIVE_IDLE; - return 1; -} - - -/* ts A60906 */ -int burn_drive_is_released(struct burn_drive *d) -{ - return !!d->released; -} - - -/* ts A60906 */ -/** Inquires drive status in respect to degree of app usage. - @param return -2 = drive is forgotten - -1 = drive is closed (i.e. released explicitely) - 0 = drive is open, not grabbed (after scan, before 1st grab) - 1 = drive is grabbed but BURN_DRIVE_IDLE - 2 = drive is grabbed, synchronous read/write interrupted - 10 = drive is grabbing (BURN_DRIVE_GRABBING) - 100 = drive is busy in cancelable state - 1000 = drive is in non-cancelable state - Expect a monotonous sequence of usage severity to emerge in future. -*/ -int burn_drive_is_occupied(struct burn_drive *d) -{ - if(d->global_index < 0) - return -2; - if(!burn_drive_is_open(d)) - return -1; - if(d->busy == BURN_DRIVE_GRABBING) - return 10; - if(d->released) - return 0; - if(d->busy == BURN_DRIVE_IDLE) - return 1; - if(d->busy == BURN_DRIVE_READING_SYNC || - d->busy == BURN_DRIVE_WRITING_SYNC) - return 2; - if(d->busy == BURN_DRIVE_WRITING) { - - /* ts A70928 */ - /* >>> how do i learn whether the writer thread is still - alive ? */; - /* >>> what to do if writer is dead ? - At least sync disc ?*/; - return 50; - } - if(d->busy == BURN_DRIVE_READING) { - return 50; - } - return 1000; -} - - -/* -void drive_read_lead_in(int dnum) -{ - mmc_read_lead_in(&drive_array[dnum], get_4k()); -} -*/ -unsigned int burn_drive_count(void) -{ - return drivetop + 1; -} - - -/* ts A61125 : media status aspects of burn_drive_grab() */ -int burn_drive_inquire_media(struct burn_drive *d) -{ - - /* ts A61225 : after loading the tray, mode page 2Ah can change */ - d->getcaps(d); - - /* ts A61020 : d->status was set to BURN_DISC_BLANK as pure guess */ - - /* ts A71128 : run read_disc_info() for any recognizeable profile */ - if (d->current_profile > 0 || - d->mdata->cdr_write || d->mdata->cdrw_write || - d->mdata->dvdr_write || d->mdata->dvdram_write) { - -#define Libburn_knows_correct_state_after_loaD 1 -#ifdef Libburn_knows_correct_state_after_loaD - - d->read_disc_info(d); - -#else - /* ts A61227 : This repeated read_disc_info seems - to be obsoleted by above d->getcaps(d). - */ - /* ts A60908 */ - /* Trying to stabilize the disc status after eventual load - without closing and re-opening the drive */ - /* This seems to work for burn_disc_erasable() . - Speed values on RIP-14 and LITE-ON 48125S are stable - and false, nevertheless. */ - int was_equal = 0, must_equal = 3, max_loop = 20; - int loop_count, old_speed = -1234567890, new_speed= -987654321; - int old_erasable = -1234567890, new_erasable = -987654321; - - fprintf(stderr,"LIBBURN_DEBUG: read_disc_info()\n"); - for (loop_count = 0; loop_count < max_loop; loop_count++){ - old_speed = new_speed; - old_erasable = new_erasable; - - d->read_disc_info(d); - if(d->status == BURN_DISC_UNSUITABLE) - break; - - new_speed = burn_drive_get_write_speed(d); - new_erasable = burn_disc_erasable(d); - if (new_speed == old_speed && - new_erasable == old_erasable) { - was_equal++; - if (was_equal >= must_equal) - break; - } else - was_equal = 0; - /* - if (loop_count >= 1 && was_equal == 0) - */ - fprintf(stderr,"LIBBURN_DEBUG: %d : speed %d:%d erasable %d:%d\n", - loop_count,old_speed,new_speed,old_erasable,new_erasable); - usleep(100000); - } -#endif /* ! Libburn_knows_correct_state_after_loaD */ - - } else { - if (d->current_profile == -1 || d->current_is_cd_profile) - d->read_toc(d); - - /* ts A70314 */ - d->status = BURN_DISC_UNSUITABLE; - } - return 1; -} - - -int burn_drive_grab(struct burn_drive *d, int le) -{ - int errcode; - /* ts A61125 - A61202 */ - int ret, sose; - - if (!d->released) { - burn_print(1, "can't grab - already grabbed\n"); - return 0; - } - if(d->drive_role != 1) { - d->released = 0; - if(d->drive_role == 2 || d->drive_role == 3) { - d->status = BURN_DISC_BLANK; - d->current_profile = 0xffff; - } else { - d->status = BURN_DISC_EMPTY; - d->current_profile = 0; - } - d->busy = BURN_DRIVE_IDLE; - return 1; - } - - d->status = BURN_DISC_UNREADY; - errcode = d->grab(d); - - if (errcode == 0) { - burn_print(1, "low level drive grab failed\n"); - return 0; - } - d->busy = BURN_DRIVE_GRABBING; - - if (le) - d->load(d); - - d->lock(d); - - /* ts A61118 */ - d->start_unit(d); - - /* ts A61202 : gave bit1 of le a meaning */ - sose = d->silent_on_scsi_error; - if (!le) - d->silent_on_scsi_error = 1; - /* ts A61125 : outsourced media state inquiry aspects */ - ret = burn_drive_inquire_media(d); - d->silent_on_scsi_error = sose; - d->busy = BURN_DRIVE_IDLE; - return ret; -} - - -/* ts A71015 */ -#define Libburn_ticket_62_re_register_is_possiblE 1 - -struct burn_drive *burn_drive_register(struct burn_drive *d) -{ -#ifdef Libburn_ticket_62_re_register_is_possiblE - int i; -#endif - - d->block_types[0] = 0; - d->block_types[1] = 0; - d->block_types[2] = 0; - d->block_types[3] = 0; - d->toc_temp = 0; - d->nwa = 0; - d->alba = 0; - d->rlba = 0; - d->cancel = 0; - d->busy = BURN_DRIVE_IDLE; - d->thread_pid = 0; - d->thread_pid_valid = 0; - d->toc_entries = 0; - d->toc_entry = NULL; - d->disc = NULL; - d->erasable = 0; - -#ifdef Libburn_ticket_62_re_register_is_possiblE - /* ts A60904 : ticket 62, contribution by elmom */ - /* Not yet accepted because no use case seen yet */ - /* ts A71015 : xorriso dialog imposes a use case now */ - - /* This is supposed to find an already freed drive struct among - all the the ones that have been used before */ - for (i = 0; i < drivetop + 1; i++) - if (drive_array[i].global_index == -1) - break; - d->global_index = i; - memcpy(&drive_array[i], d, sizeof(struct burn_drive)); - pthread_mutex_init(&drive_array[i].access_lock, NULL); - if (drivetop < i) - drivetop = i; - return &(drive_array[i]); - -#else /* Libburn_ticket_62_re_register_is_possiblE */ - /* old A60904 : */ - /* Still active by default */ - - d->global_index = drivetop + 1; - memcpy(&drive_array[drivetop + 1], d, sizeof(struct burn_drive)); - pthread_mutex_init(&drive_array[drivetop + 1].access_lock, NULL); - return &drive_array[++drivetop]; - -#endif /* ! Libburn_ticket_62_re_register_is_possiblE */ - -} - - -/* unregister most recently registered drive */ -int burn_drive_unregister(struct burn_drive *d) -{ - if(d->global_index != drivetop) - return 0; - burn_drive_free(d); - drivetop--; - return 1; -} - - -/* ts A61021 : after-setup activities from sg.c:enumerate_common() -*/ -struct burn_drive *burn_drive_finish_enum(struct burn_drive *d) -{ - struct burn_drive *t; - /* ts A60821 - <<< debug: for tracing calls which might use open drive fds */ - int mmc_function_spy(struct burn_drive *d, char * text); - - d->drive_role = 1; /* MMC drive */ - - t = burn_drive_register(d); - - /* ts A60821 */ - mmc_function_spy(NULL, "enumerate_common : -------- doing grab"); - - /* try to get the drive info */ - if (t->grab(t)) { - burn_print(2, "getting drive info\n"); - t->getcaps(t); - t->unlock(t); - t->released = 1; - } else { - burn_print(2, "unable to grab new located drive\n"); - burn_drive_unregister(t); - t = NULL; - } - - /* ts A60821 */ - mmc_function_spy(NULL, "enumerate_common : ----- would release "); - - return t; -} - - -/* ts A61125 : model aspects of burn_drive_release */ -int burn_drive_mark_unready(struct burn_drive *d) -{ - /* ts A61020 : mark media info as invalid */ - d->start_lba= -2000000000; - d->end_lba= -2000000000; - - /* ts A61202 */ - d->current_profile = -1; - d->current_has_feat21h = 0; - d->current_feat2fh_byte4 = -1; - - d->status = BURN_DISC_UNREADY; - if (d->toc_entry != NULL) - free(d->toc_entry); - d->toc_entry = NULL; - d->toc_entries = 0; - if (d->disc != NULL) { - burn_disc_free(d->disc); - d->disc = NULL; - } - if (d->stdio_fd >= 0) - close (d->stdio_fd); - d->stdio_fd = -1; - return 1; -} - - -/* ts A70918 : outsourced from burn_drive_release() and enhanced */ -/** @param flag bit0-2 = mode : 0=unlock , 1=unlock+eject , 2=leave locked -*/ -int burn_drive_release_fl(struct burn_drive *d, int flag) -{ - if (d->released) { - /* ts A61007 */ - /* burn_print(1, "second release on drive!\n"); */ - libdax_msgs_submit(libdax_messenger, - d->global_index, 0x00020105, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Drive is already released", 0, 0); - return 0; - } - - /* ts A61007 */ - /* ts A60906: one should not assume BURN_DRIVE_IDLE == 0 */ - /* a ssert(d->busy == BURN_DRIVE_IDLE); */ - if (d->busy != BURN_DRIVE_IDLE) { - libdax_msgs_submit(libdax_messenger, - d->global_index, 0x00020106, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Drive is busy on attempt to close", 0, 0); - return 0; - } - - if (d->drive_role == 1) { - if (d->needs_sync_cache) - d->sync_cache(d); - if ((flag & 7) != 2) - d->unlock(d); - if ((flag & 7) == 1) - d->eject(d); - d->release(d); - } - - d->needs_sync_cache = 0; /* just to be sure */ - d->released = 1; - - /* ts A61125 : outsourced model aspects */ - burn_drive_mark_unready(d); - return 1; -} - - -/* API */ -void burn_drive_release(struct burn_drive *d, int le) -{ - burn_drive_release_fl(d, !!le); -} - - -/* ts A70918 */ -/* API */ -int burn_drive_leave_locked(struct burn_drive *d, int flag) -{ - return burn_drive_release_fl(d, 2); -} - - -/* ts A61007 : former void burn_wait_all() */ -/* @param flag bit0= demand freed drives (else released drives) */ -int burn_drives_are_clear(int flag) -{ - int i; - - for (i = burn_drive_count() - 1; i >= 0; --i) { - /* ts A60904 : ticket 62, contribution by elmom */ - if (drive_array[i].global_index == -1) - continue; - if (drive_array[i].released && !(flag & 1)) - continue; - return 0; - } - return 1; -} - - -#if 0 -void burn_wait_all(void) -{ - unsigned int i; - int finished = 0; - struct burn_drive *d; - - while (!finished) { - finished = 1; - d = drive_array; - for (i = burn_drive_count(); i > 0; --i, ++d) { - - /* ts A60904 : ticket 62, contribution by elmom */ - if (d->global_index==-1) - continue; - - a ssert(d->released); - } - if (!finished) - sleep(1); - } -} -#endif - - -void burn_disc_erase_sync(struct burn_drive *d, int fast) -{ -/* ts A60924 : libburn/message.c gets obsoleted - burn_message_clear_queue(); -*/ - - burn_print(1, "erasing drive %s %s\n", d->idata->vendor, - d->idata->product); - - d->cancel = 0; - d->busy = BURN_DRIVE_ERASING; - d->erase(d, fast); - /* reset the progress */ - d->progress.session = 0; - d->progress.sessions = 1; - d->progress.track = 0; - d->progress.tracks = 1; - d->progress.index = 0; - d->progress.indices = 1; - d->progress.start_sector = 0; - d->progress.sectors = 0x10000; - d->progress.sector = 0; - /* read the initial 0 stage */ - while (!d->test_unit_ready(d) && d->get_erase_progress(d) == 0) - sleep(1); - while ((d->progress.sector = d->get_erase_progress(d)) > 0 || - !d->test_unit_ready(d)) - sleep(1); - d->progress.sector = 0x10000; - - /* ts A61125 : update media state records */ - burn_drive_mark_unready(d); - if (d->drive_role == 1) - burn_drive_inquire_media(d); - d->busy = BURN_DRIVE_IDLE; -} - -/* - @param flag: bit0 = fill formatted size with zeros - bit1, bit2 , bit4, bit5, bit7 - bit15 are for d->format_unit() -*/ -void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag) -{ - int ret, buf_secs, err, i, stages = 1, pbase, pfill, pseudo_sector; - off_t num_bufs; - char msg[80]; - struct buffer buf; - - /* reset the progress */ - d->progress.session = 0; - d->progress.sessions = 1; - d->progress.track = 0; - d->progress.tracks = 1; - d->progress.index = 0; - d->progress.indices = 1; - d->progress.start_sector = 0; - d->progress.sectors = 0x10000; - d->progress.sector = 0; - stages = 1 + ((flag & 1) && size > 1024 * 1024); - d->cancel = 0; - d->busy = BURN_DRIVE_FORMATTING; - - ret = d->format_unit(d, size, flag & 0xfff6); /* forward bits */ - if (ret <= 0) - d->cancel = 1; - - while (!d->test_unit_ready(d) && d->get_erase_progress(d) == 0) - sleep(1); - while ((pseudo_sector = d->get_erase_progress(d)) > 0 || - !d->test_unit_ready(d)) { - d->progress.sector = pseudo_sector / stages; - sleep(1); - } - d->sync_cache(d); - - if (size <= 0) - goto ex; - - /* update media state records */ - burn_drive_mark_unready(d); - burn_drive_inquire_media(d); - if (flag & 1) { - /* write size in zeros */; - pbase = 0x8000 + 0x7fff * (stages == 1); - pfill = 0xffff - pbase; - buf_secs = 16; /* Must not be more than 16 */ - num_bufs = size / buf_secs / 2048; - if (num_bufs > 0x7fffffff) { - d->cancel = 1; - goto ex; - } - - /* <<< */ - sprintf(msg, - "Writing %.f sectors of zeros to formatted media", - (double) num_bufs * (double) buf_secs); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - msg, 0, 0); - - d->buffer = &buf; - memset(d->buffer, 0, sizeof(struct buffer)); - d->buffer->bytes = buf_secs * 2048; - d->buffer->sectors = buf_secs; - d->busy = BURN_DRIVE_WRITING; - for (i = 0; i < num_bufs; i++) { - d->nwa = i * buf_secs; - err = d->write(d, d->nwa, d->buffer); - if (err == BE_CANCELLED || d->cancel) { - d->cancel = 1; - break; - } - d->progress.sector = pbase - + pfill * ((double) i / (double) num_bufs); - } - d->sync_cache(d); - if (d->current_profile == 0x13 || d->current_profile == 0x1a) { - /* DVD-RW or DVD+RW */ - d->busy = BURN_DRIVE_CLOSING_SESSION; - /* CLOSE SESSION, 010b */ - d->close_track_session(d, 1, 0); - d->busy = BURN_DRIVE_WRITING; - } - } -ex:; - d->progress.sector = 0x10000; - d->busy = BURN_DRIVE_IDLE; - d->buffer = NULL; -} - - -/* ts A70112 API */ -int burn_disc_get_formats(struct burn_drive *d, int *status, off_t *size, - unsigned *bl_sas, int *num_formats) -{ - int ret; - - *status = 0; - *size = 0; - *bl_sas = 0; - *num_formats = 0; - if (d->drive_role != 1) - return 0; - ret = d->read_format_capacities(d, 0x00); - if (ret <= 0) - return 0; - *status = d->format_descr_type; - *size = d->format_curr_max_size; - *bl_sas = d->format_curr_blsas; - *num_formats = d->num_format_descr; - return 1; -} - - -/* ts A70112 API */ -int burn_disc_get_format_descr(struct burn_drive *d, int index, - int *type, off_t *size, unsigned *tdp) -{ - *type = 0; - *size = 0; - *tdp = 0; - if (index < 0 || index >= d->num_format_descr) - return 0; - *type = d->format_descriptors[index].type; - *size = d->format_descriptors[index].size; - *tdp = d->format_descriptors[index].tdp; - return 1; -} - - -enum burn_disc_status burn_disc_get_status(struct burn_drive *d) -{ - /* ts A61007 */ - /* a ssert(!d->released); */ - if (d->released) { - libdax_msgs_submit(libdax_messenger, - d->global_index, 0x00020108, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Drive is not grabbed on disc status inquiry", - 0, 0); - return BURN_DISC_UNGRABBED; - } - - return d->status; -} - -int burn_disc_erasable(struct burn_drive *d) -{ - return d->erasable; -} -enum burn_drive_status burn_drive_get_status(struct burn_drive *d, - struct burn_progress *p) -{ - /* ts A70928 : inform control thread of signal in sub-threads */ - if (burn_global_abort_level > 0) - burn_global_abort_level++; - if (burn_global_abort_level > 5) { - if (burn_global_signal_handler == NULL) - kill(getpid(), burn_global_abort_signum); - else - (*burn_global_signal_handler) - (burn_global_signal_handle, - burn_global_abort_signum, 0); - burn_global_abort_level = -1; - } - - if (p != NULL) { - memcpy(p, &(d->progress), sizeof(struct burn_progress)); - /* TODO: add mutex */ - } - return d->busy; -} - -void burn_drive_cancel(struct burn_drive *d) -{ - pthread_mutex_lock(&d->access_lock); - d->cancel = 1; - pthread_mutex_unlock(&d->access_lock); -} - -/* ts A61007 : defunct because unused */ -#if 0 -int burn_drive_get_block_types(struct burn_drive *d, - enum burn_write_types write_type) -{ - burn_print(12, "write type: %d\n", write_type); - a ssert( /* (write_type >= BURN_WRITE_PACKET) && */ - (write_type <= BURN_WRITE_RAW)); - return d->block_types[write_type]; -} -#endif - -static void strip_spaces(char *str) -{ - char *tmp; - - tmp = str + strlen(str) - 1; - while (isspace(*tmp)) - *(tmp--) = '\0'; - - tmp = str; - while (*tmp) { - if (isspace(*tmp) && isspace(*(tmp + 1))) { - char *tmp2; - - for (tmp2 = tmp + 1; *tmp2; ++tmp2) - *(tmp2 - 1) = *tmp2; - *(tmp2 - 1) = '\0'; - } else - ++tmp; - } -} - -static int drive_getcaps(struct burn_drive *d, struct burn_drive_info *out) -{ - struct burn_scsi_inquiry_data *id; - - /* ts A61007 : now prevented in enumerate_common() */ -#if 0 - a ssert(d->idata); - a ssert(d->mdata); -#endif - - if (!d->idata->valid || !d->mdata->valid) - return 0; - - id = (struct burn_scsi_inquiry_data *)d->idata; - - memcpy(out->vendor, id->vendor, sizeof(id->vendor)); - strip_spaces(out->vendor); - memcpy(out->product, id->product, sizeof(id->product)); - strip_spaces(out->product); - memcpy(out->revision, id->revision, sizeof(id->revision)); - strip_spaces(out->revision); - strncpy(out->location, d->devname, 16); - out->location[16] = '\0'; - out->buffer_size = d->mdata->buffer_size; - out->read_dvdram = !!d->mdata->dvdram_read; - out->read_dvdr = !!d->mdata->dvdr_read; - out->read_dvdrom = !!d->mdata->dvdrom_read; - out->read_cdr = !!d->mdata->cdr_read; - out->read_cdrw = !!d->mdata->cdrw_read; - out->write_dvdram = !!d->mdata->dvdram_write; - out->write_dvdr = !!d->mdata->dvdr_write; - out->write_cdr = !!d->mdata->cdr_write; - out->write_cdrw = !!d->mdata->cdrw_write; - out->write_simulate = !!d->mdata->simulate; - out->c2_errors = !!d->mdata->c2_pointers; - out->drive = d; - /* update available block types for burners */ - if (out->write_dvdram || out->write_dvdr || - out->write_cdrw || out->write_cdr) - d->probe_write_modes(d); - out->tao_block_types = d->block_types[BURN_WRITE_TAO]; - out->sao_block_types = d->block_types[BURN_WRITE_SAO]; - out->raw_block_types = d->block_types[BURN_WRITE_RAW]; - out->packet_block_types = d->block_types[BURN_WRITE_PACKET]; - return 1; -} - - -/* ts A70907 : added parameter flag */ -/* @param flag bit0= reset global drive list */ -int burn_drive_scan_sync(struct burn_drive_info *drives[], - unsigned int *n_drives, int flag) -{ - /* ts A70907 : - There seems to have been a misunderstanding about the role of - burn_drive_scan_sync(). It needs no static state because it - is only started once during an asynchronous scan operation. - Its starter, burn_drive_scan(), is the one which ends immediately - and gets called repeatedly. It acts on start of scanning by - calling burn_drive_scan_sync(), returns idle while scanning is - not done and finally removes the worker object which represented - burn_drive_scan_sync(). - The scanning itself is not parallel but enumerates sequentially - drive by drive (within scsi_enumerate_drives()). - - I will use "scanned" for marking drives found by previous runs. - It will not be static any more. - */ - /* ts A71015 : this makes only trouble : static int scanning = 0; */ - /* ts A70907 : - These variables are too small anyway. We got up to 255 drives. - static int scanned = 0, found = 0; - Variable "found" was only set but never read. - */ - unsigned char scanned[32]; - unsigned count = 0; - int i; - - /* ts A61007 : moved up to burn_drive_scan() */ - /* a ssert(burn_running); */ - - - /* ts A61007 : test moved up to burn_drive_scan() - burn_wait_all() is obsoleted */ -#if 0 - /* make sure the drives aren't in use */ - burn_wait_all(); /* make sure the queue cleans up - before checking for the released - state */ -#endif /* 0 */ - - *n_drives = 0; - - /* ts A70907 : wether to scan from scratch or to extend */ - for (i = 0; i < sizeof(scanned); i++) - scanned[i] = 0; - if (flag & 1) { - burn_drive_free_all(); - } else { - for (i = 0; i <= drivetop; i++) - if (drive_array[i].global_index >= 0) - scanned[i / 8] |= (1 << (i % 8)); - } - - /* refresh the lib's drives */ - - /* ts A61115 : formerly sg_enumerate(); ata_enumerate(); */ - scsi_enumerate_drives(); - - count = burn_drive_count(); - if (count) { - /* ts A70907 : - Extra array element marks end of array. */ - *drives = calloc(count + 1, - sizeof(struct burn_drive_info)); - if (*drives == NULL) { - libdax_msgs_submit(libdax_messenger, -1, 0x00000003, - LIBDAX_MSGS_SEV_FATAL, - LIBDAX_MSGS_PRIO_HIGH, - "Out of virtual memory", 0, 0); - return -1; - } else - for (i = 0; i <= count; i++) /* invalidate */ - (*drives)[i].drive = NULL; - } else - *drives = NULL; - - for (i = 0; i < count; ++i) { - if (scanned[i / 8] & (1 << (i % 8))) - continue; /* device already scanned by previous run */ - if (drive_array[i].global_index < 0) - continue; /* invalid device */ - - while (!drive_getcaps(&drive_array[i], - &(*drives)[*n_drives])) { - sleep(1); - } - (*n_drives)++; - scanned[i / 8] |= 1 << (i % 8); - } - - return(1); -} - -/* ts A61001 : internal call */ -int burn_drive_forget(struct burn_drive *d, int force) -{ - int occup; - - occup = burn_drive_is_occupied(d); -/* - fprintf(stderr, "libburn: experimental: occup == %d\n",occup); -*/ - if(occup <= -2) - return 2; - if(occup > 0) - if(force < 1) - return 0; - if(occup > 10) - return 0; - - /* >>> do any drive calming here */; - - - burn_drive_force_idle(d); - if(occup > 0 && !burn_drive_is_released(d)) - burn_drive_release(d,0); - burn_drive_free(d); - return 1; -} - -/* API call */ -int burn_drive_info_forget(struct burn_drive_info *info, int force) -{ - return burn_drive_forget(info->drive, force); -} - - -void burn_drive_info_free(struct burn_drive_info drive_infos[]) -{ - int i; - -/* ts A60904 : ticket 62, contribution by elmom */ -/* clarifying the meaning and the identity of the victim */ - - if(drive_infos == NULL) - return; - -#ifndef Libburn_free_all_drives_on_infO - -#ifdef Not_yeT - int new_drivetop; - - /* ts A71015: compute reduced drivetop counter */ - new_drivetop = drivetop; - for (i = 0; drive_infos[i].drive != NULL; i++) - if (drive_infos[i].global_index == new_drivetop - && new_drivetop >= 0) { - new_drivetop--; - i = 0; - } -#endif /* Not_yeT */ - - /* ts A70907 : Solution for wrong behavior below */ - for (i = 0; drive_infos[i].drive != NULL; i++) - burn_drive_free(drive_infos[i].drive); - -#ifdef Not_yeT - drivetop = new_drivetop; -#endif /* Not_yeT */ - -#endif /* ! Libburn_free_all_drives_on_infO */ - - /* ts A60904 : This looks a bit weird. [ts A70907 : not any more] - burn_drive_info is not the manager of burn_drive but only its - spokesperson. To my knowlege drive_infos from burn_drive_scan() - are not memorized globally. */ - free((void *) drive_infos); - -#ifdef Libburn_free_all_drives_on_infO - /* ts A70903 : THIS IS WRONG ! (disabled now) - It endangers multi drive usage. - This call is not entitled to delete all drives, only the - ones of the array which it recieves a parmeter. - - Problem: It was unclear how many items are listed in drive_infos - Solution: Added a end marker element to any burn_drive_info array - The mark can be recognized by having drive == NULL - */ - burn_drive_free_all(); -#endif -} - - -struct burn_disc *burn_drive_get_disc(struct burn_drive *d) -{ - /* ts A61022: SIGSEGV on calling this function with blank media */ - if(d->disc == NULL) - return NULL; - - d->disc->refcnt++; - return d->disc; -} - -void burn_drive_set_speed(struct burn_drive *d, int r, int w) -{ - d->nominal_write_speed = w; - if(d->drive_role != 1) - return; - d->set_speed(d, r, w); -} - - -/* ts A70711 API function */ -int burn_drive_set_buffer_waiting(struct burn_drive *d, int enable, - int min_usec, int max_usec, int timeout_sec, - int min_percent, int max_percent) -{ - - if (enable >= 0) - d->wait_for_buffer_free = !!enable; - if (min_usec >= 0) - d->wfb_min_usec = min_usec; - if (max_usec >= 0) - d->wfb_max_usec = max_usec; - if (timeout_sec >= 0) - d->wfb_timeout_sec = timeout_sec; - if (min_percent >= 0) { - if (min_percent < 25 || min_percent > 100) - return 0; - d->wfb_min_percent = min_percent; - } - if (max_percent >= 0) { - if (max_percent < 25 || max_percent > 100) - return 0; - d->wfb_max_percent = max_percent; - } - return 1; -} - - -int burn_msf_to_sectors(int m, int s, int f) -{ - return (m * 60 + s) * 75 + f; -} - -void burn_sectors_to_msf(int sectors, int *m, int *s, int *f) -{ - *m = sectors / (60 * 75); - *s = (sectors - *m * 60 * 75) / 75; - *f = sectors - *m * 60 * 75 - *s * 75; -} - -int burn_drive_get_read_speed(struct burn_drive *d) -{ - if(!d->mdata->valid) - return 0; - return d->mdata->max_read_speed; -} - -int burn_drive_get_write_speed(struct burn_drive *d) -{ - if(!d->mdata->valid) - return 0; - return d->mdata->max_write_speed; -} - -/* ts A61021 : New API function */ -int burn_drive_get_min_write_speed(struct burn_drive *d) -{ - if(!d->mdata->valid) - return 0; - return d->mdata->min_write_speed; -} - - -/* ts A51221 */ -static char *enumeration_whitelist[BURN_DRIVE_WHITELIST_LEN]; -static int enumeration_whitelist_top = -1; - -/** Add a device to the list of permissible drives. As soon as some entry is in - the whitelist all non-listed drives are banned from enumeration. - @return 1 success, <=0 failure -*/ -int burn_drive_add_whitelist(char *device_address) -{ - char *new_item; - if(enumeration_whitelist_top+1 >= BURN_DRIVE_WHITELIST_LEN) - return 0; - enumeration_whitelist_top++; - new_item = malloc(strlen(device_address) + 1); - if (new_item == NULL) - return -1; - strcpy(new_item, device_address); - enumeration_whitelist[enumeration_whitelist_top] = new_item; - return 1; -} - -/** Remove all drives from whitelist. This enables all possible drives. */ -void burn_drive_clear_whitelist(void) -{ - int i; - for (i = 0; i <= enumeration_whitelist_top; i++) - free(enumeration_whitelist[i]); - enumeration_whitelist_top = -1; -} - -int burn_drive_is_banned(char *device_address) -{ - int i; - if(enumeration_whitelist_top<0) - return 0; - for (i = 0; i <= enumeration_whitelist_top; i++) - if (strcmp(enumeration_whitelist[i], device_address) == 0) - return 0; - return 1; -} - - -/* ts A70924 */ -int burn_drive__fd_from_special_adr(char *adr) -{ - int fd = -1, i; - - if (strcmp(adr, "-") == 0) - fd = 1; - if(strncmp(adr, "/dev/fd/", 8) == 0) { - for (i = 8; adr[i]; i++) - if (!isdigit(adr[i])) - break; - if (i> 8 && adr[i] == 0) - fd = atoi(adr + 8); - } - return fd; -} - - -/* ts A70903 : Implements adquiration of pseudo drives */ -int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname) -{ - int ret = -1, fd = -1, role = 0; - /* divided by 512 it needs to fit into a signed long integer */ - off_t size = ((off_t) (512 * 1024 * 1024 - 1) * (off_t) 2048); - struct burn_drive *d= NULL, *regd_d; - struct stat stbuf; - - static int allow_role_3 = 1; - - if (fname[0] != 0) { - memset(&stbuf, 0, sizeof(stbuf)); - fd = burn_drive__fd_from_special_adr(fname); - if (fd >= 0) - ret = fstat(fd, &stbuf); - else - ret = stat(fname, &stbuf); - if (ret == -1 || S_ISBLK(stbuf.st_mode) || - S_ISREG(stbuf.st_mode)) { - ret = burn_os_stdio_capacity(fname, &size); - if (ret == -1) { - libdax_msgs_submit(libdax_messenger, -1, - 0x00020009, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Neither stdio-path nor its directory exist", - 0, 0); - return 0; - } else if (ret == -2) { - libdax_msgs_submit(libdax_messenger, -1, - 0x00020005, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Failed to open device (a pseudo-drive)", - errno, 0); - return 0; - } - if (fname[0] != 0) - role = 2; - else - role = 0; - } else { - if(S_ISDIR(stbuf.st_mode) || !allow_role_3) { - libdax_msgs_submit(libdax_messenger, -1, - 0x00020149, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Unsuitable filetype for pseudo-drive", 0, 0); - return 0; - } - role = 3; - } - } - d= (struct burn_drive *) calloc(1, sizeof(struct burn_drive)); - if (d == NULL) - return 0; - burn_setup_drive(d, fname); - d->status = BURN_DISC_EMPTY; - - d->drive_role = role; - ret = burn_scsi_setup_drive(d, -1, -1, -1, -1, -1, 0); - if (ret <= 0) - goto ex; - regd_d = burn_drive_register(d); - if (regd_d == NULL) { - ret = -1; - goto ex; - } - free((char *) d); /* all sub pointers have been copied to *regd_d */ - d = regd_d; - if (d->drive_role == 2 || d->drive_role == 3) { - d->status = BURN_DISC_BLANK; - d->current_profile = 0xffff; /* MMC for non-compliant drive */ - strcpy(d->current_profile_text,"stdio file"); - d->current_is_cd_profile = 0; - d->current_is_supported_profile = 1; - d->block_types[BURN_WRITE_TAO] = BURN_BLOCK_MODE1; - d->block_types[BURN_WRITE_SAO] = BURN_BLOCK_SAO; - burn_drive_set_media_capacity_remaining(d, size); - - /* >>> ? open file for a test ? (>>> beware of "-" = stdin) */; - - } else - d->current_profile = 0; /* Drives return this if empty */ - - *drive_infos = calloc(2, sizeof(struct burn_drive_info)); - if (*drive_infos == NULL) - goto ex; - (*drive_infos)[0].drive = d; - (*drive_infos)[1].drive = NULL; /* End-Of-List mark */ - (*drive_infos)[0].tao_block_types = d->block_types[BURN_WRITE_TAO]; - (*drive_infos)[0].sao_block_types = d->block_types[BURN_WRITE_SAO]; - if (d->drive_role == 2) { - strcpy((*drive_infos)[0].vendor,"YOYODYNE"); - strcpy((*drive_infos)[0].product,"WARP DRIVE"); - strcpy((*drive_infos)[0].revision,"FX01"); - } else if (d->drive_role == 3) { - strcpy((*drive_infos)[0].vendor,"YOYODYNE"); - strcpy((*drive_infos)[0].product,"BLACKHOLE"); - strcpy((*drive_infos)[0].revision,"FX02"); - } else { - strcpy((*drive_infos)[0].vendor,"FERENGI"); - strcpy((*drive_infos)[0].product,"VAPORWARE"); - strcpy((*drive_infos)[0].revision,"0000"); - } - d->released = 0; - ret = 1; -ex:; - if (ret <= 0 && d != NULL) { - burn_drive_free_subs(d); - free((char *) d); - } - return ret; -} - - -/* ts A60823 */ -/** Aquire a drive with known persistent address. -*/ -int burn_drive_scan_and_grab(struct burn_drive_info *drive_infos[], char* adr, - int load) -{ - unsigned int n_drives; - int ret, i; - - /* check wether drive adress is already registered */ - for (i = 0; i <= drivetop; i++) - if (drive_array[i].global_index >= 0) - if (strcmp(drive_array[i].devname, adr) == 0) - break; - if (i <= drivetop) { - libdax_msgs_submit(libdax_messenger, i, - 0x0002014b, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Drive is already registered resp. scanned", - 0, 0); - return -1; - } - - if (strncmp(adr, "stdio:", 6) == 0) { - ret = burn_drive_grab_dummy(drive_infos, adr + 6); - return ret; - } - - burn_drive_clear_whitelist(); - burn_drive_add_whitelist(adr); -/* - fprintf(stderr,"libburn: experimental: burn_drive_scan_and_grab(%s)\n", - adr); -*/ - - /* ts A70907 : now calling synchronously rather than looping */ - ret = burn_drive_scan_sync(drive_infos, &n_drives, 0); - if (ret < 0) - return -1; - - if (n_drives <= 0) - return 0; -/* - fprintf(stderr, "libburn: experimental: n_drives %d , drivetop %d\n", - n_drives, drivetop); - if (n_drives > 0) - fprintf(stderr, "libburn: experimental: global_index %d\n", - drive_infos[0]->drive->global_index); -*/ - - ret = burn_drive_grab(drive_infos[0]->drive, load); - if (ret != 1) - return -1; - return 1; -} - -/* ts A60925 */ -/** Simple debug message frontend to libdax_msgs_submit(). - If arg is not NULL, then fmt MUST contain exactly one %s and no - other sprintf() %-formatters. -*/ -int burn_drive_adr_debug_msg(char *fmt, char *arg) -{ - int ret; - char msg[4096], *msgpt; - - msgpt= msg; - if(arg != NULL) - sprintf(msg, fmt, arg); - else - msgpt= fmt; - if(libdax_messenger == NULL) - return 0; - ret = libdax_msgs_submit(libdax_messenger, -1, 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - msgpt, 0, 0); - return ret; -} - -/* ts A60923 */ /* ts A70906 : promoted to API */ -/** Inquire the persistent address of the given drive. */ -int burn_drive_d_get_adr(struct burn_drive *d, char adr[]) -{ - if (strlen(d->devname) >= BURN_DRIVE_ADR_LEN) { - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020110, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "Persistent drive address too long", 0, 0); - return -1; - } - strcpy(adr,d->devname); - return 1; -} - -/* ts A60823 - A60923 */ /* A70906 : Now legacy API call */ -/** Inquire the persistent address of the given drive. */ -int burn_drive_get_adr(struct burn_drive_info *drive_info, char adr[]) -{ - int ret; - - ret = burn_drive_d_get_adr(drive_info->drive, adr); - return ret; -} - - - - -/* ts A60922 ticket 33 */ -/** Evaluate wether the given address would be enumerated by libburn */ -int burn_drive_is_enumerable_adr(char *adr) -{ - return sg_is_enumerable_adr(adr); -} - -#define BURN_DRIVE_MAX_LINK_DEPTH 20 - -/* ts A60922 ticket 33 */ -int burn_drive_resolve_link(char *path, char adr[], int *recursion_count) -{ - int ret; - char link_target[4096], msg[4096+100], link_adr[4096], *adrpt; - - burn_drive_adr_debug_msg("burn_drive_resolve_link( %s )", path); - if (*recursion_count >= BURN_DRIVE_MAX_LINK_DEPTH) { - burn_drive_adr_debug_msg( - "burn_drive_resolve_link aborts because link too deep", - NULL); - return 0; - } - (*recursion_count)++; - ret = readlink(path, link_target, sizeof(link_target)); - if (ret == -1) { - burn_drive_adr_debug_msg("readlink( %s ) returns -1", path); - return 0; - } - if (ret >= sizeof(link_target) - 1) { - sprintf(msg,"readlink( %s ) returns %d (too much)", path, ret); - burn_drive_adr_debug_msg(msg, NULL); - return -1; - } - link_target[ret] = 0; - adrpt= link_target; - if (link_target[0] != '/') { - strcpy(link_adr, path); - if ((adrpt = strrchr(link_adr, '/')) != NULL) { - strcpy(adrpt + 1, link_target); - adrpt = link_adr; - } else - adrpt = link_target; - } - ret = burn_drive_convert_fs_adr_sub(adrpt, adr, recursion_count); - sprintf(msg,"burn_drive_convert_fs_adr( %s ) returns %d", - link_target, ret); - burn_drive_adr_debug_msg(msg, NULL); - return ret; -} - -/* ts A60922 - A61014 ticket 33 */ -/* Try to find an enumerated address with the given stat.st_rdev number */ -int burn_drive_find_devno(dev_t devno, char adr[]) -{ - char fname[4096], msg[4096+100]; - int ret = 0, first = 1; - struct stat stbuf; - burn_drive_enumerator_t enm; - - while (1) { - ret = sg_give_next_adr(&enm, fname, sizeof(fname), first); - if(ret <= 0) - break; - first = 0; - ret = stat(fname, &stbuf); - if(ret == -1) - continue; - if(devno != stbuf.st_rdev) - continue; - if(strlen(fname) >= BURN_DRIVE_ADR_LEN) - return -1; - - sprintf(msg, "burn_drive_find_devno( 0x%lX ) found %s", - (long) devno, fname); - burn_drive_adr_debug_msg(msg, NULL); - strcpy(adr, fname); - { ret = 1; goto ex;} - } - ret = 0; -ex:; - if (first == 0) - sg_give_next_adr(&enm, fname, sizeof(fname), -1); - return ret; -} - -/* ts A60923 */ -/** Try to obtain host,channel,target,lun from path. - @return 1 = success , 0 = failure , -1 = severe error -*/ -int burn_drive_obtain_scsi_adr(char *path, - int *bus_no, int *host_no, int *channel_no, - int *target_no, int *lun_no) -{ - int ret, i; - char adr[BURN_DRIVE_ADR_LEN]; - - /* open drives cannot be inquired by sg_obtain_scsi_adr() */ - for (i = 0; i < drivetop + 1; i++) { - if (drive_array[i].global_index < 0) - continue; - ret = burn_drive_d_get_adr(&(drive_array[i]),adr); - if (ret < 0) - return -1; - if (ret == 0) - continue; - if (strcmp(adr, path) == 0) { - *host_no = drive_array[i].host; - *channel_no = drive_array[i].channel; - *target_no = drive_array[i].id; - *lun_no = drive_array[i].lun; - *bus_no = drive_array[i].bus_no; - if (*host_no < 0 || *channel_no < 0 || - *target_no < 0 || *lun_no < 0) - return 0; - return 1; - } - } - - ret = sg_obtain_scsi_adr(path, bus_no, host_no, channel_no, - target_no, lun_no); - return ret; -} - -/* ts A60923 */ -int burn_drive_convert_scsi_adr(int bus_no, int host_no, int channel_no, - int target_no, int lun_no, char adr[]) -{ - char fname[4096],msg[4096+100]; - int ret = 0, first = 1, i_bus_no = -1; - int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1; - burn_drive_enumerator_t enm; - - sprintf(msg,"burn_drive_convert_scsi_adr( %d,%d,%d,%d,%d )", - bus_no, host_no, channel_no, target_no, lun_no); - burn_drive_adr_debug_msg(msg, NULL); - - while (1) { - ret= sg_give_next_adr(&enm, fname, sizeof(fname), first); - if(ret <= 0) - break; - first = 0; - ret = burn_drive_obtain_scsi_adr(fname, &i_bus_no, &i_host_no, - &i_channel_no, &i_target_no, &i_lun_no); - if(ret <= 0) - continue; - if(bus_no >=0 && i_bus_no != bus_no) - continue; - if(host_no >=0 && i_host_no != host_no) - continue; - if(channel_no >= 0 && i_channel_no != channel_no) - continue; - if(target_no >= 0 && i_target_no != target_no) - continue; - if(lun_no >= 0 && i_lun_no != lun_no) - continue; - if(strlen(fname) >= BURN_DRIVE_ADR_LEN) - { ret = -1; goto ex;} - burn_drive_adr_debug_msg( - "burn_drive_convert_scsi_adr() found %s", fname); - strcpy(adr, fname); - { ret = 1; goto ex;} - } - ret = 0; -ex:; - if (first == 0) - sg_give_next_adr(&enm, fname, sizeof(fname), -1); - return ret; -} - -/* ts A60922 ticket 33 */ -/* Try to find an enumerated address with the same host,channel,target,lun - as path */ -int burn_drive_find_scsi_equiv(char *path, char adr[]) -{ - int ret = 0; - int bus_no, host_no, channel_no, target_no, lun_no; - char msg[4096]; - - ret = burn_drive_obtain_scsi_adr(path, &bus_no, &host_no, &channel_no, - &target_no, &lun_no); - if(ret <= 0) { - sprintf(msg,"burn_drive_obtain_scsi_adr( %s ) returns %d", - path, ret); - burn_drive_adr_debug_msg(msg, NULL); - return 0; - } - sprintf(msg, "burn_drive_find_scsi_equiv( %s ) : (%d),%d,%d,%d,%d", - path, bus_no, host_no, channel_no, target_no, lun_no); - burn_drive_adr_debug_msg(msg, NULL); - - ret= burn_drive_convert_scsi_adr(-1, host_no, channel_no, target_no, - lun_no, adr); - return ret; -} - - -/* ts A60922 ticket 33 */ -/** Try to convert a given existing filesystem address into a persistent drive - address. */ -int burn_drive_convert_fs_adr_sub(char *path, char adr[], int *rec_count) -{ - int ret; - struct stat stbuf; - - burn_drive_adr_debug_msg("burn_drive_convert_fs_adr( %s )", path); - if (strncmp(path, "stdio:", 6) == 0 || - burn_drive_is_enumerable_adr(path)) { - if(strlen(path) >= BURN_DRIVE_ADR_LEN) - return -1; - burn_drive_adr_debug_msg( - "burn_drive_is_enumerable_adr( %s ) is true", path); - strcpy(adr, path); - return 1; - } - - if(lstat(path, &stbuf) == -1) { - burn_drive_adr_debug_msg("lstat( %s ) returns -1", path); - return 0; - } - if((stbuf.st_mode & S_IFMT) == S_IFLNK) { - ret = burn_drive_resolve_link(path, adr, rec_count); - if(ret > 0) - return 1; - burn_drive_adr_debug_msg("link fallback via stat( %s )", path); - if(stat(path, &stbuf) == -1) { - burn_drive_adr_debug_msg("stat( %s ) returns -1",path); - return 0; - } - } - if((stbuf.st_mode&S_IFMT) == S_IFBLK || - (stbuf.st_mode&S_IFMT) == S_IFCHR) { - ret = burn_drive_find_devno(stbuf.st_rdev, adr); - if(ret > 0) - return 1; - ret = burn_drive_find_scsi_equiv(path, adr); - if(ret > 0) - return 1; - } - burn_drive_adr_debug_msg("Nothing found for %s", path); - return 0; -} - -/** Try to convert a given existing filesystem address into a persistent drive - address. */ -int burn_drive_convert_fs_adr(char *path, char adr[]) -{ - int ret, rec_count = 0; - - ret = burn_drive_convert_fs_adr_sub(path, adr, &rec_count); - return ret; -} - - -/** A pacifier function suitable for burn_abort. - @param handle If not NULL, a pointer to a text suitable for printf("%s") -*/ -int burn_abort_pacifier(void *handle, int patience, int elapsed) -{ - char *prefix= "libburn : "; - - if(handle!=NULL) - prefix= handle; - fprintf(stderr, - "\r%sABORT : Waiting for drive to finish ( %d s, %d max)", - (char *) prefix, elapsed, patience); - return(1); -} - - -/** Abort any running drive operation and finish libburn. - @param patience Maximum number of seconds to wait for drives to finish - @param pacifier_func Function to produce appeasing messages. See - burn_abort_pacifier() for an example. - @return 1 ok, all went well - 0 had to leave a drive in unclean state - <0 severe error, do no use libburn again -*/ -int burn_abort(int patience, - int (*pacifier_func)(void *handle, int patience, int elapsed), - void *handle) -{ - int ret, i, occup, still_not_done= 1, pacifier_off= 0, first_round= 1; - unsigned long wait_grain= 100000; - time_t start_time, current_time, pacifier_time, end_time; - - current_time = start_time = pacifier_time = time(0); - end_time = start_time + patience; - - /* >>> ts A71002 : are there any threads at work ? - If not, then one can force abort because the drives will not - change status on their own. - */ - - while(current_time-end_time < patience) { - still_not_done = 0; - - for(i = 0; i < drivetop + 1; i++) { - occup = burn_drive_is_occupied(&(drive_array[i])); - if(occup == -2) - continue; - if(drive_array[i].drive_role != 1) { - drive_array[i].busy = BURN_DRIVE_IDLE; - burn_drive_forget(&(drive_array[i]), 1); - } else if(occup <= 10) { - burn_drive_forget(&(drive_array[i]), 1); - } else if(occup <= 100) { - if(first_round) - burn_drive_cancel(&(drive_array[i])); - still_not_done++; - } else if(occup <= 1000) { - still_not_done++; - } - } - first_round = 0; - - if(still_not_done == 0) - break; - usleep(wait_grain); - current_time = time(0); - if(current_time>pacifier_time) { - if(pacifier_func != NULL && !pacifier_off) { - ret = (*pacifier_func)(handle, patience, - current_time-start_time); - pacifier_off = (ret <= 0); - } - pacifier_time = current_time; - } - } - burn_finish(); - return(still_not_done == 0); -} - - -/* ts A61020 API function */ -int burn_drive_get_start_end_lba(struct burn_drive *d, - int *start_lba, int *end_lba, int flag) -{ - if (d->start_lba == -2000000000 || d->end_lba == -2000000000) - return 0; - *start_lba = d->start_lba; - *end_lba= d->end_lba; - return 1; -} - - -/* ts A61020 API function */ -int burn_disc_pretend_blank(struct burn_drive *d) -{ - if (d->drive_role == 0) - return 0; - if (d->status != BURN_DISC_UNREADY && - d->status != BURN_DISC_UNSUITABLE) - return 0; - d->status = BURN_DISC_BLANK; - return 1; -} - -/* ts A61106 API function */ -int burn_disc_pretend_full(struct burn_drive *d) -{ - if (d->drive_role == 0) - return 0; - if (d->status != BURN_DISC_UNREADY && - d->status != BURN_DISC_UNSUITABLE) - return 0; - d->status = BURN_DISC_FULL; - return 1; -} - -/* ts A61021: new API function */ -int burn_disc_read_atip(struct burn_drive *d) -{ - if (burn_drive_is_released(d)) { - libdax_msgs_submit(libdax_messenger, - d->global_index, 0x0002010e, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "Attempt to read ATIP from ungrabbed drive", - 0, 0); - return -1; - } - if(d->drive_role != 1) - return 0; - if (d->current_profile == -1 || d->current_is_cd_profile) { - d->read_atip(d); - /* >>> some control of success would be nice :) */ - } else { - /* mmc5r03c.pdf 6.26.3.6.3 : ATIP is undefined for non-CD */; - return 0; - } - return 1; -} - -/* ts A61110 : new API function */ -int burn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o, - int trackno, int *lba, int *nwa) -{ - int ret; - - if (burn_drive_is_released(d)) { - libdax_msgs_submit(libdax_messenger, - d->global_index, 0x0002011b, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "Attempt to read track info from ungrabbed drive", - 0, 0); - return -1; - } - if (d->busy != BURN_DRIVE_IDLE) { - libdax_msgs_submit(libdax_messenger, - d->global_index, 0x0002011c, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "Attempt to read track info from busy drive", - 0, 0); - return -1; - } - *lba = *nwa = 0; - if (d->drive_role != 1) - return 0; - if (o != NULL) - d->send_write_parameters(d, o); - ret = d->get_nwa(d, trackno, lba, nwa); - return ret; -} - - -/* ts A70131 : new API function */ -int burn_disc_get_msc1(struct burn_drive *d, int *start) -{ - int ret, trackno; - - if (burn_drive_is_released(d)) { - libdax_msgs_submit(libdax_messenger, - d->global_index, 0x0002011b, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "Attempt to read track info from ungrabbed drive", - 0, 0); - return -1; - } - if (d->busy != BURN_DRIVE_IDLE) { - libdax_msgs_submit(libdax_messenger, - d->global_index, 0x0002011c, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "Attempt to read track info from busy drive", - 0, 0); - return -1; - } - *start = 0; - if (d->drive_role != 1) - return 0; - ret = d->read_multi_session_c1(d, &trackno, start); - return ret; -} - - -/* ts A70213 : new API function */ -off_t burn_disc_available_space(struct burn_drive *d, - struct burn_write_opts *o) -{ - int lba, nwa; - - if (burn_drive_is_released(d)) - return 0; - if (d->busy != BURN_DRIVE_IDLE) - return 0; - if (d->drive_role == 0) - return 0; - if (d->drive_role != 1) { - if (d->media_capacity_remaining <= 0) - burn_drive_set_media_capacity_remaining(d, - (off_t) (512 * 1024 * 1024 - 1) * (off_t) 2048); - } else { - if (o != NULL) - d->send_write_parameters(d, o); - d->get_nwa(d, -1, &lba, &nwa); - } - if (o != NULL) { - if (o->start_byte > 0) { - if (o->start_byte > d->media_capacity_remaining) - return 0; - return d->media_capacity_remaining - o->start_byte; - } - } - return d->media_capacity_remaining; -} - - -/* ts A61202 : New API function */ -int burn_disc_get_profile(struct burn_drive *d, int *pno, char name[80]) -{ - *pno = d->current_profile; - strcpy(name,d->current_profile_text); - return *pno >= 0; -} - - -/* ts A61223 : New API function */ -int burn_drive_wrote_well(struct burn_drive *d) -{ - return !d->cancel; -} - - -/* ts A61226 */ -int burn_speed_descriptor_new(struct burn_speed_descriptor **s, - struct burn_speed_descriptor *prev, - struct burn_speed_descriptor *next, int flag) -{ - struct burn_speed_descriptor *o; - - (*s) = o = malloc(sizeof(struct burn_speed_descriptor)); - if (o == NULL) - return -1; - o->source = 0; - o->profile_loaded = -2; - o->profile_name[0] = 0; - o->wrc = 0; - o->exact = 0; - o->mrw = 0; - o->end_lba = -1; - o->write_speed = 0; - o->read_speed = 0; - - o->prev = prev; - if (prev != NULL) { - next = prev->next; - prev->next = o; - } - o->next = next; - if (next != NULL) - next->prev = o; - return 1; -} - - -/* ts A61226 */ -/* @param flag bit0= destroy whole next-chain of descriptors */ -int burn_speed_descriptor_destroy(struct burn_speed_descriptor **s, int flag) -{ - struct burn_speed_descriptor *next, *o; - - if ((*s) == NULL) - return 0; - if (flag&1) - for (o = (*s); o->prev != NULL; o = o->prev); - else - o = (*s); - next = o->next; - if (next != NULL) - next->prev = o->prev; - if (o->prev != NULL) - o->prev->next = next; - free((char *) (*s)); - (*s) = NULL; - if (flag&1) - return burn_speed_descriptor_destroy(&next, flag&1); - return 1; -} - - -/* ts A61226 */ -int burn_speed_descriptor_copy(struct burn_speed_descriptor *from, - struct burn_speed_descriptor *to, int flag) -{ - to->source = from->source; - to->profile_loaded = from->profile_loaded; - strcpy(to->profile_name, from->profile_name); - to->wrc = from->wrc; - to->exact = from->exact; - to->mrw = from->mrw; - to->end_lba = from->end_lba; - to->write_speed = from->write_speed; - to->read_speed = from->read_speed; - return 1; -} - - -/* ts A61226 : free dynamically allocated sub data of struct scsi_mode_data */ -int burn_mdata_free_subs(struct scsi_mode_data *m) -{ - if(!m->valid) - return 0; - burn_speed_descriptor_destroy(&(m->speed_descriptors), 1); - return 1; -} - - -/* ts A61226 : API function */ -int burn_drive_get_speedlist(struct burn_drive *d, - struct burn_speed_descriptor **speed_list) -{ - int ret; - struct burn_speed_descriptor *sd, *csd = NULL; - - (*speed_list) = NULL; - if(!d->mdata->valid) - return 0; - for (sd = d->mdata->speed_descriptors; sd != NULL; sd = sd->next) { - ret = burn_speed_descriptor_new(&csd, NULL, csd, 0); - if (ret <= 0) - return -1; - burn_speed_descriptor_copy(sd, csd, 0); - } - (*speed_list) = csd; - return (csd != NULL); -} - - -/* ts A70713 : API function */ -int burn_drive_get_best_speed(struct burn_drive *d, int speed_goal, - struct burn_speed_descriptor **best_descr, int flag) -{ - struct burn_speed_descriptor *sd; - int best_speed = 0, best_lba = 0, source= 2, speed; - - if (flag & 2) - source = -1; - if (speed_goal < 0) - best_speed = 2000000000; - *best_descr = NULL; - if(!d->mdata->valid) - return 0; - for (sd = d->mdata->speed_descriptors; sd != NULL; sd = sd->next) { - if (flag & 1) - speed = sd->read_speed; - else - speed = sd->write_speed; - if ((source >= 0 && sd->source != source) || - speed <= 0) - continue; - if (speed_goal < 0) { - if (speed < best_speed) { - best_speed = speed; - *best_descr = sd; - } - } else if (speed_goal == 0) { - if ((source == 2 && sd->end_lba > best_lba) || - ((source !=2 || sd->end_lba == best_lba) && - speed > best_speed)) { - best_lba = sd->end_lba; - best_speed = speed; - *best_descr = sd; - } - } else if (speed <= speed_goal) { - if (speed > best_speed) { - best_speed = speed; - *best_descr = sd; - } - } - } - if (d->current_is_cd_profile && *best_descr == NULL && ! (flag & 2)) - /* Mode page 2Ah is deprecated in MMC-5 although all known - burners still support it with CD media. */ - return burn_drive_get_best_speed(d, speed_goal, best_descr, - flag | 2); - return (*best_descr != NULL); -} - - -/* ts A61226 : API function */ -int burn_drive_free_speedlist(struct burn_speed_descriptor **speed_list) -{ - return burn_speed_descriptor_destroy(speed_list, 1); -} - - -/* ts A70203 : API function */ -int burn_disc_get_multi_caps(struct burn_drive *d, enum burn_write_types wt, - struct burn_multi_caps **caps, int flag) -{ - enum burn_disc_status s; - struct burn_multi_caps *o; - int status, num_formats, ret, type, i; - off_t size; - unsigned dummy; - - *caps = NULL; - s = burn_disc_get_status(d); - if(s == BURN_DISC_UNGRABBED) - return -1; - *caps = o = (struct burn_multi_caps *) - malloc(sizeof(struct burn_multi_caps)); - if(*caps == NULL) - return -1; - /* Default says nothing is available */ - o->multi_session = o->multi_track = 0; - o-> start_adr = 0; - o->start_alignment = o->start_range_low = o->start_range_high = 0; - o->might_do_tao = o->might_do_sao = o->might_do_raw = 0; - o->advised_write_mode = BURN_WRITE_NONE; - o->selected_write_mode = wt; - o->current_profile = d->current_profile; - o->current_is_cd_profile = d->current_is_cd_profile; - o->might_simulate = 0; - - if (d->drive_role == 0) - return 0; - if (d->drive_role == 2) { - /* stdio file drive : random access read-write */ - o->start_adr = 1; - size = d->media_capacity_remaining; - burn_os_stdio_capacity(d->devname, &size); - burn_drive_set_media_capacity_remaining(d, size); - o->start_range_high = size; - o->start_alignment = 2048; /* imposting a drive, not a file */ - o->might_do_sao = 4; - o->might_do_tao = 2; - o->advised_write_mode = BURN_WRITE_TAO; - o->might_simulate = 1; - } else if (d->drive_role != 1) { - /* stdio file drive : sequential access write-only */ - o->might_do_sao = 4; - o->might_do_tao = 2; - o->advised_write_mode = BURN_WRITE_TAO; - o->might_simulate = 1; - } else if (s != BURN_DISC_BLANK && s != BURN_DISC_APPENDABLE) { - return 0; - } else if (s == BURN_DISC_APPENDABLE && - (wt == BURN_WRITE_SAO || wt == BURN_WRITE_RAW)) { - return 0; - } else if (wt == BURN_WRITE_RAW && !d->current_is_cd_profile) { - return 0; - } else if (d->current_profile == 0x09 || d->current_profile == 0x0a) { - /* CD-R , CD-RW */ - if (d->block_types[BURN_WRITE_TAO]) { - o->multi_session = o->multi_track = 1; - o->might_do_tao = 2; - if (o->advised_write_mode == BURN_WRITE_NONE) - o->advised_write_mode = BURN_WRITE_TAO; - } - if (d->block_types[BURN_WRITE_SAO]) { - o->multi_session = o->multi_track = 1; - o->might_do_sao = 1; - if (o->advised_write_mode == BURN_WRITE_NONE) - o->advised_write_mode = BURN_WRITE_SAO; - } - if (d->block_types[BURN_WRITE_RAW]) { - o->might_do_raw = 1; - if (o->advised_write_mode == BURN_WRITE_NONE) - o->advised_write_mode = BURN_WRITE_RAW; - } - if (wt == BURN_WRITE_RAW) - o->multi_session = o->multi_track = 0; - else if(wt == BURN_WRITE_NONE || wt == BURN_WRITE_SAO || - wt == BURN_WRITE_TAO) - o->might_simulate = !!d->mdata->simulate; - } else if (d->current_profile == 0x11 || d->current_profile == 0x14 || - d->current_profile == 0x15) { - /* DVD-R , sequential DVD-RW , DVD-R/DL Sequential */ - if (s == BURN_DISC_BLANK) { - o->might_do_sao = 1; - o->advised_write_mode = BURN_WRITE_SAO; - } - if (d->current_has_feat21h) { -#ifndef Libburn_dvd_r_dl_multi_no_close_sessioN - if (d->current_profile != 0x15) -#endif - o->multi_session = 1; - o->multi_track = 1; - o->might_do_tao = 2; - o->advised_write_mode = BURN_WRITE_TAO; - } - if (wt == BURN_WRITE_SAO) - o->multi_session = o->multi_track = 0; - if (wt == BURN_WRITE_NONE || wt == BURN_WRITE_SAO || - wt == BURN_WRITE_TAO) - o->might_simulate = 1; - } else if (d->current_profile == 0x12 || - d->current_profile == 0x13 || - d->current_profile == 0x1a || - d->current_profile == 0x43 - ) { - /* DVD-RAM, overwriteable DVD-RW, DVD+RW, BD-RE */ - o->start_adr = 1; - ret = burn_disc_get_formats(d, &status, &size, &dummy, - &num_formats); - if (ret == 1) { - if (status == BURN_FORMAT_IS_FORMATTED) - o->start_range_high = size; - if (d->current_profile == 0x13) { - o->start_alignment = 32 * 1024; - for (i = 0; i < num_formats; i++) { - ret = burn_disc_get_format_descr(d, i, - &type, &size, &dummy); - if (ret <= 0) - continue; - if (type == 0x13) /* expandable */ - break; - } - if (i >= num_formats) /* not expandable */ - o->start_range_high -= 32 * 1024; - if (o->start_range_high < 0) - o->start_range_high = 0; - } else { - o->start_alignment = 2 * 1024; - if (d->best_format_size - 2048 > - o->start_range_high) - o->start_range_high = - d->best_format_size - 2048; - } - } - o->might_do_sao = 4; - o->might_do_tao = 2; - o->advised_write_mode = BURN_WRITE_TAO; - } else if (d->current_profile == 0x1b || d->current_profile == 0x2b) { - /* DVD+R , DVD+R/DL */ - o->multi_session = o->multi_track = 1; - o->might_do_tao = 2; - o->might_do_sao = 1; - o->advised_write_mode = BURN_WRITE_TAO; - } else /* unknown media */ - return 0; - - if (s == BURN_DISC_APPENDABLE) - o->might_do_sao = o->might_do_raw = 0; - - if (wt == BURN_WRITE_TAO && !o->might_do_tao) - return 0; - else if (wt == BURN_WRITE_SAO && !o->might_do_sao) - return 0; - else if (wt == BURN_WRITE_RAW && !o->might_do_raw) - return 0; - return 1; -} - - -/* ts A70203 : API function */ -int burn_disc_free_multi_caps(struct burn_multi_caps **caps) -{ - if (*caps == NULL) - return 0; - free((char *) *caps); - *caps = NULL; - return 1; -} - - -/* ts A70207 : evaluate write mode related peculiarities of a disc - @param flag bit0= fill_up_media is active -*/ -int burn_disc_get_write_mode_demands(struct burn_disc *disc, - struct burn_write_opts *opts, - struct burn_disc_mode_demands *result, int flag) -{ - struct burn_session *session; - struct burn_track *track; - int i, j, mode, unknown_track_sizes = 0, last_track_is_unknown = 0; - enum burn_disc_status s; - - - memset((char *) result, 0, sizeof(struct burn_disc_mode_demands)); - if (disc == NULL) - return 2; - s = burn_disc_get_status(opts->drive); - if (s == BURN_DISC_APPENDABLE || disc->sessions > 1) - result->will_append = 1; - if (disc->sessions > 1) - result->multi_session = 1; - for (i = 0; i < disc->sessions; i++) { - session = disc->session[i]; - if (session->tracks <= 0) - continue; - mode = session->track[0]->mode; - if (session->tracks > 1) - result->multi_track = 1; - for (j = 0; j < session->tracks; j++) { - track = session->track[j]; - if (burn_track_is_open_ended(track)) { - if (burn_track_get_default_size(track) > 0) { - if (result->unknown_track_size == 0) - result->unknown_track_size = 2; - } else - result->unknown_track_size = 1; - unknown_track_sizes++; - last_track_is_unknown = 1; - } else - last_track_is_unknown = 0; - if (mode != track->mode) - result->mixed_mode = 1; - if (track->mode == BURN_MODE1) { - result->block_types |= BURN_BLOCK_MODE1; - } else if (track->mode == BURN_AUDIO) { - result->audio = 1; - result->block_types |= BURN_BLOCK_RAW0; - result->exotic_track = 1; - } else { - result->block_types |= opts->block_type; - result->exotic_track = 1; - } - } - } - if (flag&1) {/* fill_up_media will define the size of the last track */ - if (unknown_track_sizes == 1 && last_track_is_unknown) - result->unknown_track_size = 0; - } - return (disc->sessions > 0); -} - - -/* ts A70903 : API */ -int burn_drive_get_drive_role(struct burn_drive *d) -{ - return d->drive_role; -} - - -/* ts A70923 - Hands out pointers *dpt to directory path and *npt to basename. - Caution: the last '/' in adr gets replaced by a 0. -*/ -static int burn__split_path(char *adr, char **dpt, char **npt) -{ - *dpt = adr; - *npt = strrchr(*dpt, '/'); - if (*npt == NULL) { - *npt = *dpt; - *dpt = "."; - return 1; - } - **npt = 0; - if(*npt == *dpt) - *dpt = "/"; - (*npt)++; - return 2; -} - - -/* ts A70923 : API */ -int burn_drive_equals_adr(struct burn_drive *d1, char *adr2_in, int role2) -{ - struct stat stbuf1, stbuf2; - char adr1[BURN_DRIVE_ADR_LEN], *adr2 = adr2_in; - char conv_adr1[BURN_DRIVE_ADR_LEN], conv_adr2[BURN_DRIVE_ADR_LEN]; - char *npt1, *dpt1, *npt2, *dpt2; - int role1, stat_ret1, stat_ret2, conv_ret2; - - role1 = burn_drive_get_drive_role(d1); - burn_drive_d_get_adr(d1, adr1); - stat_ret1 = stat(adr1, &stbuf1); - - if (strncmp(adr2, "stdio:", 6) == 0) { - adr2+= 6; - role2 = (!!adr2[0]) * 2; - } - if (strlen(adr2) >= BURN_DRIVE_ADR_LEN) - return -1; - stat_ret2 = stat(adr2, &stbuf2); - conv_ret2 = burn_drive_convert_fs_adr(adr2, conv_adr2); - - /* roles 2 and 3 have the same name space and object interpretation */ - if (role1 == 3) - role1 = 2; - if (role2 == 3) - role2 = 2; - - if (strcmp(adr1, adr2) == 0 && role1 == role2) - return(1); /* equal role and address */ - if (role1 == 1 && role2 == 1) { - /* MMC drive meets wannabe MMC drive */ - if (conv_ret2 <= 0) - return 0; /* no MMC drive at adr2 */ - if (strcmp(adr1, conv_adr2) == 0) - return 1; /* equal real MMC drives */ - return 0; - - } else if (role1 == 0 || role2 == 0) - return 0; /* one null-drive, one not */ - - else if (role1 != 1 && role2 != 1) { - /* pseudo-drive meets file object */ - - if (stat_ret1 == -1 || stat_ret2 == -1) { - if (stat_ret1 != -1 || stat_ret2 != -1) - return 0; /* one adress existing, one not */ - - /* Two non-existing file objects */ - - strcpy(conv_adr1, adr1); - burn__split_path(conv_adr1, &dpt1, &npt1); - strcpy(conv_adr2, adr2); - burn__split_path(conv_adr2, &dpt2, &npt2); - if (strcmp(npt1, npt2)) - return 0; /* basenames differ */ - stat_ret1= stat(adr1, &stbuf1); - stat_ret2= stat(adr2, &stbuf2); - if (stat_ret1 != stat_ret2) - return 0; /* one dir existing, one not */ - - /* Both directories exist. The basenames are equal. - So the adresses are equal if the directories are - equal.*/ - } - if (stbuf1.st_ino == stbuf2.st_ino && - stbuf1.st_dev == stbuf2.st_dev) - return 1; /* same filesystem object */ - - if (S_ISBLK(stbuf1.st_mode) && S_ISBLK(stbuf2.st_mode) && - stbuf1.st_rdev == stbuf2.st_rdev) - return 1; /* same major,minor device number */ - - /* Are both filesystem objects related to the same MMC drive */ - if (conv_ret2 <= 0) - return 0; /* no MMC drive at adr2 */ - if (burn_drive_convert_fs_adr(adr1, conv_adr1) <= 0) - return 0; /* no MMC drive at adr1 */ - if (strcmp(conv_adr1, conv_adr2) == 0) - return 1; /* same MMC drive */ - - return 0; /* all filesystem disguises are checked */ - - } else if (role1 == 1 && role2 != 1) { - /* MMC drive meets file object */ - - if (conv_ret2 <= 0) - return 0; /* no MMC drive at adr2 */ - if (strcmp(adr1, conv_adr2) == 0) - return 1; /* same MMC drive */ - return 0; - - } else if (role1 != 1 && role2 == 1) { - /* stdio-drive meets wannabe MMC drive */ - - if (conv_ret2 <= 0) - return 0; /* no MMC drive at adr2 */ - if (burn_drive_convert_fs_adr(adr1, conv_adr1) <= 0) - return 0; /* no MMC drive at adr1 */ - if (strcmp(conv_adr1, conv_adr2) == 0) - return 1; /* same MMC drive */ - return 0; - - } - return 0; /* now i believe they are really not equal */ -} - - -int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid) -{ - int i; - - for (i = 0; i < drivetop + 1; i++) { - -/* - if (drive_array[i].thread_pid_valid) - fprintf(stderr, "libburn_EXPERIMENTAL : drive %d , thread_pid %d\n", i, drive_array[i].thread_pid); -*/ - - if (drive_array[i].thread_pid_valid && - drive_array[i].thread_pid == pid) { - *d = &(drive_array[i]); - return 1; - } - } - return 0; -} - - -/* ts A80422 : centralizing this setting for debugging purposes -*/ -int burn_drive_set_media_capacity_remaining(struct burn_drive *d, off_t value) -{ - d->media_capacity_remaining = value; - return 1; -} - diff --git a/libburn/drive.h b/libburn/drive.h deleted file mode 100644 index 8441293..0000000 --- a/libburn/drive.h +++ /dev/null @@ -1,128 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef __DRIVE -#define __DRIVE - -#include "libburn.h" -#include "toc.h" -#include "structure.h" - -struct burn_drive; -struct command; -struct mempage; -struct scsi_mode_data; -struct burn_speed_descriptor; - -#define LEAD_IN 1 -#define GAP 2 -#define USER_DATA 3 -#define LEAD_OUT 4 -#define SYNC 5 - -#define SESSION_LEADOUT_ENTRY(d,s) (d)->toc->session[(s)].leadout_entry - -#define CURRENT_SESSION_START(d) \ - burn_msf_to_lba(d->toc->session[d->currsession].start_m, \ - d->toc->session[d->currsession].start_s, \ - d->toc->session[d->currsession].start_f) - -#define SESSION_END(d,s) \ - TOC_ENTRY_PLBA((d)->toc, SESSION_LEADOUT_ENTRY((d), (s))) - -#define PREVIOUS_SESSION_END(d) \ - TOC_ENTRY_PLBA((d)->toc, SESSION_LEADOUT_ENTRY((d), (d)->currsession-1)) - -#define LAST_SESSION_END(d) \ - TOC_ENTRY_PLBA((d)->toc, \ - SESSION_LEADOUT_ENTRY((d), (d)->toc->sessions-1)) - -struct burn_drive *burn_drive_register(struct burn_drive *); -int burn_drive_unregister(struct burn_drive *d); - -unsigned int burn_drive_count(void); - -/* ts A61007 */ -/* void burn_wait_all(void); */ -/* @param flag bit0= demand freed drives (else released drives) */ -int burn_drives_are_clear(int flag); - -int burn_sector_length_write(struct burn_drive *d); -int burn_track_control(struct burn_drive *d, int); -void burn_write_empty_sector(int fd); -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); - -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); - -int burn_drive_is_open(struct burn_drive *d); -int burn_drive_is_occupied(struct burn_drive *d); -int burn_drive_forget(struct burn_drive *d, int force); -int burn_drive_convert_fs_adr_sub(char *path, char adr[], int *rec_count); - -/* ts A61021 : the unspecific part of sg.c:enumerate_common() -*/ -int burn_setup_drive(struct burn_drive *d, char *fname); - -/* ts A61021 : after-setup activities from sg.c:enumerate_common() -*/ -struct burn_drive *burn_drive_finish_enum(struct burn_drive *d); - -/* ts A61125 : media status aspects of burn_drive_grab() */ -int burn_drive_inquire_media(struct burn_drive *d); - -/* ts A61125 : model aspects of burn_drive_release */ -int burn_drive_mark_unready(struct burn_drive *d); - - -/* ts A61226 */ -int burn_speed_descriptor_new(struct burn_speed_descriptor **s, - struct burn_speed_descriptor *prev, - struct burn_speed_descriptor *next, int flag); - -/* ts A61226 */ -/* @param flag bit0= destroy whole next-chain of descriptors */ -int burn_speed_descriptor_destroy(struct burn_speed_descriptor **s, int flag); - - -/* ts A61226 : free dynamically allocated sub data of struct scsi_mode_data */ -int burn_mdata_free_subs(struct scsi_mode_data *m); - - -/* ts A61230 */ -void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag); - - -/* ts A70207 : evaluate write mode related peculiarities of a disc */ -struct burn_disc_mode_demands { - int multi_session; - int multi_track; - int unknown_track_size; /* 0=known, 1=unknown, 2=unknown+defaulted */ - int mixed_mode; - int audio; - int exotic_track; - int block_types; - int will_append; /* because of media state or multi session disc */ -}; -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); - - -#endif /* __DRIVE */ diff --git a/libburn/error.h b/libburn/error.h deleted file mode 100644 index 74d4f68..0000000 --- a/libburn/error.h +++ /dev/null @@ -1,8 +0,0 @@ -/* -*- indent-tabs-mode; t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef __ERROR_H -#define __ERROR_H - -#define BE_CANCELLED 1 - -#endif /* __ERROR_H */ diff --git a/libburn/file.c b/libburn/file.c deleted file mode 100644 index ffa61fd..0000000 --- a/libburn/file.c +++ /dev/null @@ -1,542 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#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 */ - - -/* This is a generic OS oriented function wrapper which compensates - shortcommings of read() in respect to a guaranteed amount of return data. - See man 2 read , paragraph "RETURN VALUE". - Possibly libburn/file.c is not the right storage location for this. - To make it ready for a move, this function is not declared static. -*/ -static int read_full_buffer(int fd, unsigned char *buffer, int size) -{ - int ret,summed_ret = 0; - - /* make safe against partial buffer returns */ - while (1) { - ret = read(fd, buffer + summed_ret, size - summed_ret); - if (ret <= 0) - break; - summed_ret += ret; - if (summed_ret >= size) - break; - } - if (ret < 0) /* error encountered. abort immediately */ - return ret; - return summed_ret; -} - - -static int file_read(struct burn_source *source, - unsigned char *buffer, - int size) -{ - struct burn_source_file *fs = source->data; - - return read_full_buffer(fs->datafd, buffer, size); -} - -static int file_read_sub(struct burn_source *source, - unsigned char *buffer, - int size) -{ - struct burn_source_file *fs = source->data; - - return read_full_buffer(fs->subfd, buffer, size); -} - -static void file_free(struct burn_source *source) -{ - struct burn_source_file *fs = source->data; - - close(fs->datafd); - if (source->read_sub) - close(fs->subfd); - free(fs); -} - -static off_t file_size(struct burn_source *source) -{ - struct stat buf; - struct burn_source_file *fs = source->data; - - if (fs->fixed_size > 0) - return fs->fixed_size; - if (fstat(fs->datafd, &buf) == -1) - return (off_t) 0; - return (off_t) buf.st_size; -} - - -/* ts A70125 */ -static int file_set_size(struct burn_source *source, off_t size) -{ - struct burn_source_file *fs = source->data; - - fs->fixed_size = size; - return 1; -} - - -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; - - if (!path) - return NULL; - fd1 = open(path, O_RDONLY); - if (fd1 == -1) - return NULL; - if (subpath != NULL) { - fd2 = open(subpath, O_RDONLY); - if (fd2 == -1) { - close(fd1); - return NULL; - } - } - 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; - - /* 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; - - src->get_size = file_size; - src->set_size = file_set_size; - src->free_data = file_free; - src->data = fs; - return src; -} - - -/* ts A70126 : removed class burn_source_fd in favor of burn_source_file */ - -struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size) -{ - struct burn_source_file *fs; - struct burn_source *src; - - 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->get_size = file_size; - src->set_size = file_set_size; - src->free_data = file_free; - src->data = fs; - 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; -} - diff --git a/libburn/file.h b/libburn/file.h deleted file mode 100644 index 7d99c64..0000000 --- a/libburn/file.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef BURN__FILE_H -#define BURN__FILE_H - -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 */ diff --git a/libburn/init.c b/libburn/init.c deleted file mode 100644 index 32ecb02..0000000 --- a/libburn/init.c +++ /dev/null @@ -1,416 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#include <unistd.h> - -/* ts A61007 */ -/* #include <a ssert.h> */ - -#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 -#include "back_hacks.h" - -/* ts A60924 : a new message handling facility */ -#include "libdax_msgs.h" -struct libdax_msgs *libdax_messenger= NULL; - - -int burn_running = 0; - -/* ts A60813 : Linux: wether to use O_EXCL on open() of device files */ -int burn_sg_open_o_excl = 1; - -/* ts A70403 : Linux: wether to use fcntl(,F_SETLK,) - after open() of device files */ -int burn_sg_fcntl_f_setlk = 1; - -/* ts A70314 : Linux: what device family to use : - 0= default family - 1= sr - 2= scd - (3= st) - 4= sg -*/ -int burn_sg_use_family = 0; - -/* O_NONBLOCK was hardcoded in enumerate_ata() which i hardly use. - For enumerate_sg() it seems ok. - So it should stay default mode until enumerate_ata() without O_NONBLOCK - has been thoroughly tested. */ -int burn_sg_open_o_nonblock = 1; - -/* wether to take a busy drive as an error */ -/* Caution: this is implemented by a rough hack and eventually leads - to unconditional abort of the process */ -int burn_sg_open_abort_busy = 0; - -/* ts A61002 */ - -#include "cleanup.h" - -/* Parameters for builtin abort handler */ -static char abort_message_prefix[81] = {"libburn : "}; -static pid_t abort_control_pid= 0; -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 */ -int burn_support_untested_profiles = 0; - - -/* ts A60925 : ticket 74 */ -/** Create the messenger object for libburn. */ -int burn_msgs_initialize(void) -{ - int ret; - - if(libdax_messenger == NULL) { - ret = libdax_msgs_new(&libdax_messenger,0); - if (ret <= 0) - return 0; - } - libdax_msgs_set_severities(libdax_messenger, LIBDAX_MSGS_SEV_NEVER, - LIBDAX_MSGS_SEV_FATAL, "libburn: ", 0); - return 1; -} - -/* ts A60924 : ticket 74 : Added use of global libdax_messenger */ -int burn_initialize(void) -{ - int ret; - - if (burn_running) - return 1; - burn_support_untested_profiles = 0; - ret = burn_msgs_initialize(); - if (ret <= 0) - return 0; - burn_running = 1; - return 1; -} - -void burn_finish(void) -{ - /* ts A61007 : assume no messageing system */ - /* a ssert(burn_running); */ - if (!burn_running) - return; - - /* ts A61007 */ - /* burn_wait_all(); */ - if (!burn_drives_are_clear(0)) { - 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); - } - - /* ts A60904 : ticket 62, contribution by elmom : name addon "_all" */ - burn_drive_free_all(); - - /* ts A60924 : ticket 74 */ - libdax_msgs_destroy(&libdax_messenger,0); - - burn_running = 0; -} - - -/* ts A60813 */ -/** API function. See libburn.h */ -void burn_preset_device_open(int exclusive, int blocking, int abort_on_busy) -{ - /* ts A61007 */ - /* a ssert(burn_running); */ - if (!burn_running) - return; - burn_sg_open_o_excl = exclusive & 3; - burn_sg_fcntl_f_setlk = !!(exclusive & 32); - burn_sg_use_family = (exclusive >> 2) & 7; - burn_sg_open_o_nonblock = !blocking; - burn_sg_open_abort_busy = !!abort_on_busy; -} - - -/* ts A60924 : ticket 74 */ -/** Control queueing and stderr printing of messages from libburn. - Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT", - "NOTE", "UPDATE", "DEBUG", "ALL". - @param queue_severity Gives the minimum limit for messages to be queued. - Default: "NEVER". If you queue messages then you - must consume them by burn_msgs_obtain(). - @param print_severity Does the same for messages to be printed directly - to stderr. - @param print_id A text prefix to be printed before the message. - @return >0 for success, <=0 for error - -*/ -int burn_msgs_set_severities(char *queue_severity, - char *print_severity, char *print_id) -{ - int ret, queue_sevno, print_sevno; - - ret = libdax_msgs__text_to_sev(queue_severity, &queue_sevno, 0); - if (ret <= 0) - return 0; - ret = libdax_msgs__text_to_sev(print_severity, &print_sevno, 0); - if (ret <= 0) - return 0; - ret = libdax_msgs_set_severities(libdax_messenger, queue_sevno, - print_sevno, print_id, 0); - if (ret <= 0) - return 0; - return 1; -} - - -/* ts A60924 : ticket 74 */ -#define BURM_MSGS_MESSAGE_LEN 4096 - -/** Obtain the oldest pending libburn message from the queue which has at - least the given minimum_severity. This message and any older message of - lower severity will get discarded from the queue and is then lost forever. - Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT", - "NOTE", "UPDATE", "DEBUG", "ALL". To call with minimum_severity "NEVER" - will discard the whole queue. - @param error_code Will become a unique error code as liste in - libburn/libdax_msgs.h - @param msg_text Must provide at least BURM_MSGS_MESSAGE_LEN bytes. - @param os_errno Will become the eventual errno related to the message - @param severity Will become the severity related to the message and - should provide at least 80 bytes. - @return 1 if a matching item was found, 0 if not, <0 for severe errors -*/ -int burn_msgs_obtain(char *minimum_severity, - int *error_code, char msg_text[], int *os_errno, - char severity[]) -{ - int ret, minimum_sevno, sevno, priority; - char *textpt, *sev_name; - struct libdax_msgs_item *item = NULL; - - ret = libdax_msgs__text_to_sev(minimum_severity, &minimum_sevno, 0); - if (ret <= 0) - return 0; - if (libdax_messenger == NULL) - return 0; - ret = libdax_msgs_obtain(libdax_messenger, &item, minimum_sevno, - LIBDAX_MSGS_PRIO_ZERO, 0); - if (ret <= 0) - goto ex; - ret = libdax_msgs_item_get_msg(item, error_code, &textpt, os_errno, 0); - if (ret <= 0) - goto ex; - strncpy(msg_text, textpt, BURM_MSGS_MESSAGE_LEN-1); - if(strlen(textpt) >= BURM_MSGS_MESSAGE_LEN) - msg_text[BURM_MSGS_MESSAGE_LEN-1] = 0; - - severity[0]= 0; - ret = libdax_msgs_item_get_rank(item, &sevno, &priority, 0); - if(ret <= 0) - goto ex; - ret = libdax_msgs__sev_to_text(sevno, &sev_name, 0); - if(ret <= 0) - goto ex; - strcpy(severity,sev_name); - - ret = 1; -ex: - libdax_msgs_destroy_item(libdax_messenger, &item, 0); - return ret; -} - - -/* 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 - - ret = burn_drive_find_by_thread_pid(&d, getpid()); - if (ret > 0 && d->busy == BURN_DRIVE_WRITING) { - /* This is an active writer thread */ - -#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 - - d->sync_cache(d); - - /* >>> perform a more qualified end of burn process */; - - d->busy = BURN_DRIVE_IDLE; - - 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; - } - -#else - usleep(1000000); /* calm down */ - return -2; -#endif /* ! Libburn_new_thread_signal_handleR */ - - } - burn_global_abort_level = -1; - Cleanup_set_handlers(NULL, NULL, 2); - fprintf(stderr,"%sABORT : Trying to shut down drive and library\n", - abort_message_prefix); - fprintf(stderr, - "%sABORT : Wait the normal burning time before any kill -9\n", - abort_message_prefix); - close(0); /* somehow stdin as input blocks abort until EOF */ - - burn_abort(4440, burn_abort_pacifier, abort_message_prefix); - - fprintf(stderr, - "\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); -} - -void burn_set_signal_handling(void *handle, burn_abort_handler_t handler, - int mode) -{ - if(handler == NULL && mode == 0) { - handler = burn_builtin_abort_handler; -/* - fprintf(stderr, "libburn_experimental: activated burn_builtin_abort_handler() with handle '%s'\n",(handle==NULL ? "libburn : " : (char *) handle)); -*/ - - } - strcpy(abort_message_prefix, "libburn : "); - if(handle != NULL) - strncpy(abort_message_prefix, (char *) handle, - sizeof(abort_message_prefix)-1); - abort_message_prefix[sizeof(abort_message_prefix)-1] = 0; - abort_control_pid = getpid(); - Cleanup_set_handlers(handle, (Cleanup_app_handler_T) handler, mode|4); - burn_global_signal_handle = handle; - burn_global_signal_handler = handler; -} - - -/* ts A70223 : API */ -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; -} - diff --git a/libburn/init.h b/libburn/init.h deleted file mode 100644 index ba2fb4f..0000000 --- a/libburn/init.h +++ /dev/null @@ -1,21 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef BURN__INIT_H -#define BURN__INIT_H - -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 */ diff --git a/libburn/lec.c b/libburn/lec.c deleted file mode 100644 index 9141593..0000000 --- a/libburn/lec.c +++ /dev/null @@ -1,451 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -/* borrowed HEAVILY from cdrdao */ - -#include <string.h> -#include "lec.h" - -#define LEC_HEADER_OFFSET 12 -#define LEC_MODE1_P_PARITY_OFFSET 2076 -#define LEC_MODE1_Q_PARITY_OFFSET 2248 - -static unsigned char gf8_ilog[255] = { - 1, 2, 4, 8, 16, 32, 64, 128, 29, 58, 116, 232, 205, 135, 19, 38, 76, - 152, 45, 90, 180, 117, 234, 201, 143, 3, 6, 12, 24, 48, 96, - 192, 157, 39, 78, 156, 37, 74, 148, 53, 106, 212, 181, 119, - 238, 193, 159, 35, 70, 140, 5, 10, 20, 40, 80, 160, 93, 186, - 105, 210, 185, 111, 222, 161, 95, 190, 97, 194, 153, 47, 94, - 188, 101, 202, 137, 15, 30, 60, 120, 240, 253, 231, 211, 187, - 107, 214, 177, 127, 254, 225, 223, 163, 91, 182, 113, 226, 217, - 175, 67, 134, 17, 34, 68, 136, 13, 26, 52, 104, 208, 189, 103, - 206, 129, 31, 62, 124, 248, 237, 199, 147, 59, 118, 236, 197, - 151, 51, 102, 204, 133, 23, 46, 92, 184, 109, 218, 169, 79, - 158, 33, 66, 132, 21, 42, 84, 168, 77, 154, 41, 82, 164, 85, - 170, 73, 146, 57, 114, 228, 213, 183, 115, 230, 209, 191, 99, - 198, 145, 63, 126, 252, 229, 215, 179, 123, 246, 241, 255, 227, - 219, 171, 75, 150, 49, 98, 196, 149, 55, 110, 220, 165, 87, - 174, 65, 130, 25, 50, 100, 200, 141, 7, 14, 28, 56, 112, 224, - 221, 167, 83, 166, 81, 162, 89, 178, 121, 242, 249, 239, 195, - 155, 43, 86, 172, 69, 138, 9, 18, 36, 72, 144, 61, 122, 244, - 245, 247, 243, 251, 235, 203, 139, 11, 22, 44, 88, 176, 125, - 250, 233, 207, 131, 27, 54, 108, 216, 173, 71, 142, -}; -static unsigned char gf8_log[256] = { - 0, 0, 1, 25, 2, 50, 26, 198, 3, 223, 51, 238, 27, 104, 199, 75, 4, 100, - 224, 14, 52, 141, 239, 129, 28, 193, 105, 248, 200, 8, 76, 113, - 5, 138, 101, 47, 225, 36, 15, 33, 53, 147, 142, 218, 240, 18, - 130, 69, 29, 181, 194, 125, 106, 39, 249, 185, 201, 154, 9, - 120, 77, 228, 114, 166, 6, 191, 139, 98, 102, 221, 48, 253, - 226, 152, 37, 179, 16, 145, 34, 136, 54, 208, 148, 206, 143, - 150, 219, 189, 241, 210, 19, 92, 131, 56, 70, 64, 30, 66, 182, - 163, 195, 72, 126, 110, 107, 58, 40, 84, 250, 133, 186, 61, - 202, 94, 155, 159, 10, 21, 121, 43, 78, 212, 229, 172, 115, - 243, 167, 87, 7, 112, 192, 247, 140, 128, 99, 13, 103, 74, 222, - 237, 49, 197, 254, 24, 227, 165, 153, 119, 38, 184, 180, 124, - 17, 68, 146, 217, 35, 32, 137, 46, 55, 63, 209, 91, 149, 188, - 207, 205, 144, 135, 151, 178, 220, 252, 190, 97, 242, 86, 211, - 171, 20, 42, 93, 158, 132, 60, 57, 83, 71, 109, 65, 162, 31, - 45, 67, 216, 183, 123, 164, 118, 196, 23, 73, 236, 127, 12, - 111, 246, 108, 161, 59, 82, 41, 157, 85, 170, 251, 96, 134, - 177, 187, 204, 62, 90, 203, 89, 95, 176, 156, 169, 160, 81, 11, - 245, 22, 235, 122, 117, 44, 215, 79, 174, 213, 233, 230, 231, - 173, 232, 116, 214, 244, 234, 168, 80, 88, 175, -}; -static unsigned char gf8_q_coeffs[2][45] = { - {97, 251, 133, 60, 82, 160, 155, 201, 8, 112, 246, 11, 21, 42, 157, - 169, 80, 174, 232, 230, 172, 211, 241, 18, 68, 216, 44, 121, 9, 200, - 75, 103, 221, 252, 96, 176, 88, 167, 114, 76, 199, 26, 1, 0, 0}, - {190, 96, 250, 132, 59, 81, 159, 154, 200, 7, 111, 245, 10, 20, 41, - 156, 168, 79, 173, 231, 229, 171, 210, 240, 17, 67, 215, 43, 120, 8, - 199, 74, 102, 220, 251, 95, 175, 87, 166, 113, 75, 198, 25, 0, 0} -}; -static unsigned char gf8_p_coeffs[2][26] = { - {230, 172, 211, 241, 18, 68, 216, 44, 121, 9, 200, 75, 103, 221, 252, - 96, 176, 88, 167, 114, 76, 199, 26, 1, 0, 0}, - {231, 229, 171, 210, 240, 17, 67, 215, 43, 120, 8, 199, 74, 102, 220, - 251, 95, 175, 87, 166, 113, 75, 198, 25, 0, 0} -}; - -static unsigned char yellowbook_scrambler[2340] = { - 1, 128, 0, 96, 0, 40, 0, 30, 128, 8, 96, 6, 168, 2, 254, 129, 128, 96, - 96, 40, 40, 30, 158, - 136, 104, 102, 174, 170, 252, 127, 1, 224, 0, 72, 0, 54, 128, 22, 224, - 14, 200, 4, 86, 131, 126, 225, - 224, 72, 72, 54, 182, 150, 246, 238, 198, 204, 82, 213, 253, 159, 1, - 168, 0, 126, 128, 32, 96, 24, 40, - 10, 158, 135, 40, 98, 158, 169, 168, 126, 254, 160, 64, 120, 48, 34, - 148, 25, 175, 74, 252, 55, 1, 214, - 128, 94, 224, 56, 72, 18, 182, 141, 182, 229, 182, 203, 54, 215, 86, - 222, 190, 216, 112, 90, 164, 59, 59, - 83, 83, 125, 253, 225, 129, 136, 96, 102, 168, 42, 254, 159, 0, 104, 0, - 46, 128, 28, 96, 9, 232, 6, - 206, 130, 212, 97, 159, 104, 104, 46, 174, 156, 124, 105, 225, 238, - 200, 76, 86, 181, 254, 247, 0, 70, 128, - 50, 224, 21, 136, 15, 38, 132, 26, 227, 75, 9, 247, 70, 198, 178, 210, - 245, 157, 135, 41, 162, 158, 249, - 168, 66, 254, 177, 128, 116, 96, 39, 104, 26, 174, 139, 60, 103, 81, - 234, 188, 79, 49, 244, 20, 71, 79, - 114, 180, 37, 183, 91, 54, 187, 86, 243, 126, 197, 224, 83, 8, 61, 198, - 145, 146, 236, 109, 141, 237, 165, - 141, 187, 37, 179, 91, 53, 251, 87, 3, 126, 129, 224, 96, 72, 40, 54, - 158, 150, 232, 110, 206, 172, 84, - 125, 255, 97, 128, 40, 96, 30, 168, 8, 126, 134, 160, 98, 248, 41, 130, - 158, 225, 168, 72, 126, 182, 160, - 118, 248, 38, 194, 154, 209, 171, 28, 127, 73, 224, 54, 200, 22, 214, - 142, 222, 228, 88, 75, 122, 183, 99, - 54, 169, 214, 254, 222, 192, 88, 80, 58, 188, 19, 49, 205, 212, 85, - 159, 127, 40, 32, 30, 152, 8, 106, - 134, 175, 34, 252, 25, 129, 202, 224, 87, 8, 62, 134, 144, 98, 236, 41, - 141, 222, 229, 152, 75, 42, 183, - 95, 54, 184, 22, 242, 142, 197, 164, 83, 59, 125, 211, 97, 157, 232, - 105, 142, 174, 228, 124, 75, 97, 247, - 104, 70, 174, 178, 252, 117, 129, 231, 32, 74, 152, 55, 42, 150, 159, - 46, 232, 28, 78, 137, 244, 102, 199, - 106, 210, 175, 29, 188, 9, 177, 198, 244, 82, 199, 125, 146, 161, 173, - 184, 125, 178, 161, 181, 184, 119, 50, - 166, 149, 186, 239, 51, 12, 21, 197, 207, 19, 20, 13, 207, 69, 148, 51, - 47, 85, 220, 63, 25, 208, 10, - 220, 7, 25, 194, 138, 209, 167, 28, 122, 137, 227, 38, 201, 218, 214, - 219, 30, 219, 72, 91, 118, 187, 102, - 243, 106, 197, 239, 19, 12, 13, 197, 197, 147, 19, 45, 205, 221, 149, - 153, 175, 42, 252, 31, 1, 200, 0, - 86, 128, 62, 224, 16, 72, 12, 54, 133, 214, 227, 30, 201, 200, 86, 214, - 190, 222, 240, 88, 68, 58, 179, - 83, 53, 253, 215, 1, 158, 128, 104, 96, 46, 168, 28, 126, 137, 224, - 102, 200, 42, 214, 159, 30, 232, 8, - 78, 134, 180, 98, 247, 105, 134, 174, 226, 252, 73, 129, 246, 224, 70, - 200, 50, 214, 149, 158, 239, 40, 76, - 30, 181, 200, 119, 22, 166, 142, 250, 228, 67, 11, 113, 199, 100, 82, - 171, 125, 191, 97, 176, 40, 116, 30, - 167, 72, 122, 182, 163, 54, 249, 214, 194, 222, 209, 152, 92, 106, 185, - 239, 50, 204, 21, 149, 207, 47, 20, - 28, 15, 73, 196, 54, 211, 86, 221, 254, 217, 128, 90, 224, 59, 8, 19, - 70, 141, 242, 229, 133, 139, 35, - 39, 89, 218, 186, 219, 51, 27, 85, 203, 127, 23, 96, 14, 168, 4, 126, - 131, 96, 97, 232, 40, 78, 158, - 180, 104, 119, 110, 166, 172, 122, 253, 227, 1, 137, 192, 102, 208, 42, - 220, 31, 25, 200, 10, 214, 135, 30, - 226, 136, 73, 166, 182, 250, 246, 195, 6, 209, 194, 220, 81, 153, 252, - 106, 193, 239, 16, 76, 12, 53, 197, - 215, 19, 30, 141, 200, 101, 150, 171, 46, 255, 92, 64, 57, 240, 18, - 196, 13, 147, 69, 173, 243, 61, 133, - 209, 163, 28, 121, 201, 226, 214, 201, 158, 214, 232, 94, 206, 184, 84, - 114, 191, 101, 176, 43, 52, 31, 87, - 72, 62, 182, 144, 118, 236, 38, 205, 218, 213, 155, 31, 43, 72, 31, - 118, 136, 38, 230, 154, 202, 235, 23, - 15, 78, 132, 52, 99, 87, 105, 254, 174, 192, 124, 80, 33, 252, 24, 65, - 202, 176, 87, 52, 62, 151, 80, - 110, 188, 44, 113, 221, 228, 89, 139, 122, 231, 99, 10, 169, 199, 62, - 210, 144, 93, 172, 57, 189, 210, 241, - 157, 132, 105, 163, 110, 249, 236, 66, 205, 241, 149, 132, 111, 35, - 108, 25, 237, 202, 205, 151, 21, 174, 143, - 60, 100, 17, 235, 76, 79, 117, 244, 39, 7, 90, 130, 187, 33, 179, 88, - 117, 250, 167, 3, 58, 129, 211, - 32, 93, 216, 57, 154, 146, 235, 45, 143, 93, 164, 57, 187, 82, 243, - 125, 133, 225, 163, 8, 121, 198, 162, - 210, 249, 157, 130, 233, 161, 142, 248, 100, 66, 171, 113, 191, 100, - 112, 43, 100, 31, 107, 72, 47, 118, 156, - 38, 233, 218, 206, 219, 20, 91, 79, 123, 116, 35, 103, 89, 234, 186, - 207, 51, 20, 21, 207, 79, 20, 52, - 15, 87, 68, 62, 179, 80, 117, 252, 39, 1, 218, 128, 91, 32, 59, 88, 19, - 122, 141, 227, 37, 137, 219, - 38, 219, 90, 219, 123, 27, 99, 75, 105, 247, 110, 198, 172, 82, 253, - 253, 129, 129, 160, 96, 120, 40, 34, - 158, 153, 168, 106, 254, 175, 0, 124, 0, 33, 192, 24, 80, 10, 188, 7, - 49, 194, 148, 81, 175, 124, 124, - 33, 225, 216, 72, 90, 182, 187, 54, 243, 86, 197, 254, 211, 0, 93, 192, - 57, 144, 18, 236, 13, 141, 197, - 165, 147, 59, 45, 211, 93, 157, 249, 169, 130, 254, 225, 128, 72, 96, - 54, 168, 22, 254, 142, 192, 100, 80, - 43, 124, 31, 97, 200, 40, 86, 158, 190, 232, 112, 78, 164, 52, 123, 87, - 99, 126, 169, 224, 126, 200, 32, - 86, 152, 62, 234, 144, 79, 44, 52, 29, 215, 73, 158, 182, 232, 118, - 206, 166, 212, 122, 223, 99, 24, 41, - 202, 158, 215, 40, 94, 158, 184, 104, 114, 174, 165, 188, 123, 49, 227, - 84, 73, 255, 118, 192, 38, 208, 26, - 220, 11, 25, 199, 74, 210, 183, 29, 182, 137, 182, 230, 246, 202, 198, - 215, 18, 222, 141, 152, 101, 170, 171, - 63, 63, 80, 16, 60, 12, 17, 197, 204, 83, 21, 253, 207, 1, 148, 0, 111, - 64, 44, 48, 29, 212, 9, - 159, 70, 232, 50, 206, 149, 148, 111, 47, 108, 28, 45, 201, 221, 150, - 217, 174, 218, 252, 91, 1, 251, 64, - 67, 112, 49, 228, 20, 75, 79, 119, 116, 38, 167, 90, 250, 187, 3, 51, - 65, 213, 240, 95, 4, 56, 3, - 82, 129, 253, 160, 65, 184, 48, 114, 148, 37, 175, 91, 60, 59, 81, 211, - 124, 93, 225, 249, 136, 66, 230, - 177, 138, 244, 103, 7, 106, 130, 175, 33, 188, 24, 113, 202, 164, 87, - 59, 126, 147, 96, 109, 232, 45, 142, - 157, 164, 105, 187, 110, 243, 108, 69, 237, 243, 13, 133, 197, 163, 19, - 57, 205, 210, 213, 157, 159, 41, 168, - 30, 254, 136, 64, 102, 176, 42, 244, 31, 7, 72, 2, 182, 129, 182, 224, - 118, 200, 38, 214, 154, 222, 235, - 24, 79, 74, 180, 55, 55, 86, 150, 190, 238, 240, 76, 68, 53, 243, 87, - 5, 254, 131, 0, 97, 192, 40, - 80, 30, 188, 8, 113, 198, 164, 82, 251, 125, 131, 97, 161, 232, 120, - 78, 162, 180, 121, 183, 98, 246, 169, - 134, 254, 226, 192, 73, 144, 54, 236, 22, 205, 206, 213, 148, 95, 47, - 120, 28, 34, 137, 217, 166, 218, 250, - 219, 3, 27, 65, 203, 112, 87, 100, 62, 171, 80, 127, 124, 32, 33, 216, - 24, 90, 138, 187, 39, 51, 90, - 149, 251, 47, 3, 92, 1, 249, 192, 66, 208, 49, 156, 20, 105, 207, 110, - 212, 44, 95, 93, 248, 57, 130, - 146, 225, 173, 136, 125, 166, 161, 186, 248, 115, 2, 165, 193, 187, 16, - 115, 76, 37, 245, 219, 7, 27, 66, - 139, 113, 167, 100, 122, 171, 99, 63, 105, 208, 46, 220, 28, 89, 201, - 250, 214, 195, 30, 209, 200, 92, 86, - 185, 254, 242, 192, 69, 144, 51, 44, 21, 221, 207, 25, 148, 10, 239, - 71, 12, 50, 133, 213, 163, 31, 57, - 200, 18, 214, 141, 158, 229, 168, 75, 62, 183, 80, 118, 188, 38, 241, - 218, 196, 91, 19, 123, 77, 227, 117, - 137, 231, 38, 202, 154, 215, 43, 30, 159, 72, 104, 54, 174, 150, 252, - 110, 193, 236, 80, 77, 252, 53, 129, - 215, 32, 94, 152, 56, 106, 146, 175, 45, 188, 29, 177, 201, 180, 86, - 247, 126, 198, 160, 82, 248, 61, 130, - 145, 161, 172, 120, 125, 226, 161, 137, 184, 102, 242, 170, 197, 191, - 19, 48, 13, 212, 5, 159, 67, 40, 49, - 222, 148, 88, 111, 122, 172, 35, 61, 217, 209, 154, 220, 107, 25, 239, - 74, 204, 55, 21, 214, 143, 30, 228, - 8, 75, 70, 183, 114, 246, 165, 134, 251, 34, 195, 89, 145, 250, 236, - 67, 13, 241, 197, 132, 83, 35, 125, - 217, 225, 154, 200, 107, 22, 175, 78, 252, 52, 65, 215, 112, 94, 164, - 56, 123, 82, 163, 125, 185, 225, 178, - 200, 117, 150, 167, 46, 250, 156, 67, 41, 241, 222, 196, 88, 83, 122, - 189, 227, 49, 137, 212, 102, 223, 106, - 216, 47, 26, 156, 11, 41, 199, 94, 210, 184, 93, 178, 185, 181, 178, - 247, 53, 134, 151, 34, 238, 153, 140, - 106, 229, 239, 11, 12, 7, 69, 194, 179, 17, 181, 204, 119, 21, 230, - 143, 10, 228, 7, 11, 66, 135, 113, - 162, 164, 121, 187, 98, 243, 105, 133, 238, 227, 12, 73, 197, 246, 211, - 6, 221, 194, 217, 145, 154, 236, 107, - 13, 239, 69, 140, 51, 37, 213, 219, 31, 27, 72, 11, 118, 135, 102, 226, - 170, 201, 191, 22, 240, 14, 196, - 4, 83, 67, 125, 241, 225, 132, 72, 99, 118, 169, 230, 254, 202, 192, - 87, 16, 62, 140, 16, 101, 204, 43, - 21, 223, 79, 24, 52, 10, 151, 71, 46, 178, 156, 117, 169, 231, 62, 202, - 144, 87, 44, 62, 157, 208, 105, - 156, 46, 233, 220, 78, 217, 244, 90, 199, 123, 18, 163, 77, 185, 245, - 178, 199, 53, 146, 151, 45, 174, 157, - 188, 105, 177, 238, 244, 76, 71, 117, 242, 167, 5, 186, 131, 51, 33, - 213, 216, 95, 26, 184, 11, 50, 135, - 85, 162, 191, 57, 176, 18, 244, 13, 135, 69, 162, 179, 57, 181, 210, - 247, 29, 134, 137, 162, 230, 249, 138, - 194, 231, 17, 138, 140, 103, 37, 234, 155, 15, 43, 68, 31, 115, 72, 37, - 246, 155, 6, 235, 66, 207, 113, - 148, 36, 111, 91, 108, 59, 109, 211, 109, 157, 237, 169, 141, 190, 229, - 176, 75, 52, 55, 87, 86, 190, 190, - 240, 112, 68, 36, 51, 91, 85, 251, 127, 3, 96, 1, 232, 0, 78, 128, 52, - 96, 23, 104, 14, 174, 132, - 124, 99, 97, 233, 232, 78, 206, 180, 84, 119, 127, 102, 160, 42, 248, - 31, 2, 136, 1, 166, 128, 122, 224, - 35, 8, 25, 198, 138, 210, 231, 29, 138, 137, 167, 38, 250, 154, 195, - 43, 17, 223, 76, 88, 53, 250, 151, - 3, 46, 129, 220, 96, 89, 232, 58, 206, 147, 20, 109, 207, 109, 148, 45, - 175, 93, 188, 57, 177, 210, 244, - 93, 135, 121, 162, 162, 249, 185, 130, 242, 225, 133, 136, 99, 38, 169, - 218, 254, 219, 0, 91, 64, 59, 112, - 19, 100, 13, 235, 69, 143, 115, 36, 37, 219, 91, 27, 123, 75, 99, 119, - 105, 230, 174, 202, 252, 87, 1, - 254, 128, 64, 96, 48, 40, 20, 30, 143, 72, 100, 54, 171, 86, 255, 126, - 192, 32, 80, 24, 60, 10, 145, - 199, 44, 82, 157, 253, 169, 129, 190, 224, 112, 72, 36, 54, 155, 86, - 235, 126, 207, 96, 84, 40, 63, 94, - 144, 56, 108, 18, 173, 205, 189, 149, 177, 175, 52, 124, 23, 97, 206, - 168, 84, 126, 191, 96, 112, 40, 36, - 30, 155, 72, 107, 118, 175, 102, 252, 42, 193, 223, 16, 88, 12, 58, - 133, 211, 35, 29, 217, 201, 154, 214, - 235, 30, 207, 72, 84, 54, 191, 86, 240, 62, 196, 16, 83, 76, 61, 245, - 209, 135, 28, 98, 137, 233, 166, - 206, 250, 212, 67, 31, 113, 200, 36, 86, 155, 126, 235, 96, 79, 104, - 52, 46, 151, 92, 110, 185, 236, 114, - 205, 229, 149, 139, 47, 39, 92, 26, 185, 203, 50, 215, 85, 158, 191, - 40, 112, 30, 164, 8, 123, 70, 163, - 114, 249, 229, 130, 203, 33, 151, 88, 110, 186, 172, 115, 61, 229, 209, - 139, 28, 103, 73, 234, 182, 207, 54, - 212, 22, 223, 78, 216, 52, 90, 151, 123, 46, 163, 92, 121, 249, 226, - 194, 201, 145, 150, 236, 110, 205, 236, - 85, 141, 255, 37, 128, 27, 32, 11, 88, 7, 122, 130, 163, 33, 185, 216, - 114, 218, 165, 155, 59, 43, 83, - 95, 125, 248, 33, 130, 152, 97, 170, 168, 127, 62, 160, 16, 120, 12, - 34, 133, 217, 163, 26, 249, 203, 2, - 215, 65, 158, 176, 104, 116, 46, 167, 92, 122, 185, 227, 50, 201, 213, - 150, 223, 46, 216, 28, 90, 137, 251, - 38, 195, 90, 209, 251, 28, 67, 73, 241, 246, 196, 70, 211, 114, 221, - 229, 153, -}; - -void scramble(unsigned char *inout) -{ - unsigned char *r = inout + 12; - unsigned char *s = yellowbook_scrambler; - unsigned int i; - - for (i = 2340; i; i--) { - *r++ ^= *s++; - } -} - -/* Calculate the P parities for the sector. - * The 43 P vectors of length 24 are combined with the GF8_P_COEFFS. - */ -void parity_p(unsigned char *sector) -{ - int i, j; - unsigned char p0_msb, p1_msb; - unsigned char p0_lsb, p1_lsb; - unsigned char *p_msb_start, *p_lsb_start; - unsigned char *p_msb, *p_lsb; - unsigned char *coeffs0, *coeffs1; - unsigned char *p0, *p1; - unsigned char d; - unsigned short c; - - p_lsb_start = sector + LEC_HEADER_OFFSET; - p_msb_start = sector + LEC_HEADER_OFFSET + 1; - - p1 = sector + LEC_MODE1_P_PARITY_OFFSET; - p0 = sector + LEC_MODE1_P_PARITY_OFFSET + 2 * 43; - - for (i = 0; i <= 42; i++) { - p_lsb = p_lsb_start; - p_msb = p_msb_start; - - coeffs0 = gf8_p_coeffs[0]; - coeffs1 = gf8_p_coeffs[1]; - - p0_lsb = p1_lsb = p0_msb = p1_msb = 0; - - for (j = 0; j <= 23; j++) { - d = *p_lsb; - - if (d != 0) { - c = gf8_log[d] + *coeffs0; - if (c >= 255) - c -= 255; - p0_lsb ^= gf8_ilog[c]; - - c = gf8_log[d] + *coeffs1; - if (c >= 255) - c -= 255; - p1_lsb ^= gf8_ilog[c]; - } - - d = *p_msb; - - if (d != 0) { - c = gf8_log[d] + *coeffs0; - if (c >= 255) - c -= 255; - p0_msb ^= gf8_ilog[c]; - - c = gf8_log[d] + *coeffs1; - if (c >= 255) - c -= 255; - p1_msb ^= gf8_ilog[c]; - } - - coeffs0++; - coeffs1++; - - p_lsb += 2 * 43; - p_msb += 2 * 43; - } - - *p0 = p0_lsb; - *(p0 + 1) = p0_msb; - - *p1 = p1_lsb; - *(p1 + 1) = p1_msb; - - p0 += 2; - p1 += 2; - - p_lsb_start += 2; - p_msb_start += 2; - } -} - -/* Calculate the Q parities for the sector. - * The 26 Q vectors of length 43 are combined with the GF8_Q_COEFFS. - */ -void parity_q(unsigned char *sector) -{ - int i, j; - unsigned char q0_msb, q1_msb; - unsigned char q0_lsb, q1_lsb; - unsigned char *q_msb_start, *q_lsb_start; - unsigned char *q_msb, *q_lsb; - unsigned char *coeffs0, *coeffs1; - unsigned char *q0, *q1, *q_start; - unsigned char d; - unsigned short c; - - q_lsb_start = sector + LEC_HEADER_OFFSET; - q_msb_start = sector + LEC_HEADER_OFFSET + 1; - - q_start = sector + LEC_MODE1_Q_PARITY_OFFSET; - q1 = sector + LEC_MODE1_Q_PARITY_OFFSET; - q0 = sector + LEC_MODE1_Q_PARITY_OFFSET + 2 * 26; - - for (i = 0; i <= 25; i++) { - q_lsb = q_lsb_start; - q_msb = q_msb_start; - - coeffs0 = gf8_q_coeffs[0]; - coeffs1 = gf8_q_coeffs[1]; - - q0_lsb = q1_lsb = q0_msb = q1_msb = 0; - - for (j = 0; j <= 42; j++) { - d = *q_lsb; - - if (d != 0) { - c = gf8_log[d] + *coeffs0; - if (c >= 255) - c -= 255; - q0_lsb ^= gf8_ilog[c]; - - c = gf8_log[d] + *coeffs1; - if (c >= 255) - c -= 255; - q1_lsb ^= gf8_ilog[c]; - } - - d = *q_msb; - - if (d != 0) { - c = gf8_log[d] + *coeffs0; - if (c >= 255) - c -= 255; - q0_msb ^= gf8_ilog[c]; - - c = gf8_log[d] + *coeffs1; - if (c >= 255) - c -= 255; - q1_msb ^= gf8_ilog[c]; - } - - coeffs0++; - coeffs1++; - - q_lsb += 2 * 44; - q_msb += 2 * 44; - - if (q_lsb >= q_start) { - q_msb -= 2 * 1118; - q_lsb -= 2 * 1118; - } - } - - *q0 = q0_lsb; - *(q0 + 1) = q0_msb; - - *q1 = q1_lsb; - *(q1 + 1) = q1_msb; - - q0 += 2; - q1 += 2; - - q_lsb_start += 2 * 43; - q_msb_start += 2 * 43; - } -} diff --git a/libburn/lec.h b/libburn/lec.h deleted file mode 100644 index f698030..0000000 --- a/libburn/lec.h +++ /dev/null @@ -1,12 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef __LEC -#define __LEC - -#define RS_L12_BITS 8 - -void scramble(unsigned char *); -void parity_p(unsigned char *in); -void parity_q(unsigned char *in); - -#endif /* __LEC */ diff --git a/libburn/libburn.h b/libburn/libburn.h deleted file mode 100644 index ecec0b7..0000000 --- a/libburn/libburn.h +++ /dev/null @@ -1,2369 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef LIBBURN_H -#define LIBBURN_H - -/* Needed for off_t which is the (POSIX-ly) appropriate type for - expressing a file or stream size. - - XXX we should enforce 64-bitness for off_t - ts A61101 : this is usually done by the build system (if it is not broken) -*/ -#include <sys/types.h> - -#ifndef DOXYGEN - -#if defined(__cplusplus) -#define BURN_BEGIN_DECLS \ - namespace burn { \ - extern "C" { -#define BURN_END_DECLS \ - } \ - } -#else -#define BURN_BEGIN_DECLS -#define BURN_END_DECLS -#endif - -BURN_BEGIN_DECLS - -#endif - -/** References a physical drive in the system */ -struct burn_drive; - -/** References a whole disc */ -struct burn_disc; - -/** References a single session on a disc */ -struct burn_session; - -/** References a single track on a disc */ -struct burn_track; - -/* ts A61111 */ -/** References a set of write parameters */ -struct burn_write_opts; - -/** Session format for normal audio or data discs */ -#define BURN_CDROM 0 -/** Session format for obsolete CD-I discs */ -#define BURN_CDI 0x10 -/** Session format for CDROM-XA discs */ -#define BURN_CDXA 0x20 - -#define BURN_POS_END 100 - -/** Mask for mode bits */ -#define BURN_MODE_BITS 127 - -/** Track mode - mode 0 data - 0 bytes of user data. it's all 0s. mode 0. get it? HAH -*/ -#define BURN_MODE0 (1 << 0) -/** Track mode - mode "raw" - all 2352 bytes supplied by app - FOR DATA TRACKS ONLY! -*/ -#define BURN_MODE_RAW (1 << 1) -/** Track mode - mode 1 data - 2048 bytes user data, and all the LEC money can buy -*/ -#define BURN_MODE1 (1 << 2) -/** Track mode - mode 2 data - defaults to formless, 2336 bytes of user data, unprotected - | with a data form if required. -*/ -#define BURN_MODE2 (1 << 3) -/** Track mode modifier - Form 1, | with MODE2 for reasonable results - 2048 bytes of user data, 4 bytes of subheader -*/ -#define BURN_FORM1 (1 << 4) -/** Track mode modifier - Form 2, | with MODE2 for reasonable results - lots of user data. not much LEC. -*/ -#define BURN_FORM2 (1 << 5) -/** Track mode - audio - 2352 bytes per sector. may be | with 4ch or preemphasis. - NOT TO BE CONFUSED WITH BURN_MODE_RAW - Audio data must be 44100Hz 16bit stereo with no riff or other header at - beginning. Extra header data will cause pops or clicks. Audio data should - also be in little-endian byte order. Big-endian audio data causes static. -*/ -#define BURN_AUDIO (1 << 6) -/** Track mode modifier - 4 channel audio. */ -#define BURN_4CH (1 << 7) -/** Track mode modifier - Digital copy permitted, can be set on any track.*/ -#define BURN_COPY (1 << 8) -/** Track mode modifier - 50/15uS pre-emphasis */ -#define BURN_PREEMPHASIS (1 << 9) -/** Input mode modifier - subcodes present packed 16 */ -#define BURN_SUBCODE_P16 (1 << 10) -/** Input mode modifier - subcodes present packed 96 */ -#define BURN_SUBCODE_P96 (1 << 11) -/** Input mode modifier - subcodes present raw 96 */ -#define BURN_SUBCODE_R96 (1 << 12) - -/** Possible disc writing style/modes */ -enum burn_write_types -{ - /** Packet writing. - currently unsupported, (for DVD Incremental Streaming use TAO) - */ - BURN_WRITE_PACKET, - - /** With CD: Track At Once recording - 2s gaps between tracks, no fonky lead-ins - - With sequential DVD-R[W]: Incremental Streaming - With DVD-RAM/+RW: Random Writeable (used sequentially) - With overwriteable DVD-RW: Rigid Restricted Overwrite - */ - BURN_WRITE_TAO, - - /** With CD: Session At Once - Block type MUST be BURN_BLOCK_SAO - ts A70122: Currently not capable of mixing data and audio tracks. - - With sequential DVD-R[W]: Disc-at-once, DAO - Single session, single track, fixed size mandatory, (-dvd-compat) - */ - BURN_WRITE_SAO, - - /** With CD: Raw disc at once recording. - all subcodes must be provided by lib or user - only raw block types are supported - */ - BURN_WRITE_RAW, - - /** In replies this indicates that not any writing will work. - As parameter for inquiries it indicates that no particular write - mode shall is specified. - Do not use for setting a write mode for burning. It won't work. - */ - BURN_WRITE_NONE -}; - -/** Data format to send to the drive */ -enum burn_block_types -{ - /** sync, headers, edc/ecc provided by lib/user */ - BURN_BLOCK_RAW0 = 1, - /** sync, headers, edc/ecc and p/q subs provided by lib/user */ - BURN_BLOCK_RAW16 = 2, - /** sync, headers, edc/ecc and packed p-w subs provided by lib/user */ - BURN_BLOCK_RAW96P = 4, - /** sync, headers, edc/ecc and raw p-w subs provided by lib/user */ - BURN_BLOCK_RAW96R = 8, - /** only 2048 bytes of user data provided by lib/user */ - BURN_BLOCK_MODE1 = 256, - /** 2336 bytes of user data provided by lib/user */ - BURN_BLOCK_MODE2R = 512, - /** 2048 bytes of user data provided by lib/user - subheader provided in write parameters - are we ever going to support this shit? I vote no. - (supposed to be supported on all drives...) - */ - BURN_BLOCK_MODE2_PATHETIC = 1024, - /** 2048 bytes of data + 8 byte subheader provided by lib/user - hey, this is also dumb - */ - BURN_BLOCK_MODE2_LAME = 2048, - /** 2324 bytes of data provided by lib/user - subheader provided in write parameters - no sir, I don't like it. - */ - BURN_BLOCK_MODE2_OBSCURE = 4096, - /** 2332 bytes of data supplied by lib/user - 8 bytes sub header provided in write parameters - this is the second least suck mode2, and is mandatory for - all drives to support. - */ - BURN_BLOCK_MODE2_OK = 8192, - /** SAO block sizes are based on cue sheet, so use this. */ - BURN_BLOCK_SAO = 16384 -}; - -/** Possible status' of the drive in regard to the disc in it. */ -enum burn_disc_status -{ - /** The current status is not yet known */ - BURN_DISC_UNREADY, - /** The drive holds a blank disc */ - BURN_DISC_BLANK, - /** There is no disc at all in the drive */ - BURN_DISC_EMPTY, - /** There is an incomplete disc in the drive */ - BURN_DISC_APPENDABLE, - /** There is a disc with data on it in the drive */ - BURN_DISC_FULL, - - /* ts A61007 */ - /** The drive was not grabbed when the status was inquired */ - BURN_DISC_UNGRABBED, - - /* ts A61020 */ - /** The media seems not to be suitable for burning */ - BURN_DISC_UNSUITABLE -}; - - -/** Possible data source return values */ -enum burn_source_status -{ - /** The source is ok */ - BURN_SOURCE_OK, - /** The source is at end of file */ - BURN_SOURCE_EOF, - /** The source is unusable */ - BURN_SOURCE_FAILED -}; - - -/** Possible busy states for a drive */ -enum burn_drive_status -{ - /** The drive is not in an operation */ - BURN_DRIVE_IDLE, - /** The library is spawning the processes to handle a pending - operation (A read/write/etc is about to start but hasn't quite - yet) */ - BURN_DRIVE_SPAWNING, - /** The drive is reading data from a disc */ - BURN_DRIVE_READING, - /** The drive is writing data to a disc */ - BURN_DRIVE_WRITING, - /** The drive is writing Lead-In */ - BURN_DRIVE_WRITING_LEADIN, - /** The drive is writing Lead-Out */ - BURN_DRIVE_WRITING_LEADOUT, - /** The drive is erasing a disc */ - BURN_DRIVE_ERASING, - /** The drive is being grabbed */ - BURN_DRIVE_GRABBING, - - /* ts A61102 */ - /** The drive gets written zeroes before the track payload data */ - BURN_DRIVE_WRITING_PREGAP, - /** The drive is told to close a track (TAO only) */ - BURN_DRIVE_CLOSING_TRACK, - /** The drive is told to close a session (TAO only) */ - BURN_DRIVE_CLOSING_SESSION, - - /* ts A61223 */ - /** The drive is formatting media */ - BURN_DRIVE_FORMATTING, - - /* ts A70822 */ - /** The drive is busy in synchronous read (if you see this then it - has been interrupted) */ - BURN_DRIVE_READING_SYNC, - /** The drive is busy in synchronous write (if you see this then it - has been interrupted) */ - BURN_DRIVE_WRITING_SYNC - -}; - - -/** Information about a track on a disc - this is from the q sub channel of the - lead-in area of a disc. The documentation here is very terse. - See a document such as mmc3 for proper information. - - CAUTION : This structure is prone to future extension ! - - Do not restrict your application to unsigned char with any counter like - "session", "point", "pmin", ... - Do not rely on the current size of a burn_toc_entry. - - ts A70201 : DVD extension, see below -*/ -struct burn_toc_entry -{ - /** Session the track is in */ - unsigned char session; - /** Type of data. for this struct to be valid, it must be 1 */ - unsigned char adr; - /** Type of data in the track */ - unsigned char control; - /** Zero. Always. Really. */ - unsigned char tno; - /** Track number or special information */ - unsigned char point; - unsigned char min; - unsigned char sec; - unsigned char frame; - unsigned char zero; - /** Track start time minutes for normal tracks */ - unsigned char pmin; - /** Track start time seconds for normal tracks */ - unsigned char psec; - /** Track start time frames for normal tracks */ - unsigned char pframe; - - /* Indicates whether extension data are valid and eventually override - older elements in this structure: - bit0= DVD extension is valid - */ - unsigned char extensions_valid; - - /* ts A70201 : DVD extension. - If invalid the members are guaranteed to be 0. */ - /* Tracks and session numbers are 16 bit. Here are the high bytes. */ - unsigned char session_msb; - unsigned char point_msb; - /* pmin, psec, and pframe may be too small if DVD extension is valid */ - int start_lba; - /* min, sec, and frame may be too small if DVD extension is valid */ - int track_blocks; - -}; - - -/** Data source interface for tracks. - This allows to use arbitrary program code as provider of track input data. - - Objects compliant to this interface are either provided by the application - or by API calls of libburn: burn_fd_source_new() , burn_file_source_new(), - and burn_fifo_source_new(). - - The API calls allow to use any file object as data source. Consider to feed - an eventual custom data stream asynchronously into a pipe(2) and to let - libburn handle the rest. - In this case the following rule applies: - Call burn_source_free() exactly once for every source obtained from - libburn API. You MUST NOT otherwise use or manipulate its components. - - In general, burn_source objects can be freed as soon as they are attached - to track objects. The track objects will keep them alive and dispose them - when they are no longer needed. With a fifo burn_source it makes sense to - keep the own reference for inquiring its state while burning is in - progress. - - --- - - The following description of burn_source applies only to application - implemented burn_source objects. You need not to know it for API provided - ones. - - If you really implement an own passive data producer by this interface, - then beware: it can do anything and it can spoil everything. - - In this case the functions (*read), (*get_size), (*set_size), (*free_data) - MUST be implemented by the application and attached to the object at - creation time. - Function (*read_sub) is allowed to be NULL or it MUST be implemented and - attached. - - burn_source.refcount MUST be handled properly: If not exactly as many - references are freed as have been obtained, then either memory leaks or - corrupted memory are the consequence. - All objects which are referred to by *data must be kept existent until - (*free_data) is called via burn_source_free() by the last referer. -*/ -struct burn_source { - - /** Reference count for the data source. MUST be 1 when a new source - is created and thus the first reference is handed out. Increment - it to take more references for yourself. Use burn_source_free() - to destroy your references to it. */ - int refcount; - - - /** Read data from the source. Semantics like with read(2), but MUST - either deliver the full buffer as defined by size or MUST deliver - EOF (return 0) or failure (return -1) at this call or at the - next following call. I.e. the only incomplete buffer may be the - last one from that source. - libburn will read a single sector by each call to (*read). - The size of a sector depends on BURN_MODE_*. The known range is - 2048 to 2352. - - IMPORTANT: - If this function pointer is NULL, then the struct burn_source is of - version >= 1 and the job of .(*read)() is done by .(*read_xt)(). - See below, member .version. - */ - int (*read)(struct burn_source *, unsigned char *buffer, int size); - - - /** Read subchannel data from the source (NULL if lib generated) - WARNING: This is an obscure feature with CD raw write modes. - Unless you checked the libburn code for correctness in that aspect - you should not rely on raw writing with own subchannels. - ADVICE: Set this pointer to NULL. - */ - int (*read_sub)(struct burn_source *, unsigned char *buffer, int size); - - - /** Get the size of the source's data. Return 0 means unpredictable - size. If application provided (*get_size) allows return 0, then - the application MUST provide a fully functional (*set_size). - */ - off_t (*get_size)(struct burn_source *); - - - /* ts A70125 : BROKE BINARY BACKWARD COMPATIBILITY AT libburn-0.3.1. */ - /** Program the reply of (*get_size) to a fixed value. It is advised - to implement this by a attribute off_t fixed_size; in *data . - The read() function does not have to take into respect this fake - setting. It is rather a note of libburn to itself. Eventually - necessary truncation or padding is done in libburn. Truncation - is usually considered a misburn. Padding is considered ok. - - libburn is supposed to work even if (*get_size) ignores the - setting by (*set_size). But your application will not be able to - enforce fixed track sizes by burn_track_set_size() and possibly - even padding might be left out. - */ - int (*set_size)(struct burn_source *source, off_t size); - - - /** Clean up the source specific data. This function will be called - once by burn_source_free() when the last referer disposes the - source. - */ - void (*free_data)(struct burn_source *); - - - /** Next source, for when a source runs dry and padding is disabled - WARNING: This is an obscure feature. Set to NULL at creation and - from then on leave untouched and uninterpreted. - */ - struct burn_source *next; - - - /** Source specific data. Here the various source classes express their - specific properties and the instance objects store their individual - management data. - E.g. data could point to a struct like this: - struct app_burn_source - { - struct my_app *app_handle; - ... other individual source parameters ... - off_t fixed_size; - }; - - Function (*free_data) has to be prepared to clean up and free - the struct. - */ - void *data; - - - /* ts A71222 : Supposed to be binary backwards compatible extension. */ - - /** Valid only if above member .(*read)() is NULL. This indicates a - version of struct burn_source younger than 0. - From then on, member .version tells which further members exist - in the memory layout of struct burn_source. libburn will only touch - those announced extensions. - - Versions: - 0 has .(*read)() != NULL, not even .version is present. - 1 has .version, .(*read_xt)(), .(*cancel)() - */ - int version; - - /** This substitutes for (*read)() in versions above 0. */ - int (*read_xt)(struct burn_source *, unsigned char *buffer, int size); - - /** Informs the burn_source that the consumer of data prematurely - ended reading. This call may or may not be issued by libburn - before (*free_data)() is called. - */ - int (*cancel)(struct burn_source *source); -}; - - -/** Information on a drive in the system */ -struct burn_drive_info -{ - /** Name of the vendor of the drive */ - char vendor[9]; - /** Name of the drive */ - char product[17]; - /** Revision of the drive */ - char revision[5]; - - /** Invalid: Was: "Location of the drive in the filesystem." */ - /** This string has no meaning any more. Once it stored the persistent - drive address. Now always use function burn_drive_d_get_adr() to - inquire a persistent address. ^^^^^^ ALWAYS ^^^^^^^^ */ - char location[17]; - - /** Can the drive read DVD-RAM discs */ - unsigned int read_dvdram:1; - /** Can the drive read DVD-R discs */ - unsigned int read_dvdr:1; - /** Can the drive read DVD-ROM discs */ - unsigned int read_dvdrom:1; - /** Can the drive read CD-R discs */ - unsigned int read_cdr:1; - /** Can the drive read CD-RW discs */ - unsigned int read_cdrw:1; - - /** Can the drive write DVD-RAM discs */ - unsigned int write_dvdram:1; - /** Can the drive write DVD-R discs */ - unsigned int write_dvdr:1; - /** Can the drive write CD-R discs */ - unsigned int write_cdr:1; - /** Can the drive write CD-RW discs */ - unsigned int write_cdrw:1; - - /** Can the drive simulate a write */ - unsigned int write_simulate:1; - - /** Can the drive report C2 errors */ - unsigned int c2_errors:1; - - /** The size of the drive's buffer (in kilobytes) */ - int buffer_size; - /** - * The supported block types in tao mode. - * They should be tested with the desired block type. - * See also burn_block_types. - */ - int tao_block_types; - /** - * The supported block types in sao mode. - * They should be tested with the desired block type. - * See also burn_block_types. - */ - int sao_block_types; - /** - * The supported block types in raw mode. - * They should be tested with the desired block type. - * See also burn_block_types. - */ - int raw_block_types; - /** - * The supported block types in packet mode. - * They should be tested with the desired block type. - * See also burn_block_types. - */ - int packet_block_types; - - /** The value by which this drive can be indexed when using functions - in the library. This is the value to pass to all libbburn functions - that operate on a drive. */ - struct burn_drive *drive; -}; - - -/** Operation progress report. All values are 0 based indices. - * */ -struct burn_progress { - /** The total number of sessions */ - int sessions; - /** Current session.*/ - int session; - /** The total number of tracks */ - int tracks; - /** Current track. */ - int track; - /** The total number of indices */ - int indices; - /** Curent index. */ - int index; - /** The starting logical block address */ - int start_sector; - /** On write: The number of sectors. - On blank: 0x10000 as upper limit for relative progress steps */ - int sectors; - /** On write: The current sector being processed. - On blank: Relative progress steps 0 to 0x10000 */ - int sector; - - /* ts A61023 */ - /** The capacity of the drive buffer */ - unsigned buffer_capacity; - /** The free space in the drive buffer (might be slightly outdated) */ - unsigned buffer_available; - - /* ts A61119 */ - /** The number of bytes sent to the drive buffer */ - off_t buffered_bytes; - /** The minimum number of bytes stored in buffer during write. - (Caution: Before surely one buffer size of bytes was processed, - this value is 0xffffffff.) - */ - unsigned buffer_min_fill; -}; - - -/* ts A61226 */ -/** Description of a speed capability as reported by the drive in conjunction - with eventually loaded media. There can be more than one such object per - drive. So they are chained via .next and .prev , where NULL marks the end - of the chain. This list is set up by burn_drive_scan() and gets updated - by burn_drive_grab(). - A copy may be obtained by burn_drive_get_speedlist() and disposed by - burn_drive_free_speedlist(). - For technical background info see SCSI specs MMC and SPC: - mode page 2Ah (from SPC 5Ah MODE SENSE) , mmc3r10g.pdf , 6.3.11 Table 364 - ACh GET PERFORMANCE, Type 03h , mmc5r03c.pdf , 6.8.5.3 Table 312 -*/ -struct burn_speed_descriptor { - - /** Where this info comes from : - 0 = misc , 1 = mode page 2Ah , 2 = ACh GET PERFORMANCE */ - int source; - - /** The media type that was current at the time of report - -2 = state unknown, -1 = no media was loaded , else see - burn_disc_get_profile() */ - int profile_loaded; - char profile_name[80]; - - /** The attributed capacity of appropriate media in logical block units - i.e. 2352 raw bytes or 2048 data bytes. -1 = capacity unknown. */ - int end_lba; - - /** Speed is given in 1000 bytes/s , 0 = invalid. The numbers - are supposed to be usable with burn_drive_set_speed() */ - int write_speed; - int read_speed; - - /** Expert info from ACh GET PERFORMANCE and/or mode page 2Ah. - Expect values other than 0 or 1 to get a meaning in future.*/ - /* Rotational control: 0 = CLV/default , 1 = CAV */ - int wrc; - /* 1 = drive promises reported performance over full media */ - int exact; - /* 1 = suitable for mixture of read and write */ - int mrw; - - /** List chaining. Use .next until NULL to iterate over the list */ - struct burn_speed_descriptor *prev; - struct burn_speed_descriptor *next; -}; - - -/** Initialize the library. - This must be called before using any other functions in the library. It - may be called more than once with no effect. - It is possible to 'restart' the library by shutting it down and - re-initializing it. Once this was necessary if you follow the older and - more general way of accessing a drive via burn_drive_scan() and - burn_drive_grab(). See burn_drive_scan_and_grab() with its strong - urges and its explanations. - @return Nonzero if the library was able to initialize; zero if - initialization failed. -*/ -int burn_initialize(void); - -/** Shutdown the library. - This should be called before exiting your application. Make sure that all - drives you have grabbed are released <i>before</i> calling this. -*/ -void burn_finish(void); - - -/* ts A61002 */ -/** Abort any running drive operation and finally call burn_finish(). - You MUST calm down the busy drive if an aborting event occurs during a - burn run. For that you may call this function either from your own signal - handling code or indirectly by activating the builtin signal handling: - burn_set_signal_handling("my_app_name : ", NULL, 0); - Else you may eventually call burn_drive_cancel() on the active drive and - wait for it to assume state BURN_DRIVE_IDLE. - @param patience Maximum number of seconds to wait for drives to finish - @param pacifier_func If not NULL: a function to produce appeasing messages. - See burn_abort_pacifier() for an example. - @param handle Opaque handle to be used with pacifier_func - @return 1 ok, all went well - 0 had to leave a drive in unclean state - <0 severe error, do no use libburn again -*/ -int burn_abort(int patience, - int (*pacifier_func)(void *handle, int patience, int elapsed), - void *handle); - -/** A pacifier function suitable for burn_abort. - @param handle If not NULL, a pointer to a text suitable for printf("%s") - @param patience Maximum number of seconds to wait - @param elapsed Elapsed number of seconds -*/ -int burn_abort_pacifier(void *handle, int patience, int elapsed); - - -/** ts A61006 : This is for development only. Not suitable for applications. - Set the verbosity level of the library. The default value is 0, which means - that nothing is output on stderr. The more you increase this, the more - debug output should be displayed on stderr for you. - @param level The verbosity level desired. 0 for nothing, higher positive - values for more information output. -*/ -void burn_set_verbosity(int level); - -/* ts A60813 */ -/** Set parameters for behavior on opening device files. To be called early - after burn_initialize() and before any bus scan. But not mandatory at all. - Parameter value 1 enables a feature, 0 disables. - Default is (1,0,0). Have a good reason before you change it. - @param exclusive Linux only: - 0 = no attempt to make drive access exclusive. - 1 = Try to open only devices which are not marked as busy - and try to mark them busy if opened sucessfully. (O_EXCL) - There are kernels which simply don't care about O_EXCL. - Some have it off, some have it on, some are switchable. - 2 = in case of a SCSI device, also try to open exclusively - the matching /dev/sr, /dev/scd and /dev/st . - One may select a device SCSI file family by adding - 0 = default family - 4 = /dev/sr%d - 8 = /dev/scd%d - 16 = /dev/sg%d - Do not use other values ! - Add 32 to demand an exclusive lock by fcntl(,F_SETLK,) - after open() has succeeded. - @param blocking Try to wait for drives which do not open immediately but - also do not return an error as well. (O_NONBLOCK) - This might stall indefinitely with /dev/hdX hard disks. - @param abort_on_busy Unconditionally abort process when a non blocking - exclusive opening attempt indicates a busy drive. - Use this only after thorough tests with your app. -*/ -void burn_preset_device_open(int exclusive, int blocking, int abort_on_busy); - - -/* ts A70223 */ -/** Allows the use of media types which are implemented in libburn but not yet - tested. The list of those untested profiles is subject to change. - Currently it contains: 0x15 "DVD-R/DL sequential recording", - If you really test such media, then please report the outcome on - libburn-hackers@pykix.org - If ever then this call should be done soon after burn_initialize() before - any drive scanning. - @param yes 1=allow all implemented profiles, 0=only tested media (default) -*/ -void burn_allow_untested_profiles(int yes); - - -/* ts A60823 */ -/** Aquire a drive with known persistent address. - - This is the sysadmin friendly way to open one drive and to leave all - others untouched. It bundles the following API calls to form a - non-obtrusive way to use libburn: - burn_drive_add_whitelist() , burn_drive_scan() , burn_drive_grab() - You are *strongly urged* to use this call whenever you know the drive - address in advance. - - If not, then you have to use directly above calls. In that case, you are - *strongly urged* to drop any unintended drive which will be exclusively - occupied and not closed by burn_drive_scan(). - This can be done by shutting down the library including a call to - burn_finish(). You may later start a new libburn session and should then - use the function described here with an address obtained after - burn_drive_scan() via burn_drive_d_get_adr(drive_infos[driveno].drive,adr). - Another way is to drop the unwanted drives by burn_drive_info_forget(). - - Operating on multiple drives: - - Different than with burn_drive_scan() it is allowed to call - burn_drive_scan_and_grab() without giving up any other scanned drives. So - this call can be used to get a collection of more than one aquired drives. - The attempt to aquire the same drive twice will fail, though. - - Pseudo-drives: - - burn_drive_scan_and_grab() is able to aquire virtual drives which will - accept options much like a MMC burner drive. Many of those options will not - cause any effect, though. The address of a pseudo-drive begins with - prefix "stdio:" followed by a path. - Examples: "stdio:/tmp/pseudo_drive" , "stdio:/dev/null" , "stdio:-" - - If the path is empty, the result is a null-drive = drive role 0. - It pretends to have loaded no media and supports no reading or writing. - - If the path leads to an existing regular file, or to a not yet existing - file, or to an existing block device, then the result is a random access - stdio-drive capable of reading and writing = drive role 2. - - If the path leads to an existing file of any type other than directory, - then the result is a sequential write-only stdio-drive = drive role 3. - - The special address form "stdio:/dev/fd/<number>" is interpreted literally - as reference to open file descriptor <number>. This address form coincides - with real files on some systems, but it is in fact hardcoded in libburn. - Special address "stdio:-" means stdout = "stdio:/dev/fd/1". - The role of such a drive is determined by the file type obtained via - fstat(<number>). - - Roles 2 and 3 perform all their eventual data transfer activities on a file - via standard i/o functions open(2), lseek(2), read(2), write(2), close(2). - The media profile is reported as 0xffff. Write space information from those - media is not necessarily realistic. - - The capabilities of role 2 resemble DVD-RAM but it can simulate writing. - If the path does not exist in the filesystem yet, it is attempted to create - it as a regular file as soon as write operations are started. - - The capabilities of role 3 resemble a blank DVD-R. - - One may distinguish pseudo-drives from MMC drives by call - burn_drive_get_drive_role(). - - @param drive_infos On success returns a one element array with the drive - (cdrom/burner). Thus use with driveno 0 only. On failure - the array has no valid elements at all. - The returned array should be freed via burn_drive_info_free() - when it is no longer needed. - This is a result from call burn_drive_scan(). See there. - Use with driveno 0 only. - @param adr The persistent address of the desired drive. Either once - obtained by burn_drive_d_get_adr() or composed skillfully by - application resp. its user. E.g. "/dev/sr0". - Consider to preprocess it by burn_drive_convert_fs_adr(). - @param load Nonzero to make the drive attempt to load a disc (close its - tray door, etc). - @return 1 = success , 0 = drive not found , -1 = other error -*/ -int burn_drive_scan_and_grab(struct burn_drive_info *drive_infos[], - char* adr, int load); - - -/* ts A51221 */ -/** Maximum number of particularly permissible drive addresses */ -#define BURN_DRIVE_WHITELIST_LEN 255 -/** Add a device to the list of permissible drives. As soon as some entry is in - the whitelist all non-listed drives are banned from scanning. - @return 1 success, <=0 failure -*/ -int burn_drive_add_whitelist(char *device_address); - -/** Remove all drives from whitelist. This enables all possible drives. */ -void burn_drive_clear_whitelist(void); - - -/** Scan for drives. This function MUST be called until it returns nonzero. - In case of re-scanning: - All pointers to struct burn_drive and all struct burn_drive_info arrays - are invalidated by using this function. Do NOT store drive pointers across - calls to this function ! - To avoid invalid pointers one MUST free all burn_drive_info arrays - by burn_drive_info_free() before calling burn_drive_scan() a second time. - If there are drives left, then burn_drive_scan() will refuse to work. - - After this call all drives depicted by the returned array are subject - to eventual (O_EXCL) locking. See burn_preset_device_open(). This state - ends either with burn_drive_info_forget() or with burn_drive_release(). - It is unfriendly to other processes on the system to hold drives locked - which one does not definitely plan to use soon. - @param drive_infos Returns an array of drive info items (cdroms/burners). - The returned array must be freed by burn_drive_info_free() - before burn_finish(), and also before calling this function - burn_drive_scan() again. - @param n_drives Returns the number of drive items in drive_infos. - @return 0 while scanning is not complete - >0 when it is finished sucessfully, - <0 when finished but failed. -*/ -int burn_drive_scan(struct burn_drive_info *drive_infos[], - unsigned int *n_drives); - -/* ts A60904 : ticket 62, contribution by elmom */ -/** Release memory about a single drive and any exclusive lock on it. - Become unable to inquire or grab it. Expect FATAL consequences if you try. - @param drive_info pointer to a single element out of the array - obtained from burn_drive_scan() : &(drive_infos[driveno]) - @param force controls degree of permissible drive usage at the moment this - function is called, and the amount of automatically provided - drive shutdown : - 0= drive must be ungrabbed and BURN_DRIVE_IDLE - 1= try to release drive resp. accept BURN_DRIVE_GRABBING - Use these two only. Further values are to be defined. - @return 1 on success, 2 if drive was already forgotten, - 0 if not permissible, <0 on other failures, -*/ -int burn_drive_info_forget(struct burn_drive_info *drive_info, int force); - - -/** When no longer needed, free a whole burn_drive_info array which was - returned by burn_drive_scan(). - For freeing single drive array elements use burn_drive_info_forget(). -*/ -void burn_drive_info_free(struct burn_drive_info drive_infos[]); - - -/* ts A60823 */ -/** Maximum length+1 to expect with a persistent drive address string */ -#define BURN_DRIVE_ADR_LEN 1024 - -/** Inquire the persistent address of the given drive. - @param drive The drive to inquire. - @param adr An application provided array of at least BURN_DRIVE_ADR_LEN - characters size. The persistent address gets copied to it. - @return >0 success , <=0 error (due to libburn internal problem) -*/ -int burn_drive_d_get_adr(struct burn_drive *drive, char adr[]); - -/** Inquire the persistent address of a drive via a given drive_info object. - (Note: This is a legacy call.) - @param drive_info The drive to inquire.Usually some &(drive_infos[driveno]) - @param adr An application provided array of at least BURN_DRIVE_ADR_LEN - characters size. The persistent address gets copied to it. - @return >0 success , <=0 error (due to libburn internal problem) -*/ -int burn_drive_get_adr(struct burn_drive_info *drive_info, char adr[]); - - -/* ts A60922 ticket 33 */ -/** Evaluate whether the given address would be a possible persistent drive - address of libburn. - @return 1 means yes, 0 means no -*/ -int burn_drive_is_enumerable_adr(char *adr); - -/* ts A60922 ticket 33 */ -/** Try to convert a given existing filesystem address into a persistent drive - address. This succeeds with symbolic links or if a hint about the drive's - system address can be read from the filesystem object and a matching drive - is found. - @param path The address of an existing file system object - @param adr An application provided array of at least BURN_DRIVE_ADR_LEN - characters size. The persistent address gets copied to it. - @return 1 = success , 0 = failure , -1 = severe error -*/ -int burn_drive_convert_fs_adr(char *path, char adr[]); - -/* ts A60923 */ -/** Try to convert a given SCSI address of bus,host,channel,target,lun into - a persistent drive address. If a SCSI address component parameter is < 0 - then it is not decisive and the first enumerated address which matches - the >= 0 parameters is taken as result. - Note: bus and (host,channel) are supposed to be redundant. - @param bus_no "Bus Number" (something like a virtual controller) - @param host_no "Host Number" (something like half a virtual controller) - @param channel_no "Channel Number" (other half of "Host Number") - @param target_no "Target Number" or "SCSI Id" (a device) - @param lun_no "Logical Unit Number" (a sub device) - @param adr An application provided array of at least BURN_DRIVE_ADR_LEN - characters size. The persistent address gets copied to it. - @return 1 = success , 0 = failure , -1 = severe error -*/ -int burn_drive_convert_scsi_adr(int bus_no, int host_no, int channel_no, - int target_no, int lun_no, char adr[]); - -/* ts A60923 - A61005 */ -/** Try to obtain bus,host,channel,target,lun from path. If there is an SCSI - address at all, then this call should succeed with a persistent - drive address obtained via burn_drive_d_get_adr(). It is also supposed to - succeed with any device file of a (possibly emulated) SCSI device. - @return 1 = success , 0 = failure , -1 = severe error -*/ -int burn_drive_obtain_scsi_adr(char *path, int *bus_no, int *host_no, - int *channel_no, int *target_no, int *lun_no); - -/** Grab a drive. This must be done before the drive can be used (for reading, - writing, etc). - @param drive The drive to grab. This is found in a returned - burn_drive_info struct. - @param load Nonzero to make the drive attempt to load a disc (close its - tray door, etc). - @return 1 if it was possible to grab the drive, else 0 -*/ -int burn_drive_grab(struct burn_drive *drive, int load); - - -/** Release a drive. This should not be done until the drive is no longer - busy (see burn_drive_get_status). - Linux: The drive device file is not reserved afterwards. (O_EXCL, F_SETLK). - @param drive The drive to release. - @param eject Nonzero to make the drive eject the disc in it. -*/ -void burn_drive_release(struct burn_drive *drive, int eject); - - -/* ts A70918 */ -/** Like burn_drive_release() but keeping the drive tray closed and its - eject button disabled. This physically locked drive state will last until - the drive is grabbed again and released via burn_drive_release(). - Programs like eject, cdrecord, growisofs will break that ban too. - @param drive The drive to release and leave locked. - @param flag Bitfield for control purposes (unused yet, submit 0) - @return 1 means success, <=0 means failure -*/ -int burn_drive_leave_locked(struct burn_drive *d, int flag); - - -/** Returns what kind of disc a drive is holding. This function may need to be - called more than once to get a proper status from it. See burn_disc_status - for details. - @param drive The drive to query for a disc. - @return The status of the drive, or what kind of disc is in it. - Note: BURN_DISC_UNGRABBED indicates wrong API usage -*/ -enum burn_disc_status burn_disc_get_status(struct burn_drive *drive); - - -/* ts A61020 */ -/** WARNING: This revives an old bug-like behavior that might be dangerous. - Sets the drive status to BURN_DISC_BLANK if it is BURN_DISC_UNREADY - or BURN_DISC_UNSUITABLE. Thus marking media as writable which actually - failed to declare themselves either blank or (partially) filled. - @return 1 drive status has been set , 0 = unsuitable drive status -*/ -int burn_disc_pretend_blank(struct burn_drive *drive); - - -/* ts A61106 */ -/** WARNING: This overrides the safety measures against unsuitable media. - Sets the drive status to BURN_DISC_FULL if it is BURN_DISC_UNREADY - or BURN_DISC_UNSUITABLE. Thus marking media as blankable which actually - failed to declare themselves either blank or (partially) filled. -*/ -int burn_disc_pretend_full(struct burn_drive *drive); - - -/* ts A61021 */ -/** Reads ATIP information from inserted media. To be obtained via - burn_drive_get_write_speed(), burn_drive_get_min_write_speed(), - burn_drive_get_start_end_lba(). The drive must be grabbed for this call. - @param drive The drive to query. - @return 1=sucess, 0=no valid ATIP info read, -1 severe error -*/ -int burn_disc_read_atip(struct burn_drive *drive); - - -/* ts A61020 */ -/** Returns start and end lba of the media which is currently inserted - in the given drive. The drive has to be grabbed to have hope for reply. - Shortcomming (not a feature): unless burn_disc_read_atip() was called - only blank media will return valid info. - @param drive The drive to query. - @param start_lba Returns the start lba value - @param end_lba Returns the end lba value - @param flag Bitfield for control purposes (unused yet, submit 0) - @return 1 if lba values are valid , 0 if invalid -*/ -int burn_drive_get_start_end_lba(struct burn_drive *drive, - int *start_lba, int *end_lba, int flag); - -/* ts A61110 */ -/** Read start lba and Next Writeable Address of a track from media. - Usually a track lba is obtained from the result of burn_track_get_entry(). - This call retrieves an updated lba, eventual nwa, and can address the - invisible track to come. - The drive must be grabbed for this call. One may not issue this call - during ongoing burn_disc_write() or burn_disc_erase(). - @param d The drive to query. - @param o If not NULL: write parameters to be set on drive before query - @param trackno 0=next track to come, >0 number of existing track - @param lba return value: start lba - @param nwa return value: Next Writeable Address - @return 1=nwa is valid , 0=nwa is not valid , -1=error -*/ -int burn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o, - int trackno, int *lba, int *nwa); - -/* ts A70131 */ -/** Read start lba of the first track in the last complete session. - This is the first parameter of mkisofs option -C. The second parameter - is nwa as obtained by burn_disc_track_lba_nwa() with trackno 0. - @param d The drive to query. - @param start_lba returns the start address of that track - @return <= 0 : failure, 1 = ok -*/ -int burn_disc_get_msc1(struct burn_drive *d, int *start_lba); - - -/* ts A70213 */ -/** Return the best possible estimation of the currently available capacity of - the media. This might depend on particular write option settings. For - inquiring the space with such a set of options, the drive has to be - grabbed and BURN_DRIVE_IDLE. If not, then one will only get a canned value - from the most recent automatic inquiry (e.g. during last drive grabbing). - An eventual start address from burn_write_opts_set_start_byte() will be - subtracted from the obtained capacity estimation. Negative results get - defaulted to 0. - @param d The drive to query. - @param o If not NULL: write parameters to be set on drive before query - @return number of most probably available free bytes -*/ -off_t burn_disc_available_space(struct burn_drive *d, - struct burn_write_opts *o); - - -/* ts A61202 */ -/** Tells the MMC Profile identifier of the loaded media. The drive must be - grabbed in order to get a non-zero result. - libburn currently writes only to profiles - 0x09 "CD-R", 0x0a "CD-RW", - 0x11 "DVD-R sequential recording", 0x12 "DVD-RAM", - 0x13 "DVD-RW restricted overwrite", 0x14 "DVD-RW sequential recording", - 0x1a "DVD+RW", 0x1b "DVD+R", - 0x2b "DVD+R/DL", 0x43 "BD-RE", - 0xffff "stdio file" - Note: 0xffff is not a MMC profile but a libburn invention. - If enabled by burn_allow_untested_profiles() it also writes to profiles - 0x15 "DVD-R/DL sequential recording", - Read-only are the profiles - 0x08 "CD-ROM", 0x10 "DVD-ROM", - 0x40 "BD-ROM", - For now read-only are BD-R profiles (testers wanted) - 0x41 "BD-R sequential recording", 0x42 "BD-R random recording" - @param d The drive where the media is inserted. - @param pno Profile Number. See also mmc5r03c.pdf, table 89 - @param name Profile Name (see above list, unknown profiles have empty name) - @return 1 profile is valid, 0 no profile info available -*/ -int burn_disc_get_profile(struct burn_drive *d, int *pno, char name[80]); - -/** Tells whether a disc can be erased or not - @param d The drive to inquire. - @return Non-zero means erasable -*/ -int burn_disc_erasable(struct burn_drive *d); - -/** Returns the progress and status of a drive. - @param drive The drive to query busy state for. - @param p Returns the progress of the operation, NULL if you don't care - @return the current status of the drive. See also burn_drive_status. -*/ -enum burn_drive_status burn_drive_get_status(struct burn_drive *drive, - struct burn_progress *p); - -/** Creates a write_opts struct for burning to the specified drive - must be freed with burn_write_opts_free - @param drive The drive to write with - @return The write_opts, NULL on error -*/ -struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive); - - -/* ts A70901 */ -/** Inquires the drive associated with a burn_write_opts object. - @param opts object to inquire - @return pointer to drive -*/ -struct burn_drive *burn_write_opts_get_drive(struct burn_write_opts *opts); - - -/** Frees a write_opts struct created with burn_write_opts_new - @param opts write_opts to free -*/ -void burn_write_opts_free(struct burn_write_opts *opts); - -/** Creates a read_opts struct for reading from the specified drive - must be freed with burn_read_opts_free - @param drive The drive to read from - @return The read_opts -*/ -struct burn_read_opts *burn_read_opts_new(struct burn_drive *drive); - -/** Frees a read_opts struct created with burn_read_opts_new - @param opts write_opts to free -*/ -void burn_read_opts_free(struct burn_read_opts *opts); - -/** Erase a disc in the drive. The drive must be grabbed successfully BEFORE - calling this functions. Always ensure that the drive reports a status of - BURN_DISC_FULL before calling this function. An erase operation is not - cancellable, as control of the operation is passed wholly to the drive and - there is no way to interrupt it safely. - @param drive The drive with which to erase a disc. - @param fast Nonzero to do a fast erase, where only the disc's headers are - erased; zero to erase the entire disc. - With DVD-RW, fast blanking yields media capable only of DAO. -*/ -void burn_disc_erase(struct burn_drive *drive, int fast); - - -/* ts A70101 - A70417 */ -/** Format media for use with libburn. This currently applies to DVD-RW - in state "Sequential Recording" (profile 0014h) which get formatted to - state "Restricted Overwrite" (profile 0013h). DVD+RW can be "de-iced" - by setting bit2 of flag. Other media cannot be formatted yet. - This function usually returns while the drive is still in the process - of formatting. The formatting is done, when burn_drive_get_status() - returns BURN_DRIVE_IDLE. This may be immediately after return or may - need several thousand seconds to occur. - @param drive The drive with the disc to format. - @param size The size in bytes to be used with the format command. It should - be divisible by 32*1024. The effect of this parameter may - depend on the media profile and on parameter flag. - @param flag Bitfield for control purposes: - bit0= after formatting, write the given number of zero-bytes - to the media and eventually perform preliminary closing. - bit1+2: size mode - 0 = use parameter size as far as it makes sense - 1 = insist in size 0 even if there is a better default known - (on DVD-RAM or BD-RE identical to size mode 0) - 2 = without bit7: format to maximum available size - with bit7 : take size from indexed format descriptor - 3 = without bit7: format to default size - with bit7 : take size from indexed format descriptor - bit3= -reserved- - bit4= enforce re-format of (partly) formatted media - bit5= try to disable eventual defect management - bit6= try to avoid lengthy media certification - bit7= MMC expert application mode (else libburn tries to - choose a suitable format type): - bit8 to bit15 contain the index of the format to use. See - burn_disc_get_formats(), burn_disc_get_format_descr(). - Acceptable types are: 0x00, 0x01, 0x10, 0x11, 0x13, - 0x15, 0x26, 0x30, 0x31. - If bit7 is set, bit4 is set automatically. -*/ -void burn_disc_format(struct burn_drive *drive, off_t size, int flag); - - -/* ts A70112 */ -/** Possible formatting status values */ -#define BURN_FORMAT_IS_UNFORMATTED 1 -#define BURN_FORMAT_IS_FORMATTED 2 -#define BURN_FORMAT_IS_UNKNOWN 3 - -/** Inquire the formatting status, the associated sizes and the number of - available formats. The info is media specific and stems from MMC command - 23h READ FORMAT CAPACITY. See mmc5r03c.pdf 6.24 for background details. - Media type can be determined via burn_disc_get_profile(). - @param drive The drive with the disc to format. - @param status The current formatting status of the inserted media. - See BURN_FORMAT_IS_* macros. Note: "unknown" is the - legal status for quick formatted, yet unwritten DVD-RW. - @param size The size in bytes associated with status. - unformatted: the maximum achievable size of the media - formatted: the currently formatted capacity - unknown: maximum capacity of drive or of media - @param bl_sas Additional info "Block Length/Spare Area Size". - Expected to be constantly 2048 for non-BD media. - @param num_formats The number of available formats. To be used with - burn_disc_get_format_descr() to obtain such a format - and eventually with burn_disc_format() to select one. - @return 1 reply is valid , <=0 failure -*/ -int burn_disc_get_formats(struct burn_drive *drive, int *status, off_t *size, - unsigned *bl_sas, int *num_formats); - -/** Inquire parameters of an available media format. - @param drive The drive with the disc to format. - @param index The index of the format item. Beginning with 0 up to reply - parameter from burn_disc_get_formats() : num_formats - 1 - @param type The format type. See mmc5r03c.pdf, 6.5, 04h FORMAT UNIT. - 0x00=full, 0x10=CD-RW/DVD-RW full, 0x11=CD-RW/DVD-RW grow, - 0x15=DVD-RW quick, 0x13=DVD-RW quick grow, - 0x26=DVD+RW background - @param size The maximum size in bytes achievable with this format. - @param tdp Type Dependent Parameter. See mmc5r03c.pdf. - @return 1 reply is valid , <=0 failure -*/ -int burn_disc_get_format_descr(struct burn_drive *drive, int index, - int *type, off_t *size, unsigned *tdp); - - - -/* ts A61109 : this was and is defunct */ -/** Read a disc from the drive and write it to an fd pair. The drive must be - grabbed successfully BEFORE calling this function. Always ensure that the - drive reports a status of BURN_DISC_FULL before calling this function. - @param drive The drive from which to read a disc. - @param o The options for the read operation. -*/ -void burn_disc_read(struct burn_drive *drive, const struct burn_read_opts *o); - - - -/* ts A70222 */ -/** The length of a rejection reasons string for burn_precheck_write() and - burn_write_opts_auto_write_type() . -*/ -#define BURN_REASONS_LEN 4096 - - -/* ts A70219 */ -/** Examines a completed setup for burn_disc_write() whether it is permissible - with drive and media. This function is called by burn_disc_write() but - an application might be interested in this check in advance. - @param o The options for the writing operation. - @param disc The descrition of the disc to be created - @param reasons Eventually returns a list of rejection reason statements - @param silent 1= do not issue error messages , 0= report problems - @return 1 ok, -1= no recordable media detected, 0= other failure -*/ -int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc, - char reasons[BURN_REASONS_LEN], int silent); - - -/** Write a disc in the drive. The drive must be grabbed successfully before - calling this function. Always ensure that the drive reports a status of - BURN_DISC_BLANK ot BURN_DISC_APPENDABLE before calling this function. - Note: write_type BURN_WRITE_SAO is currently not capable of writing a mix - of data and audio tracks. You must use BURN_WRITE_TAO for such sessions. - To be set by burn_write_opts_set_write_type(). - Note: This function is not suitable for overwriting data in the middle of - a valid data area because it is allowed to append trailing data. - For exact random access overwriting use burn_random_access_write(). - @param o The options for the writing operation. - @param disc The struct burn_disc * that described the disc to be created -*/ -void burn_disc_write(struct burn_write_opts *o, struct burn_disc *disc); - -/** Cancel an operation on a drive. - This will only work when the drive's busy state is BURN_DRIVE_READING or - BURN_DRIVE_WRITING. - @param drive The drive on which to cancel the current operation. -*/ -void burn_drive_cancel(struct burn_drive *drive); - - -/* ts A61223 */ -/** Inquire whether the most recent write run was successful. Reasons for - non-success may be: rejection of burn parameters, abort during fatal errors - during write, a call to burn_drive_cancel() by the application thread. - @param d The drive to inquire. - @return 1=burn seems to have went well, 0=burn failed -*/ -int burn_drive_wrote_well(struct burn_drive *d); - - -/** Convert a minute-second-frame (MSF) value to sector count - @param m Minute component - @param s Second component - @param f Frame component - @return The sector count -*/ -int burn_msf_to_sectors(int m, int s, int f); - -/** Convert a sector count to minute-second-frame (MSF) - @param sectors The sector count - @param m Returns the minute component - @param s Returns the second component - @param f Returns the frame component -*/ -void burn_sectors_to_msf(int sectors, int *m, int *s, int *f); - -/** Convert a minute-second-frame (MSF) value to an lba - @param m Minute component - @param s Second component - @param f Frame component - @return The lba -*/ -int burn_msf_to_lba(int m, int s, int f); - -/** Convert an lba to minute-second-frame (MSF) - @param lba The lba - @param m Returns the minute component - @param s Returns the second component - @param f Returns the frame component -*/ -void burn_lba_to_msf(int lba, int *m, int *s, int *f); - -/** Create a new disc - @return Pointer to a burn_disc object or NULL on failure. -*/ -struct burn_disc *burn_disc_create(void); - -/** Delete disc and decrease the reference count on all its sessions - @param d The disc to be freed -*/ -void burn_disc_free(struct burn_disc *d); - -/** Create a new session - @return Pointer to a burn_session object or NULL on failure. - */ -struct burn_session *burn_session_create(void); - -/** Free a session (and decrease reference count on all tracks inside) - @param s Session to be freed -*/ -void burn_session_free(struct burn_session *s); - -/** Add a session to a disc at a specific position, increasing the - sessions's reference count. - @param d Disc to add the session to - @param s Session to add to the disc - @param pos position to add at (BURN_POS_END is "at the end") - @return 0 for failure, 1 for success -*/ -int burn_disc_add_session(struct burn_disc *d, struct burn_session *s, - unsigned int pos); - -/** Remove a session from a disc - @param d Disc to remove session from - @param s Session pointer to find and remove -*/ -int burn_disc_remove_session(struct burn_disc *d, struct burn_session *s); - - -/** Create a track (for TAO recording, or to put in a session) */ -struct burn_track *burn_track_create(void); - -/** Free a track - @param t Track to free -*/ -void burn_track_free(struct burn_track *t); - -/** Add a track to a session at specified position - @param s Session to add to - @param t Track to insert in session - @param pos position to add at (BURN_POS_END is "at the end") - @return 0 for failure, 1 for success -*/ -int burn_session_add_track(struct burn_session *s, struct burn_track *t, - unsigned int pos); - -/** Remove a track from a session - @param s Session to remove track from - @param t Track pointer to find and remove - @return 0 for failure, 1 for success -*/ -int burn_session_remove_track(struct burn_session *s, struct burn_track *t); - - -/** Define the data in a track - @param t the track to define - @param offset The lib will write this many 0s before start of data - @param tail The number of extra 0s to write after data - @param pad 1 means the lib should pad the last sector with 0s if the - track isn't exactly sector sized. (otherwise the lib will - begin reading from the next track) - @param mode data format (bitfield) -*/ -void burn_track_define_data(struct burn_track *t, int offset, int tail, - int pad, int mode); - - -/* ts A61024 */ -/** Define whether a track shall swap bytes of its input stream. - @param t The track to change - @param swap_source_bytes 0=do not swap, 1=swap byte pairs - @return 1=success , 0=unacceptable value -*/ -int burn_track_set_byte_swap(struct burn_track *t, int swap_source_bytes); - - -/** Set the ISRC details for a track - @param t The track to change - @param country the 2 char country code. Each character must be - only numbers or letters. - @param owner 3 char owner code. Each character must be only numbers - or letters. - @param year 2 digit year. A number in 0-99 (Yep, not Y2K friendly). - @param serial 5 digit serial number. A number in 0-99999. -*/ -void burn_track_set_isrc(struct burn_track *t, char *country, char *owner, - unsigned char year, unsigned int serial); - -/** Disable ISRC parameters for a track - @param t The track to change -*/ -void burn_track_clear_isrc(struct burn_track *t); - -/** Hide the first track in the "pre gap" of the disc - @param s session to change - @param onoff 1 to enable hiding, 0 to disable -*/ -void burn_session_hide_first_track(struct burn_session *s, int onoff); - -/** Get the drive's disc struct - free when done - @param d drive to query - @return the disc struct or NULL on failure -*/ -struct burn_disc *burn_drive_get_disc(struct burn_drive *d); - -/** Set the track's data source - @param t The track to set the data source for - @param s The data source to use for the contents of the track - @return An error code stating if the source is ready for use for - writing the track, or if an error occured - -*/ -enum burn_source_status burn_track_set_source(struct burn_track *t, - struct burn_source *s); - - -/* ts A70218 */ -/** Set a default track size to be used only if the track turns out to be of - unpredictable length and if the effective write type demands a fixed size. - This can be useful to enable write types CD SAO or DVD DAO together with - a track source like stdin. If the track source delivers fewer bytes than - announced then the track will be padded up with zeros. - @param t The track to change - @param size The size to set - @return 0=failure 1=sucess -*/ -int burn_track_set_default_size(struct burn_track *t, off_t size); - -/** Free a burn_source (decrease its refcount and maybe free it) - @param s Source to free -*/ -void burn_source_free(struct burn_source *s); - -/** Creates a data source for an image file (and maybe subcode file) - @param path The file address for the main channel payload. - @param subpath Eventual address for subchannel data. Only used in exotic - raw write modes. Submit NULL for normal tasks. - @return Pointer to a burn_source object, NULL indicates failure -*/ -struct burn_source *burn_file_source_new(const char *path, - const char *subpath); - -/** Creates a data source for an image file (a track) from an open - readable filedescriptor, an eventually open readable subcodes file - descriptor and eventually a fixed size in bytes. - @param datafd The source of data. - @param subfd The eventual source of subchannel data. Only used in exotic - raw write modes. Submit -1 for normal tasks. - @param size The eventual fixed size of eventually both fds. - If this value is 0, the size will be determined from datafd. - @return Pointer to a burn_source object, NULL indicates failure -*/ -struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size); - - -/* ts A70930 */ -/** Creates a fifo which acts as proxy for an already existing data source. - The fifo provides a ring buffer which shall smoothen the data stream - between burn_source and writer thread. Each fifo serves only for one - data source and gets attached to one track as its only data source - by burn_track_set_source(). - A fifo starts its life in "standby" mode with no buffer space allocated. - As soon as its track requires bytes, the fifo establishes a worker thread - and allocates its buffer. After input has ended and all buffer content is - consumed, the buffer space gets freed and the worker thread ends. - This happens asynchronously. So expect two buffers and worker threads to - exist for a short time between tracks. Be modest in your size demands if - multiple tracks are to be expected. - @param inp The burn_source for which the fifo shall act as proxy. - It can be disposed by burn_source_free() immediately - after this call. - @param chunksize The size in bytes of a chunk. Use 2048 for sources - suitable for BURN_BLOCK_MODE1 and 2352 for sources - which deliver for BURN_BLOCK_AUDIO. - Some variations of burn_source might work only with - a particular chunksize. E.g. libisofs demands 2048. - @param chunks The number of chunks to be allocated in ring buffer. - This value must be >= 2. - @param flag Bitfield for control purposes (unused yet, submit 0). - @return A pointer to the newly created burn_source. - Later both burn_sources, inp and the returned fifo, have - to be disposed by calling burn_source_free() for each. - inp can be freed immediately, the returned fifo may be - kept as handle for burn_fifo_inquire_status(). -*/ -struct burn_source *burn_fifo_source_new(struct burn_source *inp, - int chunksize, int chunks, int flag); - -/* ts A71003 */ -/** Inquires state and fill parameters of a fifo burn_source which was created - by burn_fifo_source_new() . Do not use with other burn_source variants. - @param fifo The fifo object to inquire - @param size The total size of the fifo - @param free_bytes The current free capacity of the fifo - @param status_text Returns a pointer to a constant text, see below - @return <0 reply invalid, >=0 fifo status code: - bit0+1=input status, bit2=consumption status, i.e: - 0="standby" : data processing not started yet - 1="active" : input and consumption are active - 2="ending" : input has ended without error - 3="failing" : input had error and ended, - 4="unused" : ( consumption has ended before processing start ) - 5="abandoned" : consumption has ended prematurely - 6="ended" : consumption has ended without input error - 7="aborted" : consumption has ended after input error -*/ -int burn_fifo_inquire_status(struct burn_source *fifo, int *size, - int *free_bytes, char **status_text); - - -/* ts A70328 */ -/** Sets a fixed track size after the data source object has already been - created. - @param t The track to operate on - @param size the number of bytes to use as track size - @return <=0 indicates failure , >0 success -*/ -int burn_track_set_size(struct burn_track *t, off_t size); - - -/** Tells how long a track will be on disc - >>> NOTE: Not reliable with tracks of undefined length -*/ -int burn_track_get_sectors(struct burn_track *); - - -/* ts A61101 */ -/** Tells how many source bytes have been read and how many data bytes have - been written by the track during burn */ -int burn_track_get_counters(struct burn_track *t, - off_t *read_bytes, off_t *written_bytes); - - -/** Sets drive read and write speed - Note: "k" is 1000, not 1024. 1xCD = 176.4 k/s, 1xDVD = 1385 k/s. - Fractional speeds should be rounded up. Like 4xCD = 706. - @param d The drive to set speed for - @param read Read speed in k/s (0 is max, -1 is min). - @param write Write speed in k/s (0 is max, -1 is min). -*/ -void burn_drive_set_speed(struct burn_drive *d, int read, int write); - - -/* ts A70711 */ -/** Controls the behavior with writing when the drive buffer is suspected to - be full. To check and wait for enough free buffer space before writing - will move the task of waiting from the operating system's device driver - to libburn. While writing is going on and waiting is enabled, any write - operation will be checked whether it will fill the drive buffer up to - more than max_percent. If so, then waiting will happen until the buffer - fill is predicted with at most min_percent. - Thus: if min_percent < max_percent then transfer rate will oscillate. - This may allow the driver to operate on other devices, e.g. a disk from - which to read the input for writing. On the other hand, this checking might - reduce maximum throughput to the drive or even get misled by faulty buffer - fill replies from the drive. - If a setting parameter is < 0, then this setting will stay unchanged - by the call. - Known burner or media specific pitfalls: - To have max_percent larger than the burner's best reported buffer fill has - the same effect as min_percent==max_percent. Some burners do not report - their full buffer with all media types. Some are not suitable because - they report their buffer fill with delay. - @param d The drive to control - @param enable 0= disable , 1= enable waiting , (-1 = do not change setting) - @param min_usec Shortest possible sleeping period (given in micro seconds) - @param max_usec Longest possible sleeping period (given in micro seconds) - @param timeout_sec If a single write has to wait longer than this number - of seconds, then waiting gets disabled and mindless - writing starts. A value of 0 disables this timeout. - @param min_percent Minimum of desired buffer oscillation: 25 to 100 - @param max_percent Maximum of desired buffer oscillation: 25 to 100 - @return 1=success , 0=failure -*/ -int burn_drive_set_buffer_waiting(struct burn_drive *d, int enable, - int min_usec, int max_usec, int timeout_sec, - int min_percent, int max_percent); - - -/* these are for my debugging, they will disappear */ -void burn_structure_print_disc(struct burn_disc *d); -void burn_structure_print_session(struct burn_session *s); -void burn_structure_print_track(struct burn_track *t); - -/** Sets the write type for the write_opts struct. - Note: write_type BURN_WRITE_SAO is currently not capable of writing a mix - of data and audio tracks. You must use BURN_WRITE_TAO for such sessions. - @param opts The write opts to change - @param write_type The write type to use - @param block_type The block type to use - @return Returns 1 on success and 0 on failure. -*/ -int burn_write_opts_set_write_type(struct burn_write_opts *opts, - enum burn_write_types write_type, - int block_type); - - -/* ts A70207 */ -/** As an alternative to burn_write_opts_set_write_type() this function tries - to find a suitable write type and block type for a given write job - described by opts and disc. To be used after all other setups have been - made, i.e. immediately before burn_disc_write(). - @param opts The nearly complete write opts to change - @param disc The already composed session and track model - @param reasons This text string collects reasons for decision resp. failure - @param flag Bitfield for control purposes: - bit0= do not choose type but check the one that is already set - bit1= do not issue error messages via burn_msgs queue - (is automatically set with bit0) - @return Chosen write type. BURN_WRITE_NONE on failure. -*/ -enum burn_write_types burn_write_opts_auto_write_type( - struct burn_write_opts *opts, struct burn_disc *disc, - char reasons[BURN_REASONS_LEN], int flag); - - -/** Supplies toc entries for writing - not normally required for cd mastering - @param opts The write opts to change - @param count The number of entries - @param toc_entries -*/ -void burn_write_opts_set_toc_entries(struct burn_write_opts *opts, - int count, - struct burn_toc_entry *toc_entries); - -/** Sets the session format for a disc - @param opts The write opts to change - @param format The session format to set -*/ -void burn_write_opts_set_format(struct burn_write_opts *opts, int format); - -/** Sets the simulate value for the write_opts struct . - This corresponds to the Test Write bit in MMC mode page 05h. Several media - types do not support this. See struct burn_multi_caps.might_simulate for - actual availability of this feature. - If the media is suitable, the drive will perform burn_write_disc() as a - simulation instead of effective write operations. This means that the - media content and burn_disc_get_status() stay unchanged. - Note: With stdio-drives, the target file gets eventually created, opened, - lseeked, and closed, but not written. So there are effects on it. - Warning: Call burn_random_access_write() will never do simulation because - it does not get any burn_write_opts. - @param opts The write opts to change - @param sim Non-zero enables simulation, 0 enables real writing - @return Returns 1 on success and 0 on failure. -*/ -int burn_write_opts_set_simulate(struct burn_write_opts *opts, int sim); - -/** Controls buffer underrun prevention - @param opts The write opts to change - @param underrun_proof if non-zero, buffer underrun protection is enabled - @return Returns 1 on success and 0 on failure. -*/ -int burn_write_opts_set_underrun_proof(struct burn_write_opts *opts, - int underrun_proof); - -/** Sets whether to use opc or not with the write_opts struct - @param opts The write opts to change - @param opc If non-zero, optical power calibration will be performed at - start of burn - -*/ -void burn_write_opts_set_perform_opc(struct burn_write_opts *opts, int opc); - -void burn_write_opts_set_has_mediacatalog(struct burn_write_opts *opts, int has_mediacatalog); - -void burn_write_opts_set_mediacatalog(struct burn_write_opts *opts, unsigned char mediacatalog[13]); - - -/* ts A61106 */ -/** Sets the multi flag which eventually marks the emerging session as not - being the last one and thus creating a BURN_DISC_APPENDABLE media. - @param opts The option object to be manipulated - @param multi 1=media will be appendable, 0=media will be closed (default) -*/ -void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi); - - -/* ts A61222 */ -/** Sets a start address for writing to media and write modes which allow to - choose this address at all (for now: DVD+RW, DVD-RAM, formatted DVD-RW). - now). The address is given in bytes. If it is not -1 then a write run - will fail if choice of start address is not supported or if the block - alignment of the address is not suitable for media and write mode. - Alignment to 32 kB blocks is supposed to be safe with DVD media. - Call burn_disc_get_multi_caps() can obtain the necessary media info. See - resulting struct burn_multi_caps elements .start_adr , .start_alignment , - .start_range_low , .start_range_high . - @param opts The write opts to change - @param value The address in bytes (-1 = start at default address) -*/ -void burn_write_opts_set_start_byte(struct burn_write_opts *opts, off_t value); - - -/* ts A70213 */ -/** Caution: still immature and likely to change. Problems arose with - sequential DVD-RW on one drive. - - Controls whether the whole available space of the media shall be filled up - by the last track of the last session. - @param opts The write opts to change - @param fill_up_media If 1 : fill up by last track, if 0 = do not fill up -*/ -void burn_write_opts_set_fillup(struct burn_write_opts *opts, - int fill_up_media); - - -/* ts A70303 */ -/** Eventually makes libburn ignore the failure of some conformance checks: - - the check whether CD write+block type is supported by the drive - - the check whether the media profile supports simulated burning - @param opts The write opts to change - @param use_force 1=ignore above checks, 0=refuse work on failed check -*/ -void burn_write_opts_set_force(struct burn_write_opts *opts, int use_force); - - -/* ts A80412 */ -/** Eventually makes use of the more modern write command AAh WRITE12 and - sets the Streaming bit. With DVD-RAM this can override the traditional - slowdown to half nominal speed. But if it speeds up writing then it also - disables error management and correction. Weigh your priorities. - This only affects the write operations of burn_disc_write(). - @since 0.4.6 - @param opts The write opts to change - @param value 0=use 2Ah WRITE10, 1=use AAh WRITE12 with Streaming bit -*/ -void burn_write_opts_set_stream_recording(struct burn_write_opts *opts, - int value); - - -/** Sets whether to read in raw mode or not - @param opts The read opts to change - @param raw_mode If non-zero, reading will be done in raw mode, so that everything in the data tracks on the - disc is read, including headers. -*/ -void burn_read_opts_set_raw(struct burn_read_opts *opts, int raw_mode); - -/** Sets whether to report c2 errors or not - @param opts The read opts to change - @param c2errors If non-zero, report c2 errors. -*/ -void burn_read_opts_set_c2errors(struct burn_read_opts *opts, int c2errors); - -/** Sets whether to read subcodes from audio tracks or not - @param opts The read opts to change - @param subcodes_audio If non-zero, read subcodes from audio tracks on the disc. -*/ -void burn_read_opts_read_subcodes_audio(struct burn_read_opts *opts, - int subcodes_audio); - -/** Sets whether to read subcodes from data tracks or not - @param opts The read opts to change - @param subcodes_data If non-zero, read subcodes from data tracks on the disc. -*/ -void burn_read_opts_read_subcodes_data(struct burn_read_opts *opts, - int subcodes_data); - -/** Sets whether to recover errors if possible - @param opts The read opts to change - @param hardware_error_recovery If non-zero, attempt to recover errors if possible. -*/ -void burn_read_opts_set_hardware_error_recovery(struct burn_read_opts *opts, - int hardware_error_recovery); - -/** Sets whether to report recovered errors or not - @param opts The read opts to change - @param report_recovered_errors If non-zero, recovered errors will be reported. -*/ -void burn_read_opts_report_recovered_errors(struct burn_read_opts *opts, - int report_recovered_errors); - -/** Sets whether blocks with unrecoverable errors should be read or not - @param opts The read opts to change - @param transfer_damaged_blocks If non-zero, blocks with unrecoverable errors will still be read. -*/ -void burn_read_opts_transfer_damaged_blocks(struct burn_read_opts *opts, - int transfer_damaged_blocks); - -/** Sets the number of retries to attempt when trying to correct an error - @param opts The read opts to change - @param hardware_error_retries The number of retries to attempt when correcting an error. -*/ -void burn_read_opts_set_hardware_error_retries(struct burn_read_opts *opts, - unsigned char hardware_error_retries); - -/** Gets the maximum write speed for a drive and eventually loaded media. - The return value might change by the media type of already loaded media, - again by call burn_drive_grab() and again by call burn_disc_read_atip(). - @param d Drive to query - @return Maximum write speed in K/s -*/ -int burn_drive_get_write_speed(struct burn_drive *d); - - -/* ts A61021 */ -/** Gets the minimum write speed for a drive and eventually loaded media. - The return value might change by the media type of already loaded media, - again by call burn_drive_grab() and again by call burn_disc_read_atip(). - @param d Drive to query - @return Minimum write speed in K/s -*/ -int burn_drive_get_min_write_speed(struct burn_drive *d); - - -/** Gets the maximum read speed for a drive - @param d Drive to query - @return Maximum read speed in K/s -*/ -int burn_drive_get_read_speed(struct burn_drive *d); - - -/* ts A61226 */ -/** Obtain a copy of the current speed descriptor list. The drive's list gets - updated on various occasions such as burn_drive_grab() but the copy - obtained here stays untouched. It has to be disposed via - burn_drive_free_speedlist() when it is not longer needed. Speeds - may appear several times in the list. The list content depends much on - drive and media type. It seems that .source == 1 applies mostly to CD media - whereas .source == 2 applies to any media. - @param d Drive to query - @param speed_list The copy. If empty, *speed_list gets returned as NULL. - @return 1=success , 0=list empty , <0 severe error -*/ -int burn_drive_get_speedlist(struct burn_drive *d, - struct burn_speed_descriptor **speed_list); - -/* ts A70713 */ -/** Look up the fastest speed descriptor which is not faster than the given - speed_goal. If it is 0, then the fastest one is chosen among the - descriptors with the highest end_lba. If it is -1 then the slowest speed - descriptor is chosen regardless of end_lba. Parameter flag decides whether - the speed goal means write speed or read speed. - @param d Drive to query - @param speed_goal Upper limit for speed, - 0=search for maximum speed , -1 search for minimum speed - @param best_descr Result of the search, NULL if no match - @param flag Bitfield for control purposes - bit0= look for best read speed rather than write speed - bit1= look for any source type (else look for source==2 first - and for any other source type only with CD media) - @return >0 indicates a valid best_descr, 0 = no valid best_descr -*/ -int burn_drive_get_best_speed(struct burn_drive *d, int speed_goal, - struct burn_speed_descriptor **best_descr, int flag); - - -/* ts A61226 */ -/** Dispose a speed descriptor list copy which was obtained by - burn_drive_get_speedlist(). - @param speed_list The list copy. *speed_list gets set to NULL. - @return 1=list disposed , 0= *speedlist was already NULL -*/ -int burn_drive_free_speedlist(struct burn_speed_descriptor **speed_list); - - -/* ts A70203 */ -/** The reply structure for burn_disc_get_multi_caps() -*/ -struct burn_multi_caps { - - /* Multi-session capability allows to keep the media appendable after - writing a session. It also guarantees that the drive will be able - to predict and use the appropriate Next Writeable Address to place - the next session on the media without overwriting the existing ones. - It does not guarantee that the selected write type is able to do - an appending session after the next session. (E.g. CD SAO is capable - of multi-session by keeping a disc appendable. But .might_do_sao - will be 0 afterwards, when checking the appendable media.) - 1= media may be kept appendable by burn_write_opts_set_multi(o,1) - 0= media will not be appendable - */ - int multi_session; - - /* Multi-track capability allows to write more than one track source - during a single session. The written tracks can later be found in - libburn's TOC model with their start addresses and sizes. - 1= multiple tracks per session are allowed - 0= only one track per session allowed - */ - int multi_track; - - /* Start-address capability allows to set a non-zero address with - burn_write_opts_set_start_byte(). Eventually this has to respect - .start_alignment and .start_range_low, .start_range_high in this - structure. - 1= non-zero start address is allowed - 0= only start address 0 is allowed (to depict the drive's own idea - about the appropriate write start) - */ - int start_adr; - - /** The alignment for start addresses. - ( start_address % start_alignment ) must be 0. - */ - off_t start_alignment; - - /** The lowest permissible start address. - */ - off_t start_range_low; - - /** The highest addressable start address. - */ - off_t start_range_high; - - /** Potential availability of write modes - 4= needs no size prediction, not to be chosen automatically - 3= needs size prediction, not to be chosen automatically - 2= available, no size prediction necessary - 1= available, needs exact size prediction - 0= not available - With CD media (profiles 0x09 and 0x0a) check also the elements - *_block_types of the according write mode. - */ - int might_do_tao; - int might_do_sao; - int might_do_raw; - - /** Generally advised write mode. - Not necessarily the one chosen by burn_write_opts_auto_write_type() - because the burn_disc structure might impose particular demands. - */ - enum burn_write_types advised_write_mode; - - /** Write mode as given by parameter wt of burn_disc_get_multi_caps(). - */ - enum burn_write_types selected_write_mode; - - /** Profile number which was current when the reply was generated */ - int current_profile; - - /** Wether the current profile indicates CD media. 1=yes, 0=no */ - int current_is_cd_profile; - - /* ts A70528, added to version 0.3.7 */ - /** Wether the current profile is able to perform simulated write */ - int might_simulate; -}; - -/** Allocates a struct burn_multi_caps (see above) and fills it with values - which are appropriate for the drive and the loaded media. The drive - must be grabbed for this call. The returned structure has to be disposed - via burn_disc_free_multi_caps() when no longer needed. - @param d The drive to inquire - @param wt With BURN_WRITE_NONE the best capabilities of all write modes - get returned. If set to a write mode like BURN_WRITE_SAO the - capabilities with that particular mode are returned and the - return value is 0 if the desired mode is not possible. - @param caps returns the info structure - @param flag Bitfield for control purposes (unused yet, submit 0) - @return < 0 : error , 0 : writing seems impossible , 1 : writing possible -*/ -int burn_disc_get_multi_caps(struct burn_drive *d, enum burn_write_types wt, - struct burn_multi_caps **caps, int flag); - -/** Removes from memory a multi session info structure which was returned by - burn_disc_get_multi_caps(). The pointer *caps gets set to NULL. - @param caps the info structure to dispose (note: pointer to pointer) - @return 0 : *caps was already NULL, 1 : memory object was disposed -*/ -int burn_disc_free_multi_caps(struct burn_multi_caps **caps); - - -/** Gets a copy of the toc_entry structure associated with a track - @param t Track to get the entry from - @param entry Struct for the library to fill out -*/ -void burn_track_get_entry(struct burn_track *t, struct burn_toc_entry *entry); - -/** Gets a copy of the toc_entry structure associated with a session's lead out - @param s Session to get the entry from - @param entry Struct for the library to fill out -*/ -void burn_session_get_leadout_entry(struct burn_session *s, - struct burn_toc_entry *entry); - -/** Gets an array of all the sessions for the disc - THIS IS NO LONGER VALID AFTER YOU ADD OR REMOVE A SESSION - @param d Disc to get session array for - @param num Returns the number of sessions in the array - @return array of sessions -*/ -struct burn_session **burn_disc_get_sessions(struct burn_disc *d, - int *num); - -int burn_disc_get_sectors(struct burn_disc *d); - -/** Gets an array of all the tracks for a session - THIS IS NO LONGER VALID AFTER YOU ADD OR REMOVE A TRACK - @param s session to get track array for - @param num Returns the number of tracks in the array - @return array of tracks -*/ -struct burn_track **burn_session_get_tracks(struct burn_session *s, - int *num); - -int burn_session_get_sectors(struct burn_session *s); - -/** Gets the mode of a track - @param track the track to query - @return the track's mode -*/ -int burn_track_get_mode(struct burn_track *track); - -/** Returns whether the first track of a session is hidden in the pregap - @param session the session to query - @return non-zero means the first track is hidden -*/ -int burn_session_get_hidefirst(struct burn_session *session); - -/** Returns the library's version in its parts. - This is the runtime counterpart of the three build time macros - burn_header_version_* below. - @param major The major version number - @param minor The minor version number - @param micro The micro version number -*/ -void burn_version(int *major, int *minor, int *micro); - - -/* ts A80129 */ -/** These three release version numbers tell the revision of this header file - and of the API it describes. They are memorized by applications at build - time. - Immediately after burn_initialize() an application should do this check: - burn_version(&major, &minor, µ); - if(major > burn_header_version_major - || (major == burn_header_version_major - && (minor > burn_header_version_minor - || (minor == burn_header_version_minor - && micro >= burn_header_version_micro)))) { - ... Young enough. Go on with program run .... - } else { - ... Too old. Do not use this libburn version ... - } - -*/ -#define burn_header_version_major 0 -#define burn_header_version_minor 4 -#define burn_header_version_micro 6 -/** Note: - Above version numbers are also recorded in configure.ac because libtool - wants them as parameters at build time. - For the library compatibility check BURN_*_VERSION in configure.ac - are not decisive. Only the three numbers above do matter. -*/ -/** Usage discussion: - -Some developers of the libburnia project have differing -opinions how to ensure the compatibility of libaries -and applications. - -It is about whether to use at compile time and at runtime -the version numbers isoburn_header_version_* provided here. -Thomas Schmitt advises to use them. -Vreixo Formoso advises to use other means. - -At compile time: - -Vreixo Formoso advises to leave proper version matching -to properly programmed checks in the the application's -build system, which will eventually refuse compilation. - -Thomas Schmitt advises to use the macros defined here -for comparison with the application's requirements of -library revisions and to eventually break compilation. - -Both advises are combinable. I.e. be master of your -build system and have #if checks in the source code -of your application, nevertheless. - -At runtime (via *_is_compatible()): - -Vreixo Formoso advises to compare the application's -requirements of library revisions with the runtime -library. This is to allow runtime libraries which are -young enough for the application but too old for -the lib*.h files seen at compile time. - -Thomas Schmitt advises to compare the header -revisions defined here with the runtime library. -This is to enforce a strictly monotonous chain -of revisions from app to header to library, -at the cost of excluding some older libraries. - -These two advises are mutually exclusive. - -*/ - - -/* ts A60924 : ticket 74 */ -/** Control queueing and stderr printing of messages from libburn. - Severity may be one of "NEVER", "ABORT", "FATAL", "FAILURE", "SORRY", - "WARNING", "HINT", "NOTE", "UPDATE", "DEBUG", "ALL". - @param queue_severity Gives the minimum limit for messages to be queued. - Default: "NEVER". If you queue messages then you - must consume them by burn_msgs_obtain(). - @param print_severity Does the same for messages to be printed directly - to stderr. Default: "FATAL". - @param print_id A text prefix to be printed before the message. - @return >0 for success, <=0 for error - -*/ -int burn_msgs_set_severities(char *queue_severity, - char *print_severity, char *print_id); - -/* ts A60924 : ticket 74 */ -#define BURN_MSGS_MESSAGE_LEN 4096 - -/** Obtain the oldest pending libburn message from the queue which has at - least the given minimum_severity. This message and any older message of - lower severity will get discarded from the queue and is then lost forever. - @param minimum_severity may be one of "NEVER", "ABORT", "FATAL", - "FAILURE", "SORRY", "WARNING", "HINT", "NOTE", "UPDATE", - "DEBUG", "ALL". - To call with minimum_severity "NEVER" will discard the - whole queue. - @param error_code Will become a unique error code as liste in - libburn/libdax_msgs.h - @param msg_text Must provide at least BURN_MSGS_MESSAGE_LEN bytes. - @param os_errno Will become the eventual errno related to the message - @param severity Will become the severity related to the message and - should provide at least 80 bytes. - @return 1 if a matching item was found, 0 if not, <0 for severe errors -*/ -int burn_msgs_obtain(char *minimum_severity, - int *error_code, char msg_text[], int *os_errno, - char severity[]); - - -/* ts A70922 */ -/** Submit a message to the libburn queueing system. It will be queued or - printed as if it was generated by libburn itself. - @param error_code The unique error code of your message. - Submit 0 if you do not have reserved error codes within - the libburnia project. - @param msg_text Not more than BURN_MSGS_MESSAGE_LEN characters of - message text. - @param os_errno Eventual errno related to the message. Submit 0 if - the message is not related to a operating system error. - @param severity One of "ABORT", "FATAL", "FAILURE", "SORRY", "WARNING", - "HINT", "NOTE", "UPDATE", "DEBUG". Defaults to "FATAL". - @param d An eventual drive to which the message shall be related. - Submit NULL if the message is not specific to a - particular drive object. - @return 1 if message was delivered, <=0 if failure -*/ -int burn_msgs_submit(int error_code, char msg_text[], int os_errno, - char severity[], struct burn_drive *d); - - -/* ts A71016 */ -/** Convert a severity name into a severity number, which gives the severity - rank of the name. - @param severity_name A name as with burn_msgs_submit(), e.g. "SORRY". - @param severity_number The rank number: the higher, the more severe. - @param flag Bitfield for control purposes (unused yet, submit 0) - @return >0 success, <=0 failure -*/ -int burn_text_to_sev(char *severity_name, int *severity_number, int flag); - - -/* ts A80202 */ -/** Convert a severity number into a severity name - @since 0.4.4 - @param severity_number The rank number: the higher, the more severe. - @param severity_name A name as with burn_msgs_submit(), e.g. "SORRY". - @param flag Bitfield for control purposes (unused yet, submit 0) -*/ -int burn_sev_to_text(int severity_number, char **severity_name, int flag); - - - -/* ts A70915 */ -/** Replace the messenger object handle of libburn by a compatible handle - obtained from a related library. - See also: libisofs, API function iso_get_messenger(). - @param messenger The foreign but compatible message handle. - @return 1 : success, <=0 : failure -*/ -int burn_set_messenger(void *messenger); - - -/* ts A61002 */ -/** The prototype of a handler function suitable for burn_set_abort_handling(). - Such a function has to return -2 if it does not want the process to - exit with value 1. -*/ -typedef int (*burn_abort_handler_t)(void *handle, int signum, int flag); - -/** Control builtin signal handling. See also burn_abort(). - @param handle Opaque handle eventually pointing to an application - provided memory object - @param handler A function to be called on signals. It will get handle as - argument. It should finally call burn_abort(). See there. - @param mode : 0 call handler(handle, signum, 0) on nearly all signals - 1 enable system default reaction on all signals - 2 try to ignore nearly all signals - 10 like mode 2 but handle SIGABRT like with mode 0 - Arguments (text, NULL, 0) activate the builtin abort handler. It will - eventually call burn_abort() and then perform exit(1). If text is not NULL - then it is used as prefix for pacifier messages of burn_abort_pacifier(). -*/ -void burn_set_signal_handling(void *handle, burn_abort_handler_t handler, - int mode); - - -/* ts A70811 */ -/** Write data in random access mode. - The drive must be grabbed successfully before calling this function which - circumvents usual libburn session processing and rather writes data without - preparations or finalizing. This will work only with overwriteable media - which are also suitable for burn_write_opts_set_start_byte(). The same - address alignment restrictions as with this function apply. I.e. for DVD - it is best to align to 32 KiB blocks (= 16 LBA units). The amount of data - to be written is subject to the same media dependent alignment rules. - Again, 32 KiB is most safe. - Call burn_disc_get_multi_caps() can obtain the necessary media info. See - resulting struct burn_multi_caps elements .start_adr , .start_alignment , - .start_range_low , .start_range_high . - Other than burn_disc_write() this is a synchronous call which returns - only after the write transaction has ended (sucessfully or not). So it is - wise not to transfer giant amounts of data in a single call. - Important: Data have to fit into the already formatted area of the media. - @param d The drive to which to write - @param byte_address The start address of the write in byte - (1 LBA unit = 2048 bytes) (do respect media alignment) - @param data The bytes to be written - @param data_count The number of those bytes (do respect media alignment) - data_count == 0 is permitted (e.g. to flush the - drive buffer without further data transfer). - @param flag Bitfield for control purposes: - bit0 = flush the drive buffer after eventual writing - @return 1=sucessful , <=0 : number of transfered bytes * -1 -*/ -int burn_random_access_write(struct burn_drive *d, off_t byte_address, - char *data, off_t data_count, int flag); - - -/* ts A70812 */ -/** Read data in random access mode. - The drive must be grabbed successfully before calling this function. - With all currently supported drives and media the byte_address has to - be aligned to 2048 bytes. Only data tracks with 2048 bytes per sector - can be read this way. I.e. not CD-audio, not CD-video-stream ... - This is a synchronous call which returns only after the full read job - has ended (sucessfully or not). So it is wise not to read giant amounts - of data in a single call. - @param d The drive to which to write - @param byte_address The start address of the read in byte (aligned to 2048) - @param data A memory buffer capable of taking data_size bytes - @param data_size The amount of data to be read. This does not have to - be aligned to any block size. - @param data_count The amount of data actually read (interesting on error) - @param flag Bitfield for control purposes: - bit0= - reserved - - bit1= do not submit error message if read error - @return 1=sucessful , <=0 an error occured -*/ -int burn_read_data(struct burn_drive *d, off_t byte_address, - char data[], off_t data_size, off_t *data_count, int flag); - - -/* A70904 */ -/** Inquire whether the drive object is a real MMC drive or a pseudo-drive - created by a stdio: address. - @param d The drive to inquire - @return 0= null-drive - 1= real MMC drive - 2= stdio-drive, random access, read-write - 3= stdio-drive, sequential, write-only -*/ -int burn_drive_get_drive_role(struct burn_drive *d); - - -/* ts A70923 */ -/** Find out whether a given address string would lead to the given drive - object. This should be done in advance for track source addresses - with parameter drive_role set to 2. - Although a real MMC drive should hardly exist as two drive objects at - the same time, this can easily happen with stdio-drives. So if more than - one drive is used by the application, then this gesture is advised: - burn_drive_d_get_adr(d2, adr2); - if (burn_drive_equals_adr(d1, adr2, burn_drive_get_drive_role(d2))) - ... Both drive objects point to the same storage facility ... - - @param d1 Existing drive object - @param adr2 Address string to be tested. Prefix "stdio:" overrides - parameter drive_role2 by either 0 or 2 as appropriate. - The string must be shorter than BURN_DRIVE_ADR_LEN. - @param drive_role2 Role as burn_drive_get_drive_role() would attribute - to adr2 if it was a drive. Use value 2 for checking track - sources resp. pseudo-drive addresses without "stdio:". - Use 1 for checking drive addresses including those with - prefix "stdio:". - @return 1= adr2 leads to d1 , 0= adr2 seems not to lead to d1, - -1 = adr2 is bad -*/ -int burn_drive_equals_adr(struct burn_drive *d1, char *adr2, int drive_role2); - - - -#ifndef DOXYGEN - -BURN_END_DECLS - -#endif - -#endif /*LIBBURN_H*/ diff --git a/libburn/libdax_audioxtr.c b/libburn/libdax_audioxtr.c deleted file mode 100644 index 888218e..0000000 --- a/libburn/libdax_audioxtr.c +++ /dev/null @@ -1,326 +0,0 @@ - -/* libdax_audioxtr - Audio track data extraction facility of libdax and libburn. - Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL -*/ - -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> - - -#include "libdax_msgs.h" -extern struct libdax_msgs *libdax_messenger; - - -/* Only this single source module is entitled to do this */ -#define LIBDAX_AUDIOXTR_H_INTERNAL 1 - -/* All clients of the extraction facility must do this */ -#include "libdax_audioxtr.h" - - -int libdax_audioxtr_new(struct libdax_audioxtr **xtr, char *path, int flag) -{ - int ret= -1; - struct libdax_audioxtr *o; - - o= *xtr= (struct libdax_audioxtr *) malloc(sizeof(struct libdax_audioxtr)); - if(o==NULL) - return(-1); - strncpy(o->path,path,LIBDAX_AUDIOXTR_STRLEN-1); - o->path[LIBDAX_AUDIOXTR_STRLEN-1]= 0; - o->fd= -1; - strcpy(o->fmt,"unidentified"); - o->fmt_info[0]= 0; - o->data_size= 0; - o->extract_count= 0; - - o->num_channels= 0; - o->sample_rate= 0; - o->bits_per_sample= 0; - o->msb_first= 0; - - o->wav_subchunk2_size= 0; - - o->au_data_location= 0; - o->au_data_size= 0xffffffff; - - ret= libdax_audioxtr_open(o,0); - if(ret<=0) - {ret= -2*(ret<0); goto failure;} - - return(1); -failure: - libdax_audioxtr_destroy(xtr,0); - return(ret); -} - - -int libdax_audioxtr_destroy(struct libdax_audioxtr **xtr, int flag) -{ - struct libdax_audioxtr *o; - - o= *xtr; - if(o==NULL) - return(0); - if(o->fd>=0 && strcmp(o->path,"-")!=0) - close(o->fd); - free((char *) o); - *xtr= NULL; - return(1); -} - - -static int libdax_audioxtr_open(struct libdax_audioxtr *o, int flag) -{ - int ret; - char msg[LIBDAX_AUDIOXTR_STRLEN+80]; - - if(strcmp(o->path,"-")==0) - o->fd= 0; - else - o->fd= open(o->path, O_RDONLY); - if(o->fd<0) { - sprintf(msg,"Cannot open audio source file : %s",o->path); - libdax_msgs_submit(libdax_messenger,-1,0x00020200, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - msg, errno, 0); - return(-1); - } - ret= libdax_audioxtr_identify(o,0); - if(ret<=0) { - sprintf(msg,"Audio source file has unsuitable format : %s",o->path); - libdax_msgs_submit(libdax_messenger,-1,0x00020201, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - return(0); - } - ret= libdax_audioxtr_init_reading(o,0); - if(ret<=0) { - sprintf(msg,"Failed to prepare reading of audio data : %s",o->path); - libdax_msgs_submit(libdax_messenger,-1,0x00020202, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - return(0); - } - return(1); -} - - -static int libdax_audioxtr_identify_wav(struct libdax_audioxtr *o, int flag) -{ - int ret; - char buf[45]; - - /* check wether this is a MS WAVE file .wav */ - /* info used: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ */ - - if(o->fd!=0) { - ret= lseek(o->fd,0,SEEK_SET); - if(ret==-1) - return(0); - } - ret= read(o->fd, buf, 44); - if(ret<44) - return(0); - buf[44]= 0; /* as stopper for any string operations */ - - if(strncmp(buf,"RIFF",4)!=0) /* ChunkID */ - return(0); - if(strncmp(buf+8,"WAVE",4)!=0) /* Format */ - return(0); - if(strncmp(buf+12,"fmt ",4)!=0) /* Subchunk1ID */ - return(0); - if(buf[16]!=16 || buf[17]!=0 || buf[18]!=0 || buf[19]!=0) /* Subchunk1Size */ - return(0); - if(buf[20]!=1 || buf[21]!=0) /* AudioFormat must be 1 (Linear quantization) */ - return(0); - - strcpy(o->fmt,".wav"); - o->msb_first= 0; - o->num_channels= libdax_audioxtr_to_int(o,(unsigned char *) buf+22,2,0); - o->sample_rate= libdax_audioxtr_to_int(o,(unsigned char *) buf+24,4,0); - o->bits_per_sample= libdax_audioxtr_to_int(o,(unsigned char *)buf+34,2,0); - sprintf(o->fmt_info, - ".wav , num_channels=%d , sample_rate=%d , bits_per_sample=%d", - o->num_channels,o->sample_rate,o->bits_per_sample); - o->wav_subchunk2_size= libdax_audioxtr_to_int(o,(unsigned char *)buf+40,4,0); - o->data_size= o->wav_subchunk2_size; - return(1); -} - - -static int libdax_audioxtr_identify_au(struct libdax_audioxtr *o, int flag) -{ - int ret,encoding; - char buf[24]; - - /* Check wether this is a Sun Audio, .au file */ - /* info used: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ */ - - if(o->fd!=0) { - ret= lseek(o->fd,0,SEEK_SET); - if(ret==-1) - return(0); - } - ret= read(o->fd, buf, 24); - if(ret<24) - return(0); - - if(strncmp(buf,".snd",4)!=0) - return(0); - strcpy(o->fmt,".au"); - o->msb_first= 1; - o->au_data_location= libdax_audioxtr_to_int(o,(unsigned char *)buf+4,4,1); - o->au_data_size= libdax_audioxtr_to_int(o,(unsigned char *)buf+8,4,1); - encoding= libdax_audioxtr_to_int(o,(unsigned char *)buf+12,4,1); - if(encoding==2) - o->bits_per_sample= 8; - else if(encoding==3) - o->bits_per_sample= 16; - else if(encoding==4) - o->bits_per_sample= 24; - else if(encoding==5) - o->bits_per_sample= 32; - else - o->bits_per_sample= -encoding; - o->sample_rate= libdax_audioxtr_to_int(o,(unsigned char *)buf+16,4,1); - o->num_channels= libdax_audioxtr_to_int(o,(unsigned char *)buf+20,4,1); - if(o->au_data_size!=0xffffffff) - o->data_size= o->au_data_size; - else - o->data_size= 0; - sprintf(o->fmt_info, - ".au , num_channels=%d , sample_rate=%d , bits_per_sample=%d", - o->num_channels,o->sample_rate,o->bits_per_sample); - - /* <<< for testing only */; - return(1); - - return(o->bits_per_sample>0); /* Audio format must be linear PCM */ -} - - -static int libdax_audioxtr_identify(struct libdax_audioxtr *o, int flag) -{ - int ret; - - ret= libdax_audioxtr_identify_wav(o, 0); - if(ret!=0) - return(ret); - if(o->fd==0) /* cannot rewind stdin */ - return(0); - ret= libdax_audioxtr_identify_au(o, 0); - if(ret!=0) - return(ret); - return(0); -} - - -/* @param flag bit0=msb_first */ -static unsigned libdax_audioxtr_to_int(struct libdax_audioxtr *o, - unsigned char *bytes, int len, int flag) -{ - unsigned int ret= 0; - int i; - - if(flag&1) - for(i= 0; i<len; i++) - ret= ret*256+bytes[i]; - else - for(i= len-1; i>=0; i--) - ret= ret*256+bytes[i]; - return(ret); -} - - -static int libdax_audioxtr_init_reading(struct libdax_audioxtr *o, int flag) -{ - int ret; - - - /* currently this only works for MS WAVE files .wav and Sun .au*/; - if(o->fd==0) /* stdin: hope no read came after libdax_audioxtr_identify() */ - return(1); - - o->extract_count= 0; - if(strcmp(o->fmt,".wav")==0) - ret= lseek(o->fd,44,SEEK_SET); - else if(strcmp(o->fmt,".au")==0) - ret= lseek(o->fd,o->au_data_location,SEEK_SET); - else - ret= -1; - if(ret==-1) - return(0); - - return(1); -} - - -int libdax_audioxtr_get_id(struct libdax_audioxtr *o, - char **fmt, char **fmt_info, - int *num_channels, int *sample_rate, int *bits_per_sample, - int *msb_first, int flag) -{ - *fmt= o->fmt; - *fmt_info= o->fmt_info; - *num_channels= o->num_channels; - *sample_rate= o->sample_rate; - *bits_per_sample= o->bits_per_sample; - *msb_first= o->msb_first; - return(1); -} - - -int libdax_audioxtr_get_size(struct libdax_audioxtr *o, off_t *size, int flag) -{ - *size= o->data_size; - return(1); -} - - -int libdax_audioxtr_read(struct libdax_audioxtr *o, - char buffer[], int buffer_size, int flag) -{ - int ret; - - if(buffer_size<=0 || o->fd<0) - return(-2); - if(o->data_size>0 && !(flag&1)) - if(buffer_size > o->data_size - o->extract_count) - buffer_size= o->data_size - o->extract_count; - if(buffer_size<=0) - return(0); - ret= read(o->fd,buffer,buffer_size); - if(ret>0) - o->extract_count+= ret; - return(ret); -} - - -int libdax_audioxtr_detach_fd(struct libdax_audioxtr *o, int *fd, int flag) -{ - if(o->fd<0) - return(-1); - if(strcmp(o->fmt,".wav")!=0 && strcmp(o->fmt,".au")!=0) - return(0); - if(flag&1) { - *fd= o->fd; - } else { - *fd= dup(o->fd); - if(*fd>=0 && strcmp(o->path,"-")!=0) - close(o->fd); - } - if(*fd>=0) { - o->fd= -1; - return(1); - } - return(-1); -} - diff --git a/libburn/libdax_audioxtr.h b/libburn/libdax_audioxtr.h deleted file mode 100644 index 72b62bf..0000000 --- a/libburn/libdax_audioxtr.h +++ /dev/null @@ -1,229 +0,0 @@ - -/* libdax_audioxtr - Audio track data extraction facility of libdax and libburn. - Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL -*/ - -#ifndef LIBDAX_AUDIOXTR_H_INCLUDED -#define LIBDAX_AUDIOXTR_H_INCLUDED 1 - - /* Public Macros */ - -/* Maximum size for address paths and fmt_info strings */ -#define LIBDAX_AUDIOXTR_STRLEN 4096 - - - /* Public Opaque Handles */ - -/** Extractor object encapsulating intermediate states of extraction. - The clients of libdax_audioxtr shall only allocate pointers to this - struct and get a storage object via libdax_audioxtr_new(). - Appropriate initial value for the pointer is NULL. -*/ -struct libdax_audioxtr; - - - /* Public Functions */ - - /* Calls initiated from inside libdax/libburn */ - - - /* Calls from applications (to be forwarded by libdax/libburn) */ - - -/** Open an audio file, check wether suitable, create extractor object. - @param xtr Opaque handle to extractor. Gets attached extractor object. - @param path Address of the audio file to extract. "-" is stdin (but might - be not suitable for all futurely supported formats). - @param flag Bitfield for control purposes (unused yet, submit 0) - @return >0 success - 0 unsuitable format - -1 severe error - -2 path not found -*/ -int libdax_audioxtr_new(struct libdax_audioxtr **xtr, char *path, int flag); - - -/** Obtain identification parameters of opened audio source. - @param xtr Opaque handle to extractor - @param fmt Gets pointed to the audio file format id text: ".wav" , ".au" - @param fmt_info Gets pointed to a format info text telling parameters - @param num_channels e.g. 1=mono, 2=stereo, etc - @param sample_rate e.g. 11025, 44100 - @param bits_per_sample e.g. 8= 8 bits per sample, 16= 16 bits ... - @param msb_first Byte order of samples: 0=Intel 1=Motorola - @param flag Bitfield for control purposes (unused yet, submit 0) - @return >0 success, <=0 failure -*/ -int libdax_audioxtr_get_id(struct libdax_audioxtr *xtr, - char **fmt, char **fmt_info, - int *num_channels, int *sample_rate, - int *bits_per_sample, int *msb_first, int flag); - - -/** Obtain a prediction about the extracted size based on internal information - of the formatted file. - @param xtr Opaque handle to extractor - @param size Gets filled with the predicted size - @param flag Bitfield for control purposes (unused yet, submit 0) - @return 1 prediction was possible , 0 no prediction could be made -*/ -int libdax_audioxtr_get_size(struct libdax_audioxtr *o, off_t *size, int flag); - - -/** Obtain next buffer full of extracted data in desired format (only raw audio - for now). - @param xtr Opaque handle to extractor - @param buffer Gets filled with extracted data - @param buffer_size Maximum number of bytes to be filled into buffer - @param flag Bitfield for control purposes - bit0= do not stop at predicted end of data - @return >0 number of valid buffer bytes, - 0 End of file - -1 operating system reports error - -2 usage error by application -*/ -int libdax_audioxtr_read(struct libdax_audioxtr *xtr, - char buffer[], int buffer_size, int flag); - - -/** Try to obtain a file descriptor which will deliver extracted data - to normal calls of read(2). This may fail because the format is - unsuitable for that, but ".wav" is ok. If this call succeeds the xtr - object will have forgotten its file descriptor and libdax_audioxtr_read() - will return a usage error. One may use *fd after libdax_audioxtr_destroy() - and will have to close it via close(2) when done with it. - @param xtr Opaque handle to extractor - @param fd Eventually returns the file descriptor number - @param flag Bitfield for control purposes - bit0= do not dup(2) and close(2) but hand out original fd - @return 1 success, 0 cannot hand out fd , -1 severe error -*/ -int libdax_audioxtr_detach_fd(struct libdax_audioxtr *o, int *fd, int flag); - - -/** Clean up after extraction and destroy extractor object. - @param xtr Opaque handle to extractor, *xtr is allowed to be NULL, - *xtr is set to NULL by this function - @param flag Bitfield for control purposes (unused yet, submit 0) - @return 1 = destroyed object, 0 = was already destroyed -*/ -int libdax_audioxtr_destroy(struct libdax_audioxtr **xtr, int flag); - - - -#ifdef LIDBAX_AUDIOXTR________________ - - --- place documentation text here --- - - -#endif /* LIDBAX_AUDIOXTR_________________ */ - - - -/* - *Never* set this macro outside libdax_audioxtr.c ! - The entrails of this facility are not to be seen by - the other library components or the applications. -*/ -#ifdef LIBDAX_AUDIOXTR_H_INTERNAL - - /* Internal Structures */ - -/** Extractor object encapsulating intermediate states of extraction */ -struct libdax_audioxtr { - - /* Source of the encoded audio data */ - char path[LIBDAX_AUDIOXTR_STRLEN]; - - /* File descriptor to path. Anything else than 0 must be lseek-able */ - int fd; - - /* Format identifier. E.g. ".wav" */ - char fmt[80]; - - /* Format parameter info text */ - char fmt_info[LIBDAX_AUDIOXTR_STRLEN]; - - /* 1= mono, 2= stereo, etc. */ - int num_channels; - - /* 8000, 44100, etc. */ - int sample_rate; - - /* 8 bits = 8, 16 bits = 16, etc. */ - int bits_per_sample; - - /* Byte order of samples: 0=Intel 1=Motorola */ - int msb_first; - - /* Number of bytes to extract (0= unknown/unlimited) */ - off_t data_size; - - /* Number of extracted data bytes */ - off_t extract_count; - - - /* Format dependent parameters */ - - /* MS WAVE Format */ - /* info used: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ */ - - /* == NumSamples * NumChannels * BitsPerSample/8 - This is the number of bytes in the data. */ - unsigned wav_subchunk2_size; - - - /* Sun Audio, .au */ - /* info used: http://www.opengroup.org/public/pubs/external/auformat.html */ - - /* Number of bytes in non-payload header part */ - unsigned au_data_location; - - /* Number of payload bytes or 0xffffffff */ - unsigned au_data_size; - -}; - - - /* Internal Functions */ - -/** Open the audio source pointed to by .path and evaluate suitability. - @return -1 failure to open, 0 unsuitable format, 1 success -*/ -static int libdax_audioxtr_open(struct libdax_audioxtr *o, int flag); - - -/** Identify format and evaluate suitability. - @return 0 unsuitable format, 1 format is suitable -*/ -static int libdax_audioxtr_identify(struct libdax_audioxtr *o, int flag); - -/** Specialized identifier for .wav */ -static int libdax_audioxtr_identify_wav(struct libdax_audioxtr *o, int flag); -/** Specialized identifier for .au */ -static int libdax_audioxtr_identify_au(struct libdax_audioxtr *o, int flag); - - -/** Convert a byte string into a number (currently only little endian) - @param flag Bitfield for control purposes - bit0=msb_first - @return The resulting number -*/ -static unsigned libdax_audioxtr_to_int(struct libdax_audioxtr *o, - unsigned char *bytes, int len, int flag); - - -/** Prepare for reading of first buffer. - @return 0 error, 1 success -*/ -static int libdax_audioxtr_init_reading(struct libdax_audioxtr *o, int flag); - - - -#endif /* LIBDAX_AUDIOXTR_H_INTERNAL */ - - -#endif /* ! LIBDAX_AUDIOXTR_H_INCLUDED */ - diff --git a/libburn/libdax_msgs.c b/libburn/libdax_msgs.c deleted file mode 100644 index 84ca9a4..0000000 --- a/libburn/libdax_msgs.c +++ /dev/null @@ -1,439 +0,0 @@ - -/* libdax_msgs - Message handling facility of libdax. - Copyright (C) 2006 - 2008 Thomas Schmitt <scdbackup@gmx.net>, - provided under GPL version 2 -*/ - -#include <stdio.h> -#include <sys/types.h> -#include <unistd.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> -#include <sys/time.h> - -/* Only this single source module is entitled to do this */ -#define LIBDAX_MSGS_H_INTERNAL 1 - -/* All participants in the messaging system must do this */ -#include "libdax_msgs.h" - - -/* ----------------------------- libdax_msgs_item ------------------------- */ - - -static int libdax_msgs_item_new(struct libdax_msgs_item **item, - struct libdax_msgs_item *link, int flag) -{ - int ret; - struct libdax_msgs_item *o; - struct timeval tv; - struct timezone tz; - - (*item)= o= - (struct libdax_msgs_item *) malloc(sizeof(struct libdax_msgs_item)); - if(o==NULL) - return(-1); - o->timestamp= 0.0; - ret= gettimeofday(&tv,&tz); - if(ret==0) - o->timestamp= tv.tv_sec+0.000001*tv.tv_usec; - o->process_id= getpid(); - o->origin= -1; - o->severity= LIBDAX_MSGS_SEV_ALL; - o->priority= LIBDAX_MSGS_PRIO_ZERO; - o->error_code= 0; - o->msg_text= NULL; - o->os_errno= 0; - o->prev= link; - o->next= NULL; - if(link!=NULL) { - if(link->next!=NULL) { - link->next->prev= o; - o->next= link->next; - } - link->next= o; - } - return(1); -} - - -/** Detaches item from its queue and eventually readjusts start, end pointers - of the queue */ -int libdax_msgs_item_unlink(struct libdax_msgs_item *o, - struct libdax_msgs_item **chain_start, - struct libdax_msgs_item **chain_end, int flag) -{ - if(o->prev!=NULL) - o->prev->next= o->next; - if(o->next!=NULL) - o->next->prev= o->prev; - if(chain_start!=NULL) - if(*chain_start == o) - *chain_start= o->next; - if(chain_end!=NULL) - if(*chain_end == o) - *chain_end= o->prev; - o->next= o->prev= NULL; - return(1); -} - - -int libdax_msgs_item_destroy(struct libdax_msgs_item **item, - int flag) -{ - struct libdax_msgs_item *o; - - o= *item; - if(o==NULL) - return(0); - libdax_msgs_item_unlink(o,NULL,NULL,0); - if(o->msg_text!=NULL) - free((char *) o->msg_text); - free((char *) o); - *item= NULL; - return(1); -} - - -int libdax_msgs_item_get_msg(struct libdax_msgs_item *item, - int *error_code, char **msg_text, int *os_errno, - int flag) -{ - *error_code= item->error_code; - *msg_text= item->msg_text; - *os_errno= item->os_errno; - return(1); -} - - -int libdax_msgs_item_get_origin(struct libdax_msgs_item *item, - double *timestamp, pid_t *process_id, int *origin, - int flag) -{ - *timestamp= item->timestamp; - *process_id= item->process_id; - *origin= item->origin; - return(1); -} - - -int libdax_msgs_item_get_rank(struct libdax_msgs_item *item, - int *severity, int *priority, int flag) -{ - *severity= item->severity; - *priority= item->priority; - return(1); -} - - -/* ------------------------------- libdax_msgs ---------------------------- */ - - -int libdax_msgs_new(struct libdax_msgs **m, int flag) -{ - struct libdax_msgs *o; - - (*m)= o= (struct libdax_msgs *) malloc(sizeof(struct libdax_msgs)); - if(o==NULL) - return(-1); - o->refcount= 1; - o->oldest= NULL; - o->youngest= NULL; - o->count= 0; - o->queue_severity= LIBDAX_MSGS_SEV_ALL; - o->print_severity= LIBDAX_MSGS_SEV_NEVER; - strcpy(o->print_id,"libdax: "); - -#ifndef LIBDAX_MSGS_SINGLE_THREADED - pthread_mutex_init(&(o->lock_mutex),NULL); -#endif - - return(1); -} - - -static int libdax_msgs_lock(struct libdax_msgs *m, int flag) -{ - -#ifndef LIBDAX_MSGS_SINGLE_THREADED - int ret; - - ret= pthread_mutex_lock(&(m->lock_mutex)); - if(ret!=0) - return(0); -#endif - - return(1); -} - - -static int libdax_msgs_unlock(struct libdax_msgs *m, int flag) -{ - -#ifndef LIBDAX_MSGS_SINGLE_THREADED - int ret; - - ret= pthread_mutex_unlock(&(m->lock_mutex)); - if(ret!=0) - return(0); -#endif - - return(1); -} - - -int libdax_msgs_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) -{ - if(strncmp(severity_name,"NEVER",5)==0) - *severity= LIBDAX_MSGS_SEV_NEVER; - else if(strncmp(severity_name,"ABORT",5)==0) - *severity= LIBDAX_MSGS_SEV_ABORT; - else if(strncmp(severity_name,"FATAL",5)==0) - *severity= LIBDAX_MSGS_SEV_FATAL; - else if(strncmp(severity_name,"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) - *severity= LIBDAX_MSGS_SEV_WARNING; - else if(strncmp(severity_name,"HINT",4)==0) - *severity= LIBDAX_MSGS_SEV_HINT; - else if(strncmp(severity_name,"NOTE",4)==0) - *severity= LIBDAX_MSGS_SEV_NOTE; - else if(strncmp(severity_name,"UPDATE",6)==0) - *severity= LIBDAX_MSGS_SEV_UPDATE; - else if(strncmp(severity_name,"DEBUG",5)==0) - *severity= LIBDAX_MSGS_SEV_DEBUG; - else if(strncmp(severity_name,"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; - return(0); - } - return(1); -} - - -int libdax_msgs__sev_to_text(int severity, char **severity_name, - int flag) -{ - if(flag&1) { - *severity_name= "NEVER\nABORT\nFATAL\nFAILURE\nMISHAP\nSORRY\nWARNING\nHINT\nNOTE\nUPDATE\nDEBUG\nERRFILE\nALL"; - return(1); - } - *severity_name= ""; - if(severity>=LIBDAX_MSGS_SEV_NEVER) - *severity_name= "NEVER"; - else if(severity>=LIBDAX_MSGS_SEV_ABORT) - *severity_name= "ABORT"; - else if(severity>=LIBDAX_MSGS_SEV_FATAL) - *severity_name= "FATAL"; - else if(severity>=LIBDAX_MSGS_SEV_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) - *severity_name= "WARNING"; - else if(severity>=LIBDAX_MSGS_SEV_HINT) - *severity_name= "HINT"; - else if(severity>=LIBDAX_MSGS_SEV_NOTE) - *severity_name= "NOTE"; - else if(severity>=LIBDAX_MSGS_SEV_UPDATE) - *severity_name= "UPDATE"; - else if(severity>=LIBDAX_MSGS_SEV_DEBUG) - *severity_name= "DEBUG"; - else if(severity>=LIBDAX_MSGS_SEV_ERRFILE) - *severity_name= "ERRFILE"; - else if(severity>=LIBDAX_MSGS_SEV_ALL) - *severity_name= "ALL"; - else { - *severity_name= ""; - return(0); - } - return(1); -} - - -int libdax_msgs_submit(struct libdax_msgs *m, int origin, int error_code, - int severity, int priority, char *msg_text, - int os_errno, int flag) -{ - int ret; - char *textpt,*sev_name,sev_text[81]; - struct libdax_msgs_item *item= NULL; - - if(severity >= m->print_severity) { - if(msg_text==NULL) - textpt= ""; - else - textpt= msg_text; - sev_text[0]= 0; - ret= libdax_msgs__sev_to_text(severity,&sev_name,0); - if(ret>0) - sprintf(sev_text,"%s : ",sev_name); - - fprintf(stderr,"%s%s%s\n",m->print_id,sev_text,textpt); - if(os_errno!=0) { - ret= libdax_msgs_lock(m,0); - if(ret<=0) - return(-1); - fprintf(stderr,"%s( Most recent system error: %d '%s' )\n", - m->print_id,os_errno,strerror(os_errno)); - libdax_msgs_unlock(m,0); - } - - } - if(severity < m->queue_severity) - return(0); - - ret= libdax_msgs_lock(m,0); - if(ret<=0) - return(-1); - ret= libdax_msgs_item_new(&item,m->youngest,0); - if(ret<=0) - goto failed; - item->origin= origin; - item->error_code= error_code; - item->severity= severity; - item->priority= priority; - if(msg_text!=NULL) { - item->msg_text= malloc(strlen(msg_text)+1); - if(item->msg_text==NULL) - goto failed; - strcpy(item->msg_text,msg_text); - } - item->os_errno= os_errno; - if(m->oldest==NULL) - m->oldest= item; - m->youngest= item; - m->count++; - libdax_msgs_unlock(m,0); - -/* -fprintf(stderr,"libdax_experimental: message submitted to queue (now %d)\n", - m->count); -*/ - - return(1); -failed:; - libdax_msgs_item_destroy(&item,0); - libdax_msgs_unlock(m,0); - return(-1); -} - - -int libdax_msgs_obtain(struct libdax_msgs *m, struct libdax_msgs_item **item, - int severity, int priority, int flag) -{ - int ret; - struct libdax_msgs_item *im, *next_im= NULL; - - *item= NULL; - ret= libdax_msgs_lock(m,0); - if(ret<=0) - return(-1); - for(im= m->oldest; im!=NULL; im= next_im) { - for(; im!=NULL; im= next_im) { - next_im= im->next; - if(im->severity>=severity) - break; - libdax_msgs_item_unlink(im,&(m->oldest),&(m->youngest),0); - libdax_msgs_item_destroy(&im,0); /* severity too low: delete */ - } - if(im==NULL) - break; - if(im->priority>=priority) - break; - } - if(im==NULL) - {ret= 0; goto ex;} - libdax_msgs_item_unlink(im,&(m->oldest),&(m->youngest),0); - *item= im; - ret= 1; -ex:; - libdax_msgs_unlock(m,0); - return(ret); -} - - -int libdax_msgs_destroy_item(struct libdax_msgs *m, - struct libdax_msgs_item **item, int flag) -{ - int ret; - - ret= libdax_msgs_lock(m,0); - if(ret<=0) - return(-1); - ret= libdax_msgs_item_destroy(item,0); - libdax_msgs_unlock(m,0); - return(ret); -} - diff --git a/libburn/libdax_msgs.h b/libburn/libdax_msgs.h deleted file mode 100644 index 722984c..0000000 --- a/libburn/libdax_msgs.h +++ /dev/null @@ -1,682 +0,0 @@ - -/* libdax_msgs - Message handling facility of libdax. - Copyright (C) 2006-2008 Thomas Schmitt <scdbackup@gmx.net>, - provided under GPL version 2 -*/ - - -/* - *Never* set this macro outside libdax_msgs.c ! - The entrails of the message handling facility are not to be seen by - the other library components or the applications. -*/ -#ifdef LIBDAX_MSGS_H_INTERNAL - - -#ifndef LIBDAX_MSGS_SINGLE_THREADED -#include <pthread.h> -#endif - - -struct libdax_msgs_item { - - double timestamp; - pid_t process_id; - int origin; - - int severity; - int priority; - - /* Apply for your developer's error code range at - libburn-hackers@pykix.org - Report introduced codes in the list below. */ - int error_code; - - char *msg_text; - int os_errno; - - struct libdax_msgs_item *prev,*next; - -}; - - -struct libdax_msgs { - - int refcount; - - struct libdax_msgs_item *oldest; - struct libdax_msgs_item *youngest; - int count; - - int queue_severity; - int print_severity; - char print_id[81]; - -#ifndef LIBDAX_MSGS_SINGLE_THREADED - pthread_mutex_t lock_mutex; -#endif - - -}; - -#endif /* LIBDAX_MSGS_H_INTERNAL */ - - -#ifndef LIBDAX_MSGS_H_INCLUDED -#define LIBDAX_MSGS_H_INCLUDED 1 - - -#ifndef LIBDAX_MSGS_H_INTERNAL - - - /* 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 */ -struct libdax_msgs; - -/** A pointer to this is a opaque handle to a single message item */ -struct libdax_msgs_item; - -#endif /* ! LIBDAX_MSGS_H_INTERNAL */ - - - /* Public Macros */ - - -/* Registered Severities */ - -/* It is well advisable to let applications select severities via strings and - forwarded functions libdax_msgs__text_to_sev(), libdax_msgs__sev_to_text(). - These macros are for use by the owner of libdax_msgs. -*/ - -/** 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 - -/** Update of a progress report about long running actions -*/ -#define LIBDAX_MSGS_SEV_UPDATE 0x20000000 - -/** Not so usual events which were gracefully handled -*/ -#define LIBDAX_MSGS_SEV_NOTE 0x30000000 - -/** Possibilities to achieve a better result -*/ -#define LIBDAX_MSGS_SEV_HINT 0x40000000 - -/** Warnings about problems which could not be handled optimally -*/ -#define LIBDAX_MSGS_SEV_WARNING 0x50000000 - - -/** Non-fatal error messages indicating that parts of 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. -*/ -#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. -*/ -#define LIBDAX_MSGS_SEV_FATAL 0x70000000 - - -/** A message from an abort handler which will finally finish libburn -*/ -#define LIBDAX_MSGS_SEV_ABORT 0x71000000 - -/** A severity to exclude resp. discard any possible message. - Do not use this severity for submitting. -*/ -#define LIBDAX_MSGS_SEV_NEVER 0x7fffffff - - -/* Registered Priorities */ - -/* Priorities are to be selected by the programmers and not by the user. */ - -#define LIBDAX_MSGS_PRIO_ZERO 0x00000000 -#define LIBDAX_MSGS_PRIO_LOW 0x10000000 -#define LIBDAX_MSGS_PRIO_MEDIUM 0x20000000 -#define LIBDAX_MSGS_PRIO_HIGH 0x30000000 -#define LIBDAX_MSGS_PRIO_TOP 0x7ffffffe - -/* Do not use this priority for submitting */ -#define LIBDAX_MSGS_PRIO_NEVER 0x7fffffff - - -/* 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) */ - - -/** Create new empty message handling facility with queue and issue a first - official reference to it. - @param flag Bitfield for control purposes (unused yet, submit 0) - @return >0 success, <=0 failure -*/ -int libdax_msgs_new(struct libdax_msgs **m, int flag); - - -/** Destroy a message handling facility and all its eventual messages. - The submitted pointer gets set to NULL. - 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 -*/ -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 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" - versus "cannot open SCSI drive" would be equivalent.) - @param severity The LIBDAX_MSGS_SEV_* of the event. - @param priority The LIBDAX_MSGS_PRIO_* number of the event. - @param msg_text Printable and human readable message text. - @param os_errno Eventual error code from operating system (0 if none) - @param flag Bitfield for control purposes (unused yet, submit 0) - @return 1 on success, 0 on rejection, <0 for severe errors -*/ -int libdax_msgs_submit(struct libdax_msgs *m, int origin, int error_code, - int severity, int priority, char *msg_text, - int os_errno, int flag); - - - - /* Calls from applications (to be forwarded by direct owner) */ - - -/** Convert a registered severity number into a severity name - @param flag Bitfield for control purposes: - bit0= list all severity names in a newline separated string - @return >0 success, <=0 failure -*/ -int libdax_msgs__sev_to_text(int severity, char **severity_name, - int flag); - - -/** Convert a severity name into a severity number, - @param flag Bitfield for control purposes (unused yet, submit 0) - @return >0 success, <=0 failure -*/ -int libdax_msgs__text_to_sev(char *severity_name, int *severity, - int flag); - - -/** Set minimum severity for messages to be queued (default - LIBDAX_MSGS_SEV_ALL) and for messages to be printed directly to stderr - (default LIBDAX_MSGS_SEV_NEVER). - @param print_id A text of at most 80 characters to be printed before - any eventually printed message (default is "libdax: "). - @param flag Bitfield for control purposes (unused yet, submit 0) - @return always 1 for now -*/ -int libdax_msgs_set_severities(struct libdax_msgs *m, int queue_severity, - int print_severity, char *print_id, int flag); - - -/** Obtain a message item that has at least the given severity and priority. - Usually all older messages of lower severity are discarded then. If no - item of sufficient severity was found, all others are discarded from the - queue. - @param flag Bitfield for control purposes (unused yet, submit 0) - @return 1 if a matching item was found, 0 if not, <0 for severe errors -*/ -int libdax_msgs_obtain(struct libdax_msgs *m, struct libdax_msgs_item **item, - int severity, int priority, int flag); - - -/** Destroy a message item obtained by libdax_msgs_obtain(). The submitted - pointer gets set to NULL. - Caution: Copy eventually obtained msg_text before destroying the item, - if you want to use it further. - @param flag Bitfield for control purposes (unused yet, submit 0) - @return 1 for success, 0 for pointer to NULL, <0 for severe errors -*/ -int libdax_msgs_destroy_item(struct libdax_msgs *m, - struct libdax_msgs_item **item, int flag); - - -/** Obtain from a message item the three application oriented components as - submitted with the originating call of libdax_msgs_submit(). - Caution: msg_text becomes a pointer into item, not a copy. - @param flag Bitfield for control purposes (unused yet, submit 0) - @return 1 on success, 0 on invalid item, <0 for servere errors -*/ -int libdax_msgs_item_get_msg(struct libdax_msgs_item *item, - int *error_code, char **msg_text, int *os_errno, - int flag); - - -/** Obtain from a message item the submitter identification submitted - with the originating call of libdax_msgs_submit(). - @param flag Bitfield for control purposes (unused yet, submit 0) - @return 1 on success, 0 on invalid item, <0 for servere errors -*/ -int libdax_msgs_item_get_origin(struct libdax_msgs_item *item, - double *timestamp, pid_t *process_id, int *origin, - int flag); - - -/** Obtain from a message item severity and priority as submitted - with the originating call of libdax_msgs_submit(). - @param flag Bitfield for control purposes (unused yet, submit 0) - @return 1 on success, 0 on invalid item, <0 for servere errors -*/ -int libdax_msgs_item_get_rank(struct libdax_msgs_item *item, - int *severity, int *priority, int flag); - - -#ifdef LIDBAX_MSGS_________________ - - - /* Registered Error Codes */ - - -Format: error_code (LIBDAX_MSGS_SEV_*,LIBDAX_MSGS_PRIO_*) = explanation -If no severity or priority are fixely associated, use "(,)". - ------------------------------------------------------------------------------- -Range "libdax_msgs" : 0x00000000 to 0x0000ffff - - 0x00000000 (ALL,ZERO) = Initial setting in new libdax_msgs_item - 0x00000001 (DEBUG,ZERO) = Test error message - 0x00000002 (DEBUG,ZERO) = Debugging message - 0x00000003 (FATAL,HIGH) = Out of virtual memory - - ------------------------------------------------------------------------------- -Range "elmom" : 0x00010000 to 0x0001ffff - - - ------------------------------------------------------------------------------- -Range "scdbackup" : 0x00020000 to 0x0002ffff - - Acessing and defending drives: - - 0x00020001 (SORRY,LOW) = Cannot open busy device - 0x00020002 (SORRY,HIGH) = Encountered error when closing drive - 0x00020003 (SORRY,HIGH) = Could not grab drive - 0x00020004 (NOTE,HIGH) = Opened O_EXCL scsi sibling - 0x00020005 (SORRY,HIGH) = Failed to open device - 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 - - General library operations: - - 0x00020101 (WARNING,HIGH) = Cannot find given worker item - 0x00020102 (SORRY,HIGH) = A drive operation is still going on - 0x00020103 (WARNING,HIGH) = After scan a drive operation is still going on - 0x00020104 (SORRY,HIGH) = NULL pointer caught - 0x00020105 (SORRY,HIGH) = Drive is already released - 0x00020106 (SORRY,HIGH) = Drive is busy on attempt to close - 0x00020107 (WARNING,HIGH) = A drive is still busy on shutdown of library - 0x00020108 (SORRY,HIGH) = Drive is not grabbed on disc status inquiry - 0x00020108 (FATAL,HIGH) = Could not allocate new drive object - 0x00020109 (FATAL,HIGH) = Library not running - 0x0002010a (FATAL,HIGH) = Unsuitable track mode - 0x0002010b (FATAL,HIGH) = Burn run failed - 0x0002010c (FATAL,HIGH) = Failed to transfer command to drive - 0x0002010d (DEBUG,HIGH) = Could not inquire TOC - 0x0002010e (FATAL,HIGH) = Attempt to read ATIP from ungrabbed drive - 0x0002010f (DEBUG,HIGH) = SCSI error condition on command - 0x00020110 (FATAL,HIGH) = Persistent drive address too long - 0x00020111 (FATAL,HIGH) = Could not allocate new auxiliary object - 0x00020112 (SORRY,HIGH) = Bad combination of write_type and block_type - 0x00020113 (FATAL,HIGH) = Drive capabilities not inquired yet - 0x00020114 (SORRY,HIGH) = Attempt to set ISRC with bad data - 0x00020115 (SORRY,HIGH) = Attempt to set track mode to unusable value - 0x00020116 (FATAL,HIGH) = Track mode has unusable value - 0x00020117 (FATAL,HIGH) = toc_entry of drive is already in use - 0x00020118 (DEBUG,HIGH) = Closing track - 0x00020119 (DEBUG,HIGH) = Closing session - 0x0002011a (NOTE,HIGH) = Padding up track to minimum size - 0x0002011b (FATAL,HIGH) = Attempt to read track info from ungrabbed drive - 0x0002011c (FATAL,HIGH) = Attempt to read track info from busy drive - 0x0002011d (FATAL,HIGH) = SCSI error on write - 0x0002011e (SORRY,HIGH) = Unsuitable media detected - 0x0002011f (SORRY,HIGH) = Burning is restricted to a single track - 0x00020120 (NOTE,HIGH) = FORMAT UNIT ignored - 0x00020121 (FATAL,HIGH) = Write preparation setup failed - 0x00020122 (FATAL,HIGH) = SCSI error on format_unit - 0x00020123 (SORRY,HIGH) = DVD Media are unsuitable for desired track type - 0x00020124 (SORRY,HIGH) = SCSI error on set_streaming - 0x00020125 (SORRY,HIGH) = Write start address not supported - 0x00020126 (SORRY,HIGH) = Write start address not properly aligned - 0x00020127 (NOTE,HIGH) = Write start address is ... - 0x00020128 (FATAL,HIGH) = Unsupported inquiry_type with mmc_get_performance - 0x00020129 (SORRY,HIGH) = Will not format media type - 0x0002012a (FATAL,HIGH) = Cannot inquire write mode capabilities - 0x0002012b (FATAL,HIGH) = Drive offers no suitable write mode with this job - 0x0002012c (SORRY,HIGH) = Too many logical tracks recorded - 0x0002012d (FATAL,HIGH) = Exceeding range of permissible write addresses - 0x0002012e (NOTE,HIGH) = Activated track default size - 0x0002012f (SORRY,HIGH) = SAO is restricted to single fixed size session - 0x00020130 (SORRY,HIGH) = Drive and media state unsuitable for blanking - 0x00020131 (SORRY,HIGH) = No suitable formatting type offered by drive - 0x00020132 (SORRY,HIGH) = Selected format is not suitable for libburn - 0x00020133 (SORRY,HIGH) = Cannot mix data and audio in SAO mode - 0x00020134 (NOTE,HIGH) = Defaulted TAO to DAO - 0x00020135 (SORRY,HIGH) = Cannot perform TAO, job unsuitable for DAO - 0x00020136 (SORRY,HIGH) = DAO burning restricted to single fixed size track - 0x00020137 (HINT,HIGH) = TAO would be possible - 0x00020138 (FATAL,HIGH) = Cannot reserve track - 0x00020139 (SORRY,HIGH) = Write job parameters are unsuitable - 0x0002013a (FATAL,HIGH) = No suitable media detected - 0x0002013b (DEBUG,HIGH) = SCSI command indicates host or driver error - 0x0002013c (SORRY,HIGH) = Malformed capabilities page 2Ah received - 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 - - 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 - - ------------------------------------------------------------------------------- - -#endif /* LIDBAX_MSGS_________________ */ - - - -#ifdef LIBDAX_MSGS_H_INTERNAL - - /* Internal Functions */ - - -/** Lock before doing side effect operations on m */ -static int libdax_msgs_lock(struct libdax_msgs *m, int flag); - -/** Unlock after effect operations on m are done */ -static int libdax_msgs_unlock(struct libdax_msgs *m, int flag); - - -/** Create new empty message item. - @param link Previous item in queue - @param flag Bitfield for control purposes (unused yet, submit 0) - @return >0 success, <=0 failure -*/ -static int libdax_msgs_item_new(struct libdax_msgs_item **item, - struct libdax_msgs_item *link, int flag); - -/** Destroy a message item obtained by libdax_msgs_obtain(). The submitted - pointer gets set to NULL. - @param flag Bitfield for control purposes (unused yet, submit 0) - @return 1 for success, 0 for pointer to NULL -*/ -static int libdax_msgs_item_destroy(struct libdax_msgs_item **item, int flag); - - -#endif /* LIBDAX_MSGS_H_INTERNAL */ - - -#endif /* ! LIBDAX_MSGS_H_INCLUDED */ diff --git a/libburn/libdax_msgs_to_xyz_msgs.sh b/libburn/libdax_msgs_to_xyz_msgs.sh deleted file mode 100755 index 46f68b1..0000000 --- a/libburn/libdax_msgs_to_xyz_msgs.sh +++ /dev/null @@ -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 - diff --git a/libburn/mmc.c b/libburn/mmc.c deleted file mode 100644 index a163391..0000000 --- a/libburn/mmc.c +++ /dev/null @@ -1,3494 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -/* ts A61009 */ -/* #include <a ssert.h> */ - -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <stdlib.h> -#include <sys/time.h> -#include <pthread.h> -#include "error.h" -#include "sector.h" -#include "libburn.h" -#include "transport.h" -#include "mmc.h" -#include "spc.h" -#include "drive.h" -#include "debug.h" -#include "toc.h" -#include "structure.h" -#include "options.h" - - -/* ts A70223 : in init.c */ -extern int burn_support_untested_profiles; - - -#ifdef Libburn_log_in_and_out_streaM -/* <<< ts A61031 */ -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#endif /* Libburn_log_in_and_out_streaM */ - - -/* ts A61005 */ -#include "libdax_msgs.h" -extern struct libdax_msgs *libdax_messenger; - - -/* ts A61219 : Based on knowlege from dvd+rw-tools-7.0 and mmc5r03c.pdf */ -#define Libburn_support_dvd_plus_rW 1 - -/* ts A61229 */ -#define Libburn_support_dvd_minusrw_overW 1 - -/* ts A70112 */ -/* ts A80410 : applies to BD-RE too */ -#define Libburn_support_dvd_raM 1 - -/* ts A70129 */ -#define Libburn_support_dvd_r_seQ 1 - -/* ts A70306 */ -#define Libburn_support_dvd_plus_R 1 - -/* ts A70509 : handling 0x41 and 0x42 as read-only types */ -#define Libburn_support_bd_r_readonlY 1 - - -/* ts A80410 : <<< Dangerous experiment: Pretend that DVD-RAM is BD-RE - # define Libburn_dvd_ram_as_bd_rE yes -*/ -/* ts A80509 : <<< Experiment: pretend that DVD-COM and CD-ROM are other media - like BD-ROM (0x40), BD-R seq (0x41), BD-R random (0x42) - # define Libburn_rom_as_profilE 0x40 -*/ - - -/* ts A80425 : Prevents command FORMAT UNIT for DVD-RAM or BD-RE. - Useful only to test the selection of format descriptors without - actually formatting the media. - # define Libburn_do_not_format_dvd_ram_or_bd_rE 1 -*/ - -/* DVD/BD progress report: - ts A61219 : It seems to work with a used (i.e. thoroughly formatted) DVD+RW. - Error messages of class DEBUG appear because of inability to - read TOC or track info. Nevertheless, the written images verify. - ts A61220 : Burned to a virgin DVD+RW by help of new mmc_format_unit() - (did not test wether it would work without). Burned to a - not completely formatted DVD+RW. (Had worked before without - mmc_format_unit() but i did not exceed the formatted range - as reported by dvd+rw-mediainfo.) - ts A61221 : Speed setting now works for both of my drives. The according - functions in dvd+rw-tools are a bit intimidating to the reader. - I hope it is possible to leave much of this to the drive. - And if it fails ... well, it's only speed setting. :)) - ts A61229 : Burned to several DVD-RW formatted to mode Restricted Overwrite - by dvd+rw-format. Needs Libburn_support_dvd_minusrw_overW. - ts A61230 : Other than growisofs, libburn does not send a mode page 5 for - such DVD-RW (which the MMC-5 standard does deprecate) and it - really seems to work without such a page. - ts A70101 : Formatted DVD-RW media. Success is varying with media, but - dvd+rw-format does not do better with the same media. - ts A70112 : Support for writing to DVD-RAM. - ts A70130 : Burned a first non-multi sequential DVD-RW. Feature 0021h - Incremental Recording vanishes after that and media thus gets - not recognized as suitable any more. - After a run with -multi another disc still offers 0021h . - dvd+rw-mediainfo shows two tracks. The second, an afio archive - is readable by afio. Third and forth veryfy too. Suddenly - dvd+rw-mediainfo sees lba 0 with track 2. But #2 still verifies - if one knows its address. - ts A70203 : DVD-RW need to get blanked fully. Then feature 0021h persists. - Meanwhile Incremental streaming is supported like CD TAO: - with unpredicted size, multi-track, multi-session. - ts A70205 : Beginning to implement DVD-R[W] DAO : single track and session, - size prediction mandatory. - ts A70208 : Finally made tests with DVD-R. Worked exactly as new DVD-RW. - ts A70306 : Implemented DVD+R (always -multi for now) - ts A70330 : Allowed finalizing of DVD+R. - ts A80228 : Made DVD+R/DL support official after nightmorph reported success - in http://libburnia-project.org/ticket/13 - ts A80416 : drive->do_stream_recording brings DVD-RAM to full nominal - writing speed at cost of no defect management. - ts A80416 : Giulio Orsero reports success with BD-RE writing. With - drive->do_stream_recording it does full nominal speed. - ts A80506 : Giulio Orsero reports success with BD-RE formatting. - BD-RE is now an officially supported profile. -*/ - -/* ts A70519 : With MMC commands of data direction FROM_DRIVE: - Made struct command.dxfer_len equal to Allocation Length - of MMC commands. Made sure that not more bytes are allowed - for transfer than there are available. -*/ - - -/* ts A70711 Trying to keep writing from clogging the SCSI driver due to - full buffer at burner drive: 0=waiting disabled, 1=enabled - These are only defaults which can be overwritten by - burn_drive_set_buffer_waiting() -*/ -#define Libburn_wait_for_buffer_freE 0 -#define Libburn_wait_for_buffer_min_useC 10000 -#define Libburn_wait_for_buffer_max_useC 100000 -#define Libburn_wait_for_buffer_tio_seC 120 -#define Libburn_wait_for_buffer_min_perC 65 -#define Libburn_wait_for_buffer_max_perC 95 - - -static unsigned char MMC_GET_MSINFO[] = - { 0x43, 0, 1, 0, 0, 0, 0, 16, 0, 0 }; -static unsigned char MMC_GET_TOC[] = { 0x43, 2, 2, 0, 0, 0, 0, 16, 0, 0 }; -static unsigned char MMC_GET_TOC_FMT0[] = { 0x43, 0, 0, 0, 0, 0, 0, 16, 0, 0 }; -static unsigned char MMC_GET_ATIP[] = { 0x43, 2, 4, 0, 0, 0, 0, 16, 0, 0 }; -static unsigned char MMC_GET_DISC_INFO[] = - { 0x51, 0, 0, 0, 0, 0, 0, 16, 0, 0 }; -static unsigned char MMC_READ_CD[] = { 0xBE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static unsigned char MMC_BLANK[] = { 0xA1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static unsigned char MMC_SEND_OPC[] = { 0x54, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static unsigned char MMC_SET_SPEED[] = - { 0xBB, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static unsigned char MMC_WRITE_12[] = - { 0xAA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static unsigned char MMC_WRITE_10[] = { 0x2A, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -/* ts A61201 : inserted 0, before 16, */ -static unsigned char MMC_GET_CONFIGURATION[] = - { 0x46, 0, 0, 0, 0, 0, 0, 16, 0, 0 }; - -static unsigned char MMC_SYNC_CACHE[] = { 0x35, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static unsigned char MMC_GET_EVENT[] = { 0x4A, 1, 0, 0, 16, 0, 0, 0, 8, 0 }; -static unsigned char MMC_CLOSE[] = { 0x5B, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static unsigned char MMC_TRACK_INFO[] = { 0x52, 0, 0, 0, 0, 0, 0, 16, 0, 0 }; - -static unsigned char MMC_SEND_CUE_SHEET[] = - { 0x5D, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -/* ts A61023 : get size and free space of drive buffer */ -static unsigned char MMC_READ_BUFFER_CAPACITY[] = - { 0x5C, 0, 0, 0, 0, 0, 0, 16, 0, 0 }; - -/* ts A61219 : format DVD+RW (and various others) */ -static unsigned char MMC_FORMAT_UNIT[] = { 0x04, 0x11, 0, 0, 0, 0 }; - -/* ts A61221 : - To set speed for DVD media (0xBB is for CD but works on my LG GSA drive) */ -static unsigned char MMC_SET_STREAMING[] = - { 0xB6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -/* ts A61225 : - To obtain write speed descriptors (command can do other things too) */ -static unsigned char MMC_GET_PERFORMANCE[] = - { 0xAC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -/* ts A70108 : To obtain info about drive and media formatting opportunities */ -static unsigned char MMC_READ_FORMAT_CAPACITIES[] = - { 0x23, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -/* ts A70205 : To describe the layout of a DVD-R[W] DAO session */ -static unsigned char MMC_RESERVE_TRACK[] = - { 0x53, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -/* ts A70812 : Read data sectors (for types with 2048 bytes/sector only) */ -static unsigned char MMC_READ_10[] = - { 0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - - -static int mmc_function_spy_do_tell = 0; - -int mmc_function_spy(struct burn_drive *d, char * text) -{ - if (mmc_function_spy_do_tell) - fprintf(stderr,"libburn: experimental: mmc_function_spy: %s\n", - text); - if (d == NULL) - return 1; - if (d->drive_role != 1) { - char msg[4096]; - - sprintf(msg, "Emulated drive caught in SCSI adapter \"%s\"", - text); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x0002014c, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - d->cancel = 1; - return 0; - } - return 1; -} - -int mmc_function_spy_ctrl(int do_tell) -{ - mmc_function_spy_do_tell= !!do_tell; - return 1; -} - - -/* ts A70201 */ -int mmc_four_char_to_int(unsigned char *data) -{ - return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; -} - - -/* ts A70201 */ -int mmc_int_to_four_char(unsigned char *data, int num) -{ - data[0] = (num >> 24) & 0xff; - data[1] = (num >> 16) & 0xff; - data[2] = (num >> 8) & 0xff; - data[3] = num & 0xff; - return 1; -} - - -void mmc_send_cue_sheet(struct burn_drive *d, struct cue_sheet *s) -{ - struct buffer buf; - struct command c; - - - if (mmc_function_spy(d, "mmc_send_cue_sheet") <= 0) - return; - - scsi_init_command(&c, MMC_SEND_CUE_SHEET, sizeof(MMC_SEND_CUE_SHEET)); -/* - c.oplen = sizeof(MMC_SEND_CUE_SHEET); - memcpy(c.opcode, MMC_SEND_CUE_SHEET, sizeof(MMC_SEND_CUE_SHEET)); -*/ - c.retry = 1; - c.page = &buf; - c.page->bytes = s->count * 8; - c.page->sectors = 0; - c.opcode[6] = (c.page->bytes >> 16) & 0xFF; - c.opcode[7] = (c.page->bytes >> 8) & 0xFF; - c.opcode[8] = c.page->bytes & 0xFF; - c.dir = TO_DRIVE; - memcpy(c.page->data, s->data, c.page->bytes); - d->issue_command(d, &c); -} - - -/* ts A70205 : Announce size of a DVD-R[W] DAO session. - @param size The size in bytes to be announced to the drive. - It will get rounded up to align to 32 KiB. -*/ -int mmc_reserve_track(struct burn_drive *d, off_t size) -{ - struct command c; - int lba; - char msg[80]; - - if (mmc_function_spy(d, "mmc_reserve_track") <= 0) - return 0; - - scsi_init_command(&c, MMC_RESERVE_TRACK, sizeof(MMC_RESERVE_TRACK)); -/* - c.oplen = sizeof(MMC_RESERVE_TRACK); - memcpy(c.opcode, MMC_RESERVE_TRACK, sizeof(MMC_RESERVE_TRACK)); -*/ - c.retry = 1; - /* Round to 32 KiB and divide by 2048 - (by nice binary rounding trick learned from dvd+rw-tools) */ - lba = ((size + (off_t) 0x7fff) >> 11) & ~0xf; - mmc_int_to_four_char(c.opcode+5, lba); - - sprintf(msg, "reserving track of %d blocks", lba); - libdax_msgs_submit(libdax_messenger, -1, 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - msg, 0, 0); - - c.page = NULL; - c.dir = NO_TRANSFER; - d->issue_command(d, &c); - return !c.error; -} - - -/* ts A70201 : - Common track info fetcher for mmc_get_nwa() and mmc_fake_toc() -*/ -int mmc_read_track_info(struct burn_drive *d, int trackno, struct buffer *buf, - int alloc_len) -{ - struct command c; - - if (mmc_function_spy(d, "mmc_read_track_info") <= 0) - return 0; - - scsi_init_command(&c, MMC_TRACK_INFO, sizeof(MMC_TRACK_INFO)); -/* - c.oplen = sizeof(MMC_TRACK_INFO); - memcpy(c.opcode, MMC_TRACK_INFO, sizeof(MMC_TRACK_INFO)); -*/ - c.dxfer_len = alloc_len; - c.opcode[7] = (c.dxfer_len >> 8) & 0xff; - c.opcode[8] = c.dxfer_len & 0xff; - c.retry = 1; - c.opcode[1] = 1; - if(trackno<=0) { - if (d->current_profile == 0x1a || d->current_profile == 0x13 || - d->current_profile == 0x12 || d->current_profile == 0x42 || - d->current_profile == 0x43) - /* DVD+RW , DVD-RW restricted overwrite , DVD-RAM - BD-R random recording, BD-RE */ - trackno = 1; - else if (d->current_profile == 0x10 || - d->current_profile == 0x11 || - d->current_profile == 0x14 || - d->current_profile == 0x15 || - d->current_profile == 0x40 || - d->current_profile == 0x41) - /* DVD-ROM , DVD-R[W] Sequential , - BD-ROM , BD-R sequential */ - trackno = d->last_track_no; - else /* mmc5r03c.pdf: valid only for CD, DVD+R, DVD+R DL */ - trackno = 0xFF; - } - mmc_int_to_four_char(c.opcode + 2, trackno); - c.page = buf; - memset(buf->data, 0, BUFFER_SIZE); - c.dir = FROM_DRIVE; - d->issue_command(d, &c); - if (c.error) - return 0; - return 1; -} - - -/* ts A61110 : added parameters trackno, lba, nwa. Redefined return value. - @return 1=nwa is valid , 0=nwa is not valid , -1=error */ -/* ts A70201 : outsourced 52h READ TRACK INFO command */ -int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa) -{ - struct buffer buf; - int ret, num, alloc_len = 20; - unsigned char *data; - - if (mmc_function_spy(d, "mmc_get_nwa") <= 0) - return -1; - - ret = mmc_read_track_info(d, trackno, &buf, alloc_len); - if (ret <= 0) - return ret; - data = buf.data; - *lba = mmc_four_char_to_int(data + 8); - *nwa = mmc_four_char_to_int(data + 12); - num = mmc_four_char_to_int(data + 16); - if (d->current_profile == 0x1a || d->current_profile == 0x13 || - d->current_profile == 0x12 || d->current_profile == 0x43) { - /* overwriteable */ - *lba = *nwa = num = 0; - } else if (!(data[7]&1)) { - /* ts A61106 : MMC-1 Table 142 : NWA_V = NWA Valid Flag */ - libdax_msgs_submit(libdax_messenger, -1, 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - "mmc_get_nwa: Track Info Block: NWA_V == 0", 0, 0); - return 0; - } - if (num > 0) { - burn_drive_set_media_capacity_remaining(d, - ((off_t) num) * ((off_t) 2048)); - d->media_lba_limit = *nwa + num; - } else - d->media_lba_limit = 0; - -/* - fprintf(stderr, "LIBBURN_DEBUG: media_lba_limit= %d\n", - d->media_lba_limit); -*/ - - return 1; -} - -/* ts A61009 : function is obviously unused. */ -/* void mmc_close_disc(struct burn_drive *d, struct burn_write_opts *o) */ -void mmc_close_disc(struct burn_write_opts *o) -{ - struct burn_drive *d = o->drive; - - if (mmc_function_spy(d, "mmc_close_disc") <= 0) - return; - - libdax_msgs_submit(libdax_messenger, -1, 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - "HOW THAT ? mmc_close_disc() was called", 0, 0); - - /* ts A61009 : made impossible by removing redundant parameter d */ - /* a ssert(o->drive == d); */ - - o->multi = 0; - spc_select_write_params(d, o); - mmc_close(d, 1, 0); -} - -/* ts A61009 : function is obviously unused. */ -/* void mmc_close_session(struct burn_drive *d, struct burn_write_opts *o) */ -void mmc_close_session(struct burn_write_opts *o) -{ - struct burn_drive *d = o->drive; - - if (mmc_function_spy(d, "mmc_close_session") <= 0) - return; - - libdax_msgs_submit(libdax_messenger, -1, 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - "HOW THAT ? mmc_close_session() was called", 0, 0); - - /* ts A61009 : made impossible by removing redundant parameter d */ - /* a ssert(o->drive == d); */ - - o->multi = 3; - spc_select_write_params(d, o); - mmc_close(d, 1, 0); -} - -/* ts A70227 : extended meaning of session to address all possible values - of 5Bh CLOSE TRACK SESSION to address any Close Function. - @param session contains the two high bits of Close Function - @param track if not 0: sets the lowest bit of Close Function -*/ -void mmc_close(struct burn_drive *d, int session, int track) -{ - struct command c; - - if (mmc_function_spy(d, "mmc_close") <= 0) - return; - - scsi_init_command(&c, MMC_CLOSE, sizeof(MMC_CLOSE)); -/* - c.oplen = sizeof(MMC_CLOSE); - memcpy(c.opcode, MMC_CLOSE, sizeof(MMC_CLOSE)); -*/ - c.retry = 1; - - c.opcode[1] |= 1; /* ts A70918 : Immed */ - - /* (ts A61030 : shifted !!session rather than or-ing plain session ) */ - c.opcode[2] = ((session & 3) << 1) | !!track; - c.opcode[4] = track >> 8; - c.opcode[5] = track & 0xFF; - c.page = NULL; - c.dir = NO_TRANSFER; - d->issue_command(d, &c); - - /* ts A70918 : Immed : wait for drive to complete command */ - if (c.error) { - d->cancel = 1; - return; - } - if (spc_wait_unit_attention(d, 3600, "CLOSE TRACK SESSION", 0) <= 0) - d->cancel = 1; -} - -void mmc_get_event(struct burn_drive *d) -{ - struct buffer buf; - struct command c; - int alloc_len= 8; - - if (mmc_function_spy(d, "mmc_get_event") <= 0) - return; - - scsi_init_command(&c, MMC_GET_EVENT, sizeof(MMC_GET_EVENT)); -/* - c.oplen = sizeof(MMC_GET_EVENT); - memcpy(c.opcode, MMC_GET_EVENT, sizeof(MMC_GET_EVENT)); -*/ - c.dxfer_len = alloc_len; - c.opcode[7] = (c.dxfer_len >> 8) & 0xff; - c.opcode[8] = c.dxfer_len & 0xff; - c.retry = 1; - c.page = &buf; - c.page->bytes = 0; - c.page->sectors = 0; - c.dir = FROM_DRIVE; - d->issue_command(d, &c); - burn_print(12, "0x%x:0x%x:0x%x:0x%x\n", - c.page->data[0], c.page->data[1], c.page->data[2], - c.page->data[3]); - burn_print(12, "event: %d:%d:%d:%d\n", c.page->data[4], - c.page->data[5], c.page->data[6], c.page->data[7]); -} - - -/* ts A70711 - This has become a little monster because of the creative buffer reports of - my LG GSA-4082B : Belated, possibly statistically dampened. But only with - DVD media. With CD it is ok. -*/ -static int mmc_wait_for_buffer_free(struct burn_drive *d, struct buffer *buf) -{ - int usec= 0, need, reported_3s = 0, first_wait = 1; - struct timeval t0,tnow; - struct timezone dummy_tz; - double max_fac, min_fac, waiting; - -/* Enable to get reported waiting activities and total time. -#define Libburn_mmc_wfb_debuG 1 -*/ -#ifdef Libburn_mmc_wfb_debuG - char sleeplist[32768]; - static int buffer_still_invalid = 1; -#endif - - max_fac = ((double) d->wfb_max_percent) / 100.0; - - /* Buffer info from the drive is valid only after writing has begun. - Caring for buffer space makes sense mostly after max_percent of the - buffer was transmitted. */ - if (d->progress.buffered_bytes <= 0 || - d->progress.buffer_capacity <= 0 || - d->progress.buffered_bytes + buf->bytes <= - d->progress.buffer_capacity * max_fac) - return 2; - -#ifdef Libburn_mmc_wfb_debuG - if (buffer_still_invalid) - fprintf(stderr, - "\nLIBBURN_DEBUG: Buffer considered valid now\n"); - buffer_still_invalid = 0; -#endif - - /* The pessimistic counter does not assume any buffer consumption */ - if (d->pessimistic_buffer_free - buf->bytes >= - ( 1.0 - max_fac) * d->progress.buffer_capacity) - return 1; - - /* There is need to inquire the buffer fill */ - d->pessimistic_writes++; - min_fac = ((double) d->wfb_min_percent) / 100.0; - gettimeofday(&t0, &dummy_tz); -#ifdef Libburn_mmc_wfb_debuG - sleeplist[0]= 0; - sprintf(sleeplist,"(%d%s %d)", - (int) (d->pessimistic_buffer_free - buf->bytes), - (d->pbf_altered ? "? -" : " -"), - (int) ((1.0 - max_fac) * d->progress.buffer_capacity)); -#endif - - while (1) { - if ((!first_wait) || d->pbf_altered) { - d->pbf_altered = 1; - mmc_read_buffer_capacity(d); - } -#ifdef Libburn_mmc_wfb_debuG - if(strlen(sleeplist) < sizeof(sleeplist) - 80) - sprintf(sleeplist+strlen(sleeplist)," (%d%s %d)", - (int) (d->pessimistic_buffer_free - buf->bytes), - (d->pbf_altered ? "? -" : " -"), - (int) ((1.0 - min_fac) * d->progress.buffer_capacity)); -#endif - gettimeofday(&tnow,&dummy_tz); - waiting = (tnow.tv_sec - t0.tv_sec) + - ((double) (tnow.tv_usec - t0.tv_usec)) / 1.0e6; - if (d->pessimistic_buffer_free - buf->bytes >= - (1.0 - min_fac) * d->progress.buffer_capacity) { -#ifdef Libburn_mmc_wfb_debuG - if(strlen(sleeplist) >= sizeof(sleeplist) - 80) - strcat(sleeplist," ..."); - sprintf(sleeplist+strlen(sleeplist)," -> %d [%.6f]", - (int) ( - d->pessimistic_buffer_free - buf->bytes - - (1.0 - min_fac) * d->progress.buffer_capacity - ), waiting); - fprintf(stderr, - "\nLIBBURN_DEBUG: sleeplist= %s\n",sleeplist); -#endif - return 1; - } - - /* Waiting is needed */ - if (waiting >= 3 && !reported_3s) { - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x0002013d, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_LOW, - "Waiting for free buffer takes more than 3 seconds", - 0,0); - reported_3s = 1; - } else if (d->wfb_timeout_sec > 0 && - waiting > d->wfb_timeout_sec) { - d->wait_for_buffer_free = 0; - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x0002013d, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Timeout with waiting for free buffer. Now disabled.", - 0,0); - break; - } - - need = (1.0 - min_fac) * d->progress.buffer_capacity + - buf->bytes - d->pessimistic_buffer_free; - usec = 0; - if (d->nominal_write_speed > 0) - usec = ((double) need) / 1000.0 / - ((double) d->nominal_write_speed) * 1.0e6; - else - usec = d->wfb_min_usec * 2; - - /* >>> learn about buffer progress and adjust usec */ - - if (usec < d->wfb_min_usec) - usec = d->wfb_min_usec; - else if (usec > d->wfb_max_usec) - usec = d->wfb_max_usec; - usleep(usec); - if (d->waited_usec < 0xf0000000) - d->waited_usec += usec; - d->waited_tries++; - if(first_wait) - d->waited_writes++; -#ifdef Libburn_mmc_wfb_debuG - if(strlen(sleeplist) < sizeof(sleeplist) - 80) - sprintf(sleeplist+strlen(sleeplist)," %d", usec); -#endif - first_wait = 0; - } - return 0; -} - - -void mmc_write_12(struct burn_drive *d, int start, struct buffer *buf) -{ - struct command c; - int len; - - if (mmc_function_spy(d, "mmc_write_12") <= 0) - return; - - len = buf->sectors; - - /* ts A61009 */ - /* a ssert(buf->bytes >= buf->sectors);*/ /* can be == at 0... */ - - burn_print(100, "trying to write %d at %d\n", len, start); - - scsi_init_command(&c, MMC_WRITE_12, sizeof(MMC_WRITE_12)); -/* - memcpy(c.opcode, MMC_WRITE_12, sizeof(MMC_WRITE_12)); - c.oplen = sizeof(MMC_WRITE_12); -*/ - c.retry = 1; - mmc_int_to_four_char(c.opcode + 2, start); - mmc_int_to_four_char(c.opcode + 6, len); - c.page = buf; - c.dir = TO_DRIVE; - - d->issue_command(d, &c); - - /* ts A70711 */ - d->pessimistic_buffer_free -= buf->bytes; - d->pbf_altered = 1; -} - -int mmc_write(struct burn_drive *d, int start, struct buffer *buf) -{ - int cancelled; - struct command c; - int len; - -#ifdef Libburn_log_in_and_out_streaM - /* <<< ts A61031 */ - static int tee_fd= -1; - if(tee_fd==-1) - tee_fd= open("/tmp/libburn_sg_written", - O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR); -#endif /* Libburn_log_in_and_out_streaM */ - - if (mmc_function_spy(d, "mmc_write") <= 0) - return BE_CANCELLED; - - cancelled = d->cancel; - if (cancelled) - return BE_CANCELLED; - - /* ts A70215 */ - if (d->media_lba_limit > 0 && start >= d->media_lba_limit) { - char msg[160]; - - sprintf(msg, - "Exceeding range of permissible write addresses (%d >= %d)", - start, d->media_lba_limit); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x0002012d, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - d->cancel = 1; /* No need for mutexing because atomic */ - return BE_CANCELLED; - } - - len = buf->sectors; - - /* ts A61009 : buffer fill problems are to be handled by caller */ - /* a ssert(buf->bytes >= buf->sectors);*/ /* can be == at 0... */ - - burn_print(100, "trying to write %d at %d\n", len, start); - - /* ts A70711 */ - if(d->wait_for_buffer_free) - mmc_wait_for_buffer_free(d, buf); - - /* ts A80412 */ - if(d->do_stream_recording > 0) { - - /* >>> ??? is WRITE12 available ? */ - /* >>> ??? inquire feature 107h Stream Writing bit ? */ - - scsi_init_command(&c, MMC_WRITE_12, sizeof(MMC_WRITE_12)); - mmc_int_to_four_char(c.opcode + 2, start); - mmc_int_to_four_char(c.opcode + 6, len); - c.opcode[10] = 1<<7; /* Streaming bit */ - } else { - scsi_init_command(&c, MMC_WRITE_10, sizeof(MMC_WRITE_10)); - mmc_int_to_four_char(c.opcode + 2, start); - c.opcode[6] = 0; - c.opcode[7] = (len >> 8) & 0xFF; - c.opcode[8] = len & 0xFF; - } - c.retry = 1; - c.page = buf; - c.dir = TO_DRIVE; - -#ifdef Libburn_log_in_and_out_streaM - /* <<< ts A61031 */ - if(tee_fd!=-1) { - write(tee_fd,c.page->data,len*2048); - } -#endif /* Libburn_log_in_and_out_streaM */ - - d->issue_command(d, &c); - - /* ts A70711 */ - d->pessimistic_buffer_free -= buf->bytes; - d->pbf_altered = 1; - - /* ts A61112 : react on eventual error condition */ - if (c.error && c.sense[2]!=0) { - - /* >>> make this scsi_notify_error() when liberated */ - if (c.sense[2]!=0) { - char msg[160]; - sprintf(msg, - "SCSI error on write(%d,%d): key=%X asc=%2.2Xh ascq=%2.2Xh", - start, len, - c.sense[2],c.sense[12],c.sense[13]); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x0002011d, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - } - d->cancel = 1; - return BE_CANCELLED; - } - - return 0; -} - - -/* ts A70201 : Set up an entry for mmc_fake_toc() */ -int mmc_fake_toc_entry(struct burn_toc_entry *entry, int session_number, - int track_number, - unsigned char *size_data, unsigned char *start_data) -{ - int min, sec, frames, num; - - /* mark DVD extensions as valid */ - entry->extensions_valid |= 1; - - /* defaults are as of mmc5r03.pdf 6.26.3.2.4 Fabricated TOC */ - entry->session = session_number & 0xff; - entry->session_msb = (session_number >> 8) & 0xff; - entry->adr = 1; - entry->control = 4; - entry->tno = 0; - entry->point = track_number & 0xff; - entry->point_msb = (track_number >> 8) & 0xff; - num = mmc_four_char_to_int(size_data); - entry->track_blocks = num; - burn_lba_to_msf(num, &min, &sec, &frames); - if (min > 255) { - min = 255; - sec = 255; - frames = 255; - } - entry->min = min; - entry->sec = sec; - entry->frame = frames; - entry->zero = 0; - num = mmc_four_char_to_int(start_data); - entry->start_lba = num; - burn_lba_to_msf(num, &min, &sec, &frames); - if (min > 255) { - min = 255; - sec = 255; - frames = 255; - } - entry->pmin = min; - entry->psec = sec; - entry->pframe = frames; - return 1; -} - - -/* ts A71128 : for DVD-ROM drives which offer no reliable track information */ -static int mmc_read_toc_fmt0_al(struct burn_drive *d, int *alloc_len) -{ - struct burn_track *track; - struct burn_session *session; - struct burn_toc_entry *entry; - struct buffer buf; - struct command c; - int dlen, i, old_alloc_len, session_number, prev_session = -1; - int lba, size; - unsigned char *tdata, size_data[4], start_data[4]; - - if (*alloc_len < 4) - return 0; - - scsi_init_command(&c, MMC_GET_TOC_FMT0, sizeof(MMC_GET_TOC_FMT0)); - c.dxfer_len = *alloc_len; - c.opcode[7] = (c.dxfer_len >> 8) & 0xff; - c.opcode[8] = c.dxfer_len & 0xff; - c.retry = 1; - c.page = &buf; - c.page->bytes = 0; - c.page->sectors = 0; - c.dir = FROM_DRIVE; - d->issue_command(d, &c); - - if (c.error) { -err_ex:; - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x0002010d, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, - "Could not inquire TOC", 0,0); - d->status = BURN_DISC_UNSUITABLE; - d->toc_entries = 0; - /* Prefering memory leaks over fandangos */ - d->toc_entry = calloc(1, sizeof(struct burn_toc_entry)); - return 0; - } - dlen = c.page->data[0] * 256 + c.page->data[1]; - old_alloc_len = *alloc_len; - *alloc_len = dlen + 2; - if (old_alloc_len < 12) - return 1; - if (dlen + 2 > old_alloc_len) - dlen = old_alloc_len - 2; - d->complete_sessions = 1 + c.page->data[3] - c.page->data[2]; - d->last_track_no = d->complete_sessions; - if (dlen - 2 < (d->last_track_no + 1) * 8) { - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020159, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, - "TOC Format 0 returns inconsistent data", 0,0); - goto err_ex; - } - - d->toc_entries = d->last_track_no + d->complete_sessions; - if (d->toc_entries < 1) - return 0; - d->toc_entry = calloc(d->toc_entries, sizeof(struct burn_toc_entry)); - if(d->toc_entry == NULL) - return 0; - - d->disc = burn_disc_create(); - if (d->disc == NULL) - return 0; - for (i = 0; i < d->complete_sessions; i++) { - session = burn_session_create(); - if (session == NULL) - return 0; - burn_disc_add_session(d->disc, session, BURN_POS_END); - burn_session_free(session); - } - - - for (i = 0; i < d->last_track_no; i++) { - tdata = c.page->data + 4 + i * 8; - session_number = i + 1; - if (session_number != prev_session && prev_session > 0) { - /* leadout entry previous session */ - entry = &(d->toc_entry[(i - 1) + prev_session]); - lba = mmc_four_char_to_int(start_data) + - mmc_four_char_to_int(size_data); - mmc_int_to_four_char(start_data, lba); - mmc_int_to_four_char(size_data, 0); - mmc_fake_toc_entry(entry, prev_session, 0xA2, - size_data, start_data); - entry->min= entry->sec= entry->frame= 0; - d->disc->session[prev_session - 1]->leadout_entry = - entry; - } - - /* ??? >>> d->media_capacity_remaining , d->media_lba_limit - as of mmc_fake_toc() - */ - - entry = &(d->toc_entry[i + session_number - 1]); - track = burn_track_create(); - if (track == NULL) - return -1; - burn_session_add_track( - d->disc->session[session_number - 1], - track, BURN_POS_END); - track->entry = entry; - burn_track_free(track); - - memcpy(start_data, tdata + 4, 4); - /* size_data are estimated from next track start */ - memcpy(size_data, tdata + 8 + 4, 4); - size = mmc_four_char_to_int(size_data) - - mmc_four_char_to_int(start_data); - mmc_int_to_four_char(size_data, size); - mmc_fake_toc_entry(entry, session_number, i + 1, - size_data, start_data); - if (prev_session != session_number) - d->disc->session[session_number - 1]->firsttrack = i+1; - d->disc->session[session_number - 1]->lasttrack = i+1; - prev_session = session_number; - } - if (prev_session > 0 && prev_session <= d->disc->sessions) { - /* leadout entry of last session of closed disc */ - tdata = c.page->data + 4 + d->last_track_no * 8; - entry = &(d->toc_entry[(d->last_track_no - 1) + prev_session]); - memcpy(start_data, tdata + 4, 4); - mmc_int_to_four_char(size_data, 0); - mmc_fake_toc_entry(entry, prev_session, 0xA2, - size_data, start_data); - entry->min= entry->sec= entry->frame= 0; - d->disc->session[prev_session - 1]->leadout_entry = entry; - } - return 1; -} - - -/* ts A71128 : for DVD-ROM drives which offer no reliable track information */ -static int mmc_read_toc_fmt0(struct burn_drive *d) -{ - int alloc_len = 4, ret; - - if (mmc_function_spy(d, "mmc_read_toc_fmt0") <= 0) - return -1; - ret = mmc_read_toc_fmt0_al(d, &alloc_len); - if (alloc_len >= 12) - ret = mmc_read_toc_fmt0_al(d, &alloc_len); - return ret; -} - - -/* ts A70131 : compose a disc TOC structure from d->complete_sessions - and 52h READ TRACK INFORMATION */ -int mmc_fake_toc(struct burn_drive *d) -{ - struct burn_track *track; - struct burn_session *session; - struct burn_toc_entry *entry; - struct buffer buf; - int i, session_number, prev_session = -1, ret, lba, alloc_len = 34; - unsigned char *tdata, size_data[4], start_data[4]; - char msg[160]; - - if (mmc_function_spy(d, "mmc_fake_toc") <= 0) - return -1; - - if (d->last_track_no <= 0 || d->complete_sessions <= 0 || - d->status == BURN_DISC_BLANK) - return 2; - if (d->last_track_no > BURN_MMC_FAKE_TOC_MAX_SIZE) { - sprintf(msg, - "Too many logical tracks recorded (%d , max. %d)\n", - d->last_track_no, BURN_MMC_FAKE_TOC_MAX_SIZE); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x0002012c, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - msg, 0,0); - return 0; - } - /* ts A71128 : My DVD-ROM drive issues no reliable track info. - One has to try 43h READ TOC/PMA/ATIP Form 0. */ - if ((d->current_profile == 0x10 || d->current_profile == 0x40) && - d->last_track_no <= 1) { - ret = mmc_read_toc_fmt0(d); - return ret; - } - d->disc = burn_disc_create(); - if (d->disc == NULL) - return -1; - d->toc_entries = d->last_track_no + d->complete_sessions; - d->toc_entry = malloc(d->toc_entries * sizeof(struct burn_toc_entry)); - if (d->toc_entry == NULL) - return -1; - memset(d->toc_entry, 0,d->toc_entries * sizeof(struct burn_toc_entry)); - for (i = 0; i < d->complete_sessions; i++) { - session = burn_session_create(); - if (session == NULL) - return -1; - burn_disc_add_session(d->disc, session, BURN_POS_END); - burn_session_free(session); - } - memset(size_data, 0, 4); - memset(start_data, 0, 4); - - - /* Entry Layout : - session 1 track 1 entry 0 - ... - session 1 track N entry N-1 - leadout 1 entry N - session 2 track N+1 entry N+1 - ... - session 2 track M+1 entry M+1 - leadout 2 entry M+2 - session X track K entry (K-1)+(X-1) - ... - session X track i+1 entry i+(X-1) - leadout X entry i+X - */ - for (i = 0; i < d->last_track_no; i++) { - ret = mmc_read_track_info(d, i+1, &buf, alloc_len); - if (ret <= 0) - return ret; - tdata = buf.data; - session_number = (tdata[33] << 8) | tdata[3]; - if (session_number <= 0) - continue; - - if (session_number != prev_session && prev_session > 0) { - /* leadout entry previous session */ - entry = &(d->toc_entry[(i - 1) + prev_session]); - lba = mmc_four_char_to_int(start_data) + - mmc_four_char_to_int(size_data); - mmc_int_to_four_char(start_data, lba); - mmc_int_to_four_char(size_data, 0); - mmc_fake_toc_entry(entry, prev_session, 0xA2, - size_data, start_data); - entry->min= entry->sec= entry->frame= 0; - d->disc->session[prev_session - 1]->leadout_entry = - entry; - } - - if (session_number > d->disc->sessions) { - if (i == d->last_track_no - 1) { - /* ts A70212 : Last track field Free Blocks */ - burn_drive_set_media_capacity_remaining(d, - ((off_t) mmc_four_char_to_int(tdata + 16)) * - ((off_t) 2048)); - d->media_lba_limit = 0; - } - continue; - } - - entry = &(d->toc_entry[i + session_number - 1]); - track = burn_track_create(); - if (track == NULL) - return -1; - burn_session_add_track( - d->disc->session[session_number - 1], - track, BURN_POS_END); - track->entry = entry; - burn_track_free(track); - - memcpy(size_data, tdata + 24, 4); - memcpy(start_data, tdata + 8, 4); - mmc_fake_toc_entry(entry, session_number, i + 1, - size_data, start_data); - - if (prev_session != session_number) - d->disc->session[session_number - 1]->firsttrack = i+1; - d->disc->session[session_number - 1]->lasttrack = i+1; - prev_session = session_number; - } - if (prev_session > 0 && prev_session <= d->disc->sessions) { - /* leadout entry of last session of closed disc */ - entry = &(d->toc_entry[(d->last_track_no - 1) + prev_session]); - lba = mmc_four_char_to_int(start_data) + - mmc_four_char_to_int(size_data); - mmc_int_to_four_char(start_data, lba); - mmc_int_to_four_char(size_data, 0); - mmc_fake_toc_entry(entry, prev_session, 0xA2, - size_data, start_data); - entry->min= entry->sec= entry->frame= 0; - d->disc->session[prev_session - 1]->leadout_entry = entry; - } - return 1; -} - - -static int mmc_read_toc_al(struct burn_drive *d, int *alloc_len) -{ -/* read full toc, all sessions, in m/s/f form, 4k buffer */ -/* ts A70201 : or fake a toc from track information */ - struct burn_track *track; - struct burn_session *session; - struct buffer buf; - struct command c; - int dlen; - int i, bpl= 12, old_alloc_len; - unsigned char *tdata; - - if (*alloc_len < 4) - return 0; - - if (!(d->current_profile == -1 || d->current_is_cd_profile)) { - /* ts A70131 : MMC_GET_TOC uses Response Format 2 - For DVD this fails with 5,24,00 */ - /* mmc_read_toc_fmt0() uses - Response Format 0: mmc5r03.pdf 6.26.3.2 - which does not yield the same result with the same disc - on different drives. - */ - /* ts A70201 : - This uses the session count from 51h READ DISC INFORMATION - and the track records from 52h READ TRACK INFORMATION. - mmc_read_toc_fmt0() is used as fallback for dull DVD-ROM. - */ - mmc_fake_toc(d); - - if (d->status == BURN_DISC_UNREADY) - d->status = BURN_DISC_FULL; - return 1; - } - scsi_init_command(&c, MMC_GET_TOC, sizeof(MMC_GET_TOC)); -/* - memcpy(c.opcode, MMC_GET_TOC, sizeof(MMC_GET_TOC)); - c.oplen = sizeof(MMC_GET_TOC); -*/ - c.dxfer_len = *alloc_len; - c.opcode[7] = (c.dxfer_len >> 8) & 0xff; - c.opcode[8] = c.dxfer_len & 0xff; - c.retry = 1; - c.page = &buf; - c.page->bytes = 0; - c.page->sectors = 0; - c.dir = FROM_DRIVE; - d->issue_command(d, &c); - - if (c.error) { - - /* ts A61020 : this snaps on non-blank DVD media */ - /* ts A61106 : also snaps on CD with unclosed track/session */ - /* Very unsure wether this old measure is ok. - Obviously higher levels do not care about this. - outdated info: DVD+RW burns go on after passing through here. - - d->busy = BURN_DRIVE_IDLE; - */ - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x0002010d, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, - "Could not inquire TOC", 0,0); - d->status = BURN_DISC_UNSUITABLE; - d->toc_entries = 0; - /* Prefering memory leaks over fandangos */ - d->toc_entry = calloc(1, sizeof(struct burn_toc_entry)); - return 0; - } - - dlen = c.page->data[0] * 256 + c.page->data[1]; - old_alloc_len = *alloc_len; - *alloc_len = dlen + 2; - if (old_alloc_len < 15) - return 1; - if (dlen + 2 > old_alloc_len) - dlen = old_alloc_len - 2; - d->toc_entries = (dlen - 2) / 11; - if (d->toc_entries < 1) - return 0; -/* - some drives fail this check. - - ts A61007 : if re-enabled then not via Assert. - a ssert(((dlen - 2) % 11) == 0); -*/ - d->toc_entry = calloc(d->toc_entries, sizeof(struct burn_toc_entry)); - if(d->toc_entry == NULL) /* ts A70825 */ - return 0; - tdata = c.page->data + 4; - - burn_print(12, "TOC:\n"); - - d->disc = burn_disc_create(); - if (d->disc == NULL) /* ts A70825 */ - return 0; - - for (i = 0; i < c.page->data[3]; i++) { - session = burn_session_create(); - if (session == NULL) /* ts A70825 */ - return 0; - burn_disc_add_session(d->disc, session, BURN_POS_END); - burn_session_free(session); - } - - /* ts A61022 */ - burn_print(bpl, "-----------------------------------\n"); - - for (i = 0; i < d->toc_entries; i++, tdata += 11) { - - /* ts A61022: was burn_print level 12 */ - burn_print(bpl, "S %d, PT %2.2Xh, TNO %d :", tdata[0],tdata[3], - tdata[2]); - burn_print(bpl, " MSF(%d:%d:%d)", tdata[4],tdata[5],tdata[6]); - burn_print(bpl, " PMSF(%d:%d:%d %d)", - tdata[8], tdata[9], tdata[10], - burn_msf_to_lba(tdata[8], tdata[9], tdata[10])); - burn_print(bpl, " - control %d, adr %d\n", tdata[1] & 0xF, - tdata[1] >> 4); - -/* - fprintf(stderr, "libburn_experimental: toc entry #%d : %d %d %d\n",i,tdata[8], tdata[9], tdata[10]); -*/ - - if (tdata[3] == 1) { - if (burn_msf_to_lba(tdata[8], tdata[9], tdata[10])) { - d->disc->session[0]->hidefirst = 1; - track = burn_track_create(); - burn_session_add_track(d->disc-> - session[tdata[0] - 1], - track, BURN_POS_END); - burn_track_free(track); - - } - } - if (tdata[0] <= 0 || tdata[0] > d->disc->sessions) - tdata[0] = d->disc->sessions; - if (tdata[3] < 100 && tdata[0] > 0) { - track = burn_track_create(); - burn_session_add_track(d->disc->session[tdata[0] - 1], - track, BURN_POS_END); - track->entry = &d->toc_entry[i]; - burn_track_free(track); - } - d->toc_entry[i].session = tdata[0]; - d->toc_entry[i].adr = tdata[1] >> 4; - d->toc_entry[i].control = tdata[1] & 0xF; - d->toc_entry[i].tno = tdata[2]; - d->toc_entry[i].point = tdata[3]; - d->toc_entry[i].min = tdata[4]; - d->toc_entry[i].sec = tdata[5]; - d->toc_entry[i].frame = tdata[6]; - d->toc_entry[i].zero = tdata[7]; - d->toc_entry[i].pmin = tdata[8]; - d->toc_entry[i].psec = tdata[9]; - d->toc_entry[i].pframe = tdata[10]; - if (tdata[3] == 0xA0) - d->disc->session[tdata[0] - 1]->firsttrack = tdata[8]; - if (tdata[3] == 0xA1) - d->disc->session[tdata[0] - 1]->lasttrack = tdata[8]; - if (tdata[3] == 0xA2) - d->disc->session[tdata[0] - 1]->leadout_entry = - &d->toc_entry[i]; - } - - /* ts A61022 */ - burn_print(bpl, "-----------------------------------\n"); - - /* ts A70131 : was (d->status != BURN_DISC_BLANK) */ - if (d->status == BURN_DISC_UNREADY) - d->status = BURN_DISC_FULL; - toc_find_modes(d); - return 1; -} - - -void mmc_read_toc(struct burn_drive *d) -{ - int alloc_len = 4, ret; - - if (mmc_function_spy(d, "mmc_read_toc") <= 0) - return; - - ret = mmc_read_toc_al(d, &alloc_len); -/* - fprintf(stderr, - "LIBBURN_DEBUG: 43h READ TOC alloc_len = %d , ret = %d\n", - alloc_len, ret); -*/ - if (alloc_len >= 15) - ret = mmc_read_toc_al(d, &alloc_len); -} - - -/* ts A70131 : This tries to get the start of the last complete session */ -/* man mkisofs , option -C : - The first number is the sector number of the first sector in - the last session of the disk that should be appended to. -*/ -int mmc_read_multi_session_c1(struct burn_drive *d, int *trackno, int *start) -{ - struct buffer buf; - struct command c; - unsigned char *tdata; - int num_sessions, session_no, num_tracks, alloc_len = 12; - struct burn_disc *disc; - struct burn_session **sessions; - struct burn_track **tracks; - struct burn_toc_entry toc_entry; - - if (mmc_function_spy(d, "mmc_read_multi_session_c1") <= 0) - return 0; - - /* First try to evaluate the eventually loaded TOC before issueing - a MMC command. This search obtains the first track of the last - complete session which has a track. - */ - *trackno = 0; - disc = burn_drive_get_disc(d); - if (disc == NULL) - goto inquire_drive; - sessions = burn_disc_get_sessions(disc, &num_sessions); - for (session_no = 0; session_no<num_sessions; session_no++) { - tracks = burn_session_get_tracks(sessions[session_no], - &num_tracks); - if (tracks == NULL || num_tracks <= 0) - continue; - burn_track_get_entry(tracks[0], &toc_entry); - if (toc_entry.extensions_valid & 1) { /* DVD extension valid */ - *start = toc_entry.start_lba; - *trackno = (toc_entry.point_msb << 8)| toc_entry.point; - } else { - *start = burn_msf_to_lba(toc_entry.pmin, - toc_entry.psec, toc_entry.pframe); - *trackno = toc_entry.point; - } - } - burn_disc_free(disc); - if(*trackno > 0) - return 1; - -inquire_drive:; - /* mmc5r03.pdf 6.26.3.3.3 states that with non-CD this would - be a useless fake always starting at track 1, lba 0. - My drives return useful data, though. - MMC-3 states that DVD had no tracks. So maybe this mandatory fake - is a forgotten legacy ? - */ - scsi_init_command(&c, MMC_GET_MSINFO, sizeof(MMC_GET_MSINFO)); -/* - memcpy(c.opcode, MMC_GET_MSINFO, sizeof(MMC_GET_MSINFO)); - c.oplen = sizeof(MMC_GET_MSINFO); -*/ - c.dxfer_len = alloc_len; - c.opcode[7]= (c.dxfer_len >> 8) & 0xff; - c.opcode[8]= c.dxfer_len & 0xff; - c.retry = 1; - c.page = &buf; - c.page->bytes = 0; - c.page->sectors = 0; - c.dir = FROM_DRIVE; - d->issue_command(d, &c); - - if (c.error) - return 0; - - tdata = c.page->data + 4; - *trackno = tdata[2]; - *start = mmc_four_char_to_int(tdata + 4); - return 1; -} - - -static int mmc_read_disc_info_al(struct burn_drive *d, int *alloc_len) -{ - struct buffer buf; - unsigned char *data; - struct command c; - char msg[160]; - /* ts A70131 : had to move mmc_read_toc() to end of function */ - int do_read_toc = 0, session_state, disc_status, len, old_alloc_len; - - /* ts A61020 */ - d->start_lba = d->end_lba = -2000000000; - d->erasable = 0; - d->last_track_no = 1; - - /* ts A70212 - A70215 */ - d->media_capacity_remaining = 0; - d->media_lba_limit = 0; - - /* ts A61202 */ - d->toc_entries = 0; - if (d->status == BURN_DISC_EMPTY) - return 1; - - mmc_get_configuration(d); - -/* ts A70910 : found this as condition for mmc_function_spy() which went up - if (*alloc_len < 2) -*/ - - scsi_init_command(&c, MMC_GET_DISC_INFO, sizeof(MMC_GET_DISC_INFO)); -/* - memcpy(c.opcode, MMC_GET_DISC_INFO, sizeof(MMC_GET_DISC_INFO)); - c.oplen = sizeof(MMC_GET_DISC_INFO); -*/ - c.dxfer_len = *alloc_len; - c.opcode[7]= (c.dxfer_len >> 8) & 0xff; - c.opcode[8]= c.dxfer_len & 0xff; - c.retry = 1; - c.page = &buf; - c.page->sectors = 0; - c.page->bytes = 0; - c.dir = FROM_DRIVE; - d->issue_command(d, &c); - - if (c.error) { - d->busy = BURN_DRIVE_IDLE; - return 0; - } - - data = c.page->data; - len = (data[0] << 8) | data[1]; - old_alloc_len = *alloc_len; - *alloc_len = len + 2; - if (old_alloc_len < 34) - return 1; - if (*alloc_len < 24) /* data[23] is the last byte used here */ - return 0; - if (len + 2 > old_alloc_len) - len = old_alloc_len - 2; - - d->erasable = !!(data[2] & 16); - - disc_status = data[2] & 3; - if (d->current_profile == 0x10 || d->current_profile == 0x40) { - /* DVD-ROM , BD-ROM */ - disc_status = 2; /* always full and finalized */ - d->erasable = 0; /* never erasable */ - } - - /* ts A80207 : DVD - R DL can normally be read but not be written */ - if(d->current_profile == 0x15 && !burn_support_untested_profiles) { - disc_status = 2; /* always full and finalized */ - d->erasable = 0; /* never erasable */ - } - -#ifdef Libburn_support_bd_r_readonlY - /* <<< For now: declaring BD-R read-only - */ - if (d->current_profile == 0x41 || d->current_profile == 0x42) { - /* BD-R seq, BD-R rnd */ - disc_status = 2; /* always full and finalized */ - d->erasable = 0; /* never erasable */ - } -#endif /* Libburn_support_bd_r_readonlY */ - - switch (disc_status) { - case 0: - d->toc_entries = 0; - d->start_lba = burn_msf_to_lba(data[17], data[18], data[19]); - d->end_lba = burn_msf_to_lba(data[21], data[22], data[23]); - -/* - fprintf(stderr, "libburn_experimental: start_lba = %d (%d %d %d) , end_lba = %d (%d %d %d)\n", - d->start_lba, data[17], data[18], data[19], - d->end_lba, data[21], data[22], data[23]); -*/ - - d->status = BURN_DISC_BLANK; - break; - case 1: - d->status = BURN_DISC_APPENDABLE; - case 2: - if (disc_status == 2) - d->status = BURN_DISC_FULL; - do_read_toc = 1; - break; - } - - -#ifdef NIX - /* <<< on its way out. DVD-R DL are current_is_supported_profile - unconditionally. Writeability is handled above now. - */ - /* ts A80207 : DVD - R DL can normally be read but not be written */ - if(d->current_profile == 0x15 && !d->current_is_supported_profile) { - if(d->status == BURN_DISC_APPENDABLE) - d->status = BURN_DISC_FULL; - d->erasable = 0; /* never erasable */ - d->current_is_supported_profile = 1; - } -#endif /* NIX */ - - - if ((d->current_profile != 0 || d->status != BURN_DISC_UNREADY) - && ! d->current_is_supported_profile) { - if (!d->silent_on_scsi_error) { - sprintf(msg, - "Unsuitable media detected. Profile %4.4Xh %s", - d->current_profile, d->current_profile_text); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x0002011e, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - msg, 0,0); - } - d->status = BURN_DISC_UNSUITABLE; - return 0; - } - - /* >>> ts A61217 : Note for future - growisofs performs OPC if (data[0]<<8)|data[1]<=32 - which indicates no OPC entries are attached to the - reply from the drive. - */ - - /* ts A61219 : mmc5r03c.pdf 6.22.3.1.13 BG Format Status - 0=blank (not yet started) - 1=started but neither running nor complete - 2=in progress - 3=completed - */ - d->bg_format_status = data[7] & 3; - - /* Preliminarily declare blank: - ts A61219 : DVD+RW (is not bg_format_status==0 "blank") - ts A61229 : same for DVD-RW Restricted overwrite - ts A70112 : same for DVD-RAM - */ - if (d->current_profile == 0x1a || d->current_profile == 0x13 || - d->current_profile == 0x12 || d->current_profile == 0x43) - d->status = BURN_DISC_BLANK; - - if (d->status == BURN_DISC_BLANK) { - d->last_track_no = 1; /* The "incomplete track" */ - d->complete_sessions = 0; - } else { - /* ts A70131 : number of non-empty sessions */ - d->complete_sessions = (data[9] << 8) | data[4]; - session_state = (data[2] >> 2) & 3; - /* mmc5r03c.pdf 6.22.3.1.3 State of Last Session: 3=complete */ - if (session_state != 3 && d->complete_sessions >= 1) - d->complete_sessions--; - - /* ts A70129 : mmc5r03c.pdf 6.22.3.1.7 - This includes the "incomplete track" if the disk is - appendable. I.e number of complete tracks + 1. */ - d->last_track_no = (data[11] << 8) | data[6]; - } - if (d->current_profile != 0x0a && d->current_profile != 0x13 && - d->current_profile != 0x14 && d->status != BURN_DISC_FULL) - d->erasable = 0; /* stay in sync with burn_disc_erase() */ - - if (do_read_toc) - mmc_read_toc(d); - return 1; -} - - -void mmc_read_disc_info(struct burn_drive *d) -{ - int alloc_len = 34, ret; - - if (mmc_function_spy(d, "mmc_read_disc_info") <= 0) - return; - - ret = mmc_read_disc_info_al(d, &alloc_len); -/* - fprintf(stderr,"LIBBURN_DEBUG: 51h alloc_len = %d , ret = %d\n", - alloc_len, ret); -*/ - /* for now there is no need to inquire the variable lenght part */ -} - - -void mmc_read_atip(struct burn_drive *d) -{ - struct buffer buf; - struct command c; - int alloc_len = 28; - - /* ts A61021 */ - unsigned char *data; - /* Speed values from A1: - With 4 cdrecord tells "10" or "8" where MMC-1 says "8". - cdrecord "8" appear on 4xCD-RW and thus seem to be quite invalid. - My CD-R (>=24 speed) tell no A1. - The higher non-MMC-1 values are hearsay. - */ - /* 0, 2, 4, 6, 10, -, 16, -, */ - static int speed_value[16]= { 0, 353, 706, 1059, 1764, -5, 2824, -7, - 4234, 5646, 7056, 8468, -12, -13, -14, -15}; - /* 24, 32, 40, 48, -, -, -, - */ - - if (mmc_function_spy(d, "mmc_read_atip") <= 0) - return; - - scsi_init_command(&c, MMC_GET_ATIP, sizeof(MMC_GET_ATIP)); -/* - memcpy(c.opcode, MMC_GET_ATIP, sizeof(MMC_GET_ATIP)); - c.oplen = sizeof(MMC_GET_ATIP); -*/ - c.dxfer_len = alloc_len; - c.opcode[7]= (c.dxfer_len >> 8) & 0xff; - c.opcode[8]= c.dxfer_len & 0xff; - c.retry = 1; - c.page = &buf; - c.page->bytes = 0; - c.page->sectors = 0; - - c.dir = FROM_DRIVE; - d->issue_command(d, &c); - burn_print(1, "atip shit for you\n"); - - - /* ts A61021 */ - data = c.page->data; - d->erasable= !!(data[6]&64); - d->start_lba= burn_msf_to_lba(data[8],data[9],data[10]); - d->end_lba= burn_msf_to_lba(data[12],data[13],data[14]); - if (data[6]&4) { - if (speed_value[(data[16]>>4)&7] > 0) { - d->mdata->min_write_speed = - speed_value[(data[16]>>4)&7]; - if (speed_value[(data[16])&15] <= 0) - d->mdata->max_write_speed = - speed_value[(data[16]>>4)&7]; - } - if (speed_value[(data[16])&15] > 0) { - d->mdata->max_write_speed = - speed_value[(data[16])&15]; - if (speed_value[(data[16]>>4)&7] <= 0) - d->mdata->min_write_speed = - speed_value[(data[16])&15]; - } - } - -#ifdef Burn_mmc_be_verbous_about_atiP - { int i; - fprintf(stderr,"libburn_experimental: Returned ATIP Data\n"); - for(i= 0; i<28; i++) - fprintf(stderr,"%3.3d (0x%2.2x)%s", - data[i],data[i],((i+1)%5 ? " ":"\n")); - fprintf(stderr,"\n"); - - fprintf(stderr, - "libburn_experimental: Indicative Target Writing Power= %d\n", - (data[4]>>4)&7); - fprintf(stderr, - "libburn_experimental: Reference speed= %d ->%d\n", - data[4]&7, speed_value[data[4]&7]); - fprintf(stderr, - "libburn_experimental: Is %sunrestricted\n", - (data[5]&64?"":"not ")); - fprintf(stderr, - "libburn_experimental: Is %serasable, sub-type %d\n", - (data[6]&64?"":"not "),(data[6]>>3)&3); - fprintf(stderr, - "libburn_experimental: lead in: %d (%-2.2d:%-2.2d/%-2.2d)\n", - burn_msf_to_lba(data[8],data[9],data[10]), - data[8],data[9],data[10]); - fprintf(stderr, - "libburn_experimental: lead out: %d (%-2.2d:%-2.2d/%-2.2d)\n", - burn_msf_to_lba(data[12],data[13],data[14]), - data[12],data[13],data[14]); - if(data[6]&4) - fprintf(stderr, - "libburn_experimental: A1 speed low %d speed high %d\n", - speed_value[(data[16]>>4)&7], speed_value[(data[16])&7]); - if(data[6]&2) - fprintf(stderr, - "libburn_experimental: A2 speed low %d speed high %d\n", - speed_value[(data[20]>>4)&7], speed_value[(data[20])&7]); - if(data[6]&1) - fprintf(stderr, - "libburn_experimental: A3 speed low %d speed high %d\n", - speed_value[(data[24]>>4)&7], speed_value[(data[24])&7]); - } - -#endif /* Burn_mmc_be_verbous_about_atiP */ - -/* ts A61020 -http://www.t10.org/ftp/t10/drafts/mmc/mmc-r10a.pdf , table 77 : - - 0 ATIP Data Length MSB - 1 ATIP Data Length LSB - 2 Reserved - 3 Reserved - 4 bit7=1, bit4-6="Indicative Target Writing Power", bit3=reserved , - bit0-2="Reference speed" - 5 bit7=0, bit6="URU" , bit0-5=reserved - 6 bit7=1, bit6="Disc Type", bit3-4="Disc Sub-Type", - bit2="A1", bit1="A2", bit0="A3" - 7 reserved - 8 ATIP Start Time of lead-in (Min) - 9 ATIP Start Time of lead-in (Sec) -10 ATIP Start Time of lead-in (Frame) -11 reserved -12 ATIP Last Possible Start Time of lead-out (Min) -13 ATIP Last Possible Start Time of lead-out (Sec) -14 ATIP Last Possible Start Time of lead-out (Frame) -15 reserved -16 bit7=0, bit4-6="Lowest Usable CLV Recording speed" - bit0-3="Highest Usable CLV Recording speed" -17 bit7=0, bit4-6="Power Multiplication Factor p", - bit1-3="Target y value of the Modulation/Power function", bit0=reserved -18 bit7=1, bit4-6="Recommended Erase/Write Power Ratio (P(inf)/W(inf))" - bit0-3=reserved -19 reserved -20-22 A2 Values -23 reserved -24-26 A3 Values -27 reserved - -Disc Type - zero indicates CD-R media; one indicates CD-RW media. - -Disc Sub-Type - shall be set to zero. - -A1 - when set to one, indicates that bytes 16-18 are valid. - -Lowest Usable CLV Recording Speed -000b Reserved -001b 2X -010b - 111b Reserved - -Highest CLV Recording Speeds -000b Reserved -001b 2X -010b 4X -011b 6X -100b 8X -101b - 111b Reserved - -MMC-3 seems to recommend MODE SENSE (5Ah) page 2Ah rather than A1, A2, A3. -This page is loaded in libburn function spc_sense_caps() . -Speed is given in kbytes/sec there. But i suspect this to be independent -of media. So one would habe to associate the speed descriptor blocks with -the ATIP media characteristics ? How ? - -*/ -} - -void mmc_read_sectors(struct burn_drive *d, - int start, - int len, - const struct burn_read_opts *o, struct buffer *buf) -{ - int temp; - int errorblock, req; - struct command c; - - if (mmc_function_spy(d, "mmc_read_sectors") <= 0) - return; - - /* ts A61009 : to be ensured by callers */ - /* a ssert(len >= 0); */ - -/* if the drive isn't busy, why the hell are we here? */ - /* ts A61006 : i second that question */ - /* a ssert(d->busy); */ - - burn_print(12, "reading %d from %d\n", len, start); - - scsi_init_command(&c, MMC_READ_CD, sizeof(MMC_READ_CD)); -/* - memcpy(c.opcode, MMC_READ_CD, sizeof(MMC_READ_CD)); - c.oplen = sizeof(MMC_READ_CD); -*/ - c.retry = 1; - temp = start; - c.opcode[5] = temp & 0xFF; - temp >>= 8; - c.opcode[4] = temp & 0xFF; - temp >>= 8; - c.opcode[3] = temp & 0xFF; - temp >>= 8; - c.opcode[2] = temp & 0xFF; - c.opcode[8] = len & 0xFF; - len >>= 8; - c.opcode[7] = len & 0xFF; - len >>= 8; - c.opcode[6] = len & 0xFF; - req = 0xF8; - - /* ts A61106 : LG GSA-4082B dislikes this. key=5h asc=24h ascq=00h - - if (d->busy == BURN_DRIVE_GRABBING || o->report_recovered_errors) - req |= 2; - */ - - c.opcode[10] = 0; -/* always read the subcode, throw it away later, since we don't know - what we're really reading -*/ - if (d->busy == BURN_DRIVE_GRABBING || (o->subcodes_audio) - || (o->subcodes_data)) - c.opcode[10] = 1; - - c.opcode[9] = req; - c.page = buf; - c.dir = FROM_DRIVE; - d->issue_command(d, &c); - - if (c.error) { - burn_print(12, "got an error over here\n"); - burn_print(12, "%d, %d, %d, %d\n", c.sense[3], c.sense[4], - c.sense[5], c.sense[6]); - errorblock = - (c.sense[3] << 24) + (c.sense[4] << 16) + - (c.sense[5] << 8) + c.sense[6]; - c.page->sectors = errorblock - start + 1; - burn_print(1, "error on block %d\n", errorblock); - burn_print(12, "error on block %d\n", errorblock); - burn_print(12, "returning %d sectors\n", c.page->sectors); - } -} - -void mmc_erase(struct burn_drive *d, int fast) -{ - struct command c; - - if (mmc_function_spy(d, "mmc_erase") <= 0) - return; - - scsi_init_command(&c, MMC_BLANK, sizeof(MMC_BLANK)); -/* - memcpy(c.opcode, MMC_BLANK, sizeof(MMC_BLANK)); - c.oplen = sizeof(MMC_BLANK); -*/ - c.opcode[1] = 16; /* IMMED set to 1 */ - c.opcode[1] |= !!fast; - c.retry = 1; - c.page = NULL; - c.dir = NO_TRANSFER; - d->issue_command(d, &c); -} - -void mmc_read_lead_in(struct burn_drive *d, struct buffer *buf) -{ - int len; - struct command c; - - if (mmc_function_spy(d, "mmc_read_lead_in") <= 0) - return; - - len = buf->sectors; - scsi_init_command(&c, MMC_READ_CD, sizeof(MMC_READ_CD)); -/* - memcpy(c.opcode, MMC_READ_CD, sizeof(MMC_READ_CD)); - c.oplen = sizeof(MMC_READ_CD); -*/ - c.retry = 1; - c.opcode[5] = 0; - c.opcode[4] = 0; - c.opcode[3] = 0; - c.opcode[2] = 0xF0; - c.opcode[8] = 1; - c.opcode[7] = 0; - c.opcode[6] = 0; - c.opcode[9] = 0; - c.opcode[10] = 2; - c.page = buf; - c.dir = FROM_DRIVE; - d->issue_command(d, &c); -} - -void mmc_perform_opc(struct burn_drive *d) -{ - struct command c; - - if (mmc_function_spy(d, "mmc_perform_opc") <= 0) - return; - - scsi_init_command(&c, MMC_SEND_OPC, sizeof(MMC_SEND_OPC)); -/* - memcpy(c.opcode, MMC_SEND_OPC, sizeof(MMC_SEND_OPC)); - c.oplen = sizeof(MMC_SEND_OPC); -*/ - c.retry = 1; - c.opcode[1] = 1; - c.page = NULL; - c.dir = NO_TRANSFER; - d->issue_command(d, &c); -} - - -/* ts A61221 : Learned much from dvd+rw-tools-7.0 set_speed_B6h() but then - made own experiments on base of mmc5r03c.pdf 6.8.3 and 6.39 in the hope - to achieve a leaner solution - ts A70712 : That leaner solution does not suffice for my LG GSA-4082B. - Meanwhile there is a speed descriptor list anyway. -*/ -int mmc_set_streaming(struct burn_drive *d, - int r_speed, int w_speed, int end_lba) -{ - struct buffer buf; - struct command c; - int b, eff_end_lba; - char msg[160]; - unsigned char *pd; - - if (mmc_function_spy(d, "mmc_set_streaming") <= 0) - return 0; - - scsi_init_command(&c, MMC_SET_STREAMING, sizeof(MMC_SET_STREAMING)); -/* - c.oplen = sizeof(MMC_SET_STREAMING); - memcpy(c.opcode, MMC_SET_STREAMING, sizeof(MMC_SET_STREAMING)); -*/ - c.retry = 1; - c.page = &buf; - c.page->bytes = 28; - c.opcode[9] = (c.page->bytes >> 8) & 0xff; - c.opcode[10] = c.page->bytes & 0xff; - c.page->sectors = 0; - c.dir = TO_DRIVE; - memset(c.page->data, 0, c.page->bytes); - pd = c.page->data; - - pd[0] = 0; /* WRC=0 (Default Rotation Control), RDD=Exact=RA=0 */ - - if (w_speed == 0) - w_speed = 0x10000000; /* ~ 2 TB/s */ - else if (w_speed < 0) - w_speed = 177; /* 1x CD */ - if (r_speed == 0) - r_speed = 0x10000000; /* ~ 2 TB/s */ - else if (r_speed < 0) - r_speed = 177; /* 1x CD */ - if (end_lba == 0) { - /* Default computed from 4.7e9 */ - eff_end_lba = 2294921 - 1; - if (d->mdata->max_end_lba > 0) - eff_end_lba = d->mdata->max_end_lba - 1; - } else - eff_end_lba = end_lba; - - sprintf(msg, "mmc_set_streaming: end_lba=%d , r=%d , w=%d", - end_lba, r_speed, w_speed); - libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - msg, 0, 0); - - /* start_lba is 0 , 1000 = 1 second as base time for data rate */ - for (b = 0; b < 4 ; b++) { - pd[8+b] = (end_lba >> (24 - 8 * b)) & 0xff; - pd[12+b] = (r_speed >> (24 - 8 * b)) & 0xff; - pd[16+b] = (1000 >> (24 - 8 * b)) & 0xff; - pd[20+b] = (w_speed >> (24 - 8 * b)) & 0xff; - pd[24+b] = (1000 >> (24 - 8 * b)) & 0xff; - } - -/* <<< - fprintf(stderr,"LIBBURN_EXPERIMENTAL : B6h Performance descriptor:\n"); - for (b = 0; b < 28 ; b++) - fprintf(stderr, "%2.2X%c", pd[b], ((b+1)%4 ? ' ' : '\n')); -*/ - - - d->issue_command(d, &c); - if (c.error) { - if (c.sense[2]!=0 && !d->silent_on_scsi_error) { - sprintf(msg, - "SCSI error on set_streaming(%d): key=%X asc=%2.2Xh ascq=%2.2Xh", - w_speed, - c.sense[2],c.sense[12],c.sense[13]); - libdax_msgs_submit(libdax_messenger, - d->global_index, - 0x00020124, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - } - return 0; - } - return 1; -} - - -void mmc_set_speed(struct burn_drive *d, int r, int w) -{ - struct command c; - int ret, end_lba = 0; - struct burn_speed_descriptor *best_sd = NULL; - - if (mmc_function_spy(d, "mmc_set_speed") <= 0) - return; - - if (r <= 0 || w <= 0) { - /* ts A70712 : now searching for best speed descriptor */ - if (w > 0 && r <= 0) - burn_drive_get_best_speed(d, r, &best_sd, 1); - else - burn_drive_get_best_speed(d, w, &best_sd, 0); - if (best_sd != NULL) { - w = best_sd->write_speed; - d->nominal_write_speed = w; - r = best_sd->read_speed; - end_lba = best_sd->end_lba; - } - } - - /* A70711 */ - d->nominal_write_speed = w; - - /* ts A61221 : try to set DVD speed via command B6h */ - if (strstr(d->current_profile_text, "DVD") == d->current_profile_text){ - ret = mmc_set_streaming(d, r, w, end_lba); - if (ret != 0) - return; /* success or really fatal failure */ - } - - /* ts A61112 : MMC standards prescribe FFFFh as max speed. - But libburn.h prescribes 0. - ts A70715 : <0 now means minimum speed */ - if (r == 0 || r > 0xffff) - r = 0xffff; - else if (r < 0) - r = 177; /* 1x CD */ - if (w == 0 || w > 0xffff) - w = 0xffff; - else if (w < 0) - w = 177; /* 1x CD */ - - scsi_init_command(&c, MMC_SET_SPEED, sizeof(MMC_SET_SPEED)); -/* - memcpy(c.opcode, MMC_SET_SPEED, sizeof(MMC_SET_SPEED)); - c.oplen = sizeof(MMC_SET_SPEED); -*/ - c.retry = 1; - c.opcode[2] = r >> 8; - c.opcode[3] = r & 0xFF; - c.opcode[4] = w >> 8; - c.opcode[5] = w & 0xFF; - c.page = NULL; - c.dir = NO_TRANSFER; - d->issue_command(d, &c); -} - - -/* ts A61201 */ -static char *mmc_obtain_profile_name(int profile_number) -{ - static char *texts[0x53] = {NULL}; - int i, max_pno = 0x53; - - if (texts[0] == NULL) { - for (i = 0; i<max_pno; i++) - texts[i] = ""; - /* mmc5r03c.pdf , Table 89, Spelling: guessed cdrecord style */ - texts[0x01] = "Non-removable disk"; - texts[0x02] = "Removable disk"; - texts[0x03] = "MO erasable"; - texts[0x04] = "Optical write once"; - texts[0x05] = "AS-MO"; - texts[0x08] = "CD-ROM"; - texts[0x09] = "CD-R"; - texts[0x0a] = "CD-RW"; - texts[0x10] = "DVD-ROM"; - texts[0x11] = "DVD-R sequential recording"; - texts[0x12] = "DVD-RAM"; - texts[0x13] = "DVD-RW restricted overwrite"; - texts[0x14] = "DVD-RW sequential recording"; - texts[0x15] = "DVD-R/DL sequential recording"; - texts[0x16] = "DVD-R/DL layer jump recording"; - texts[0x1a] = "DVD+RW"; - texts[0x1b] = "DVD+R"; - texts[0x2a] = "DVD+RW/DL"; - texts[0x2b] = "DVD+R/DL"; - texts[0x40] = "BD-ROM"; - texts[0x41] = "BD-R sequential recording"; - texts[0x42] = "BD-R random recording"; - texts[0x43] = "BD-RE"; - texts[0x50] = "HD-DVD-ROM"; - texts[0x51] = "HD-DVD-R"; - texts[0x52] = "HD-DVD-RAM"; - } - if (profile_number<0 || profile_number>=max_pno) - return ""; - return texts[profile_number]; -} - - -/* ts A61201 : found in unfunctional state - */ -static int mmc_get_configuration_al(struct burn_drive *d, int *alloc_len) -{ - struct buffer buf; - int len, cp, descr_len = 0, feature_code, prf_number, only_current = 1; - int old_alloc_len; - unsigned char *descr, *prf, *up_to, *prf_end; - struct command c; - int phys_if_std = 0; - char *phys_name = ""; - - if (*alloc_len < 8) - return 0; - - d->current_profile = 0; - d->current_profile_text[0] = 0; - d->current_is_cd_profile = 0; - d->current_is_supported_profile = 0; - d->current_has_feat21h = 0; - d->current_feat21h_link_size = -1; - d->current_feat2fh_byte4 = -1; - - scsi_init_command(&c, MMC_GET_CONFIGURATION, - sizeof(MMC_GET_CONFIGURATION)); -/* - memcpy(c.opcode, MMC_GET_CONFIGURATION, sizeof(MMC_GET_CONFIGURATION)); - c.oplen = sizeof(MMC_GET_CONFIGURATION); -*/ - c.dxfer_len= *alloc_len; - c.retry = 1; - c.opcode[7] = (c.dxfer_len >> 8) & 0xff; - c.opcode[8] = c.dxfer_len & 0xff; - c.page = &buf; - c.page->sectors = 0; - c.page->bytes = 0; - c.dir = FROM_DRIVE; - d->issue_command(d, &c); - - if (c.error) - return 0; - old_alloc_len = *alloc_len; - *alloc_len = len = mmc_four_char_to_int(c.page->data); - if (len > old_alloc_len) - len = old_alloc_len; - if (len < 8 || len > 4096) - return 0; - cp = (c.page->data[6]<<8) | c.page->data[7]; - -#ifdef Libburn_rom_as_profilE - if (cp == 0x08 || cp == 0x10 || cp==0x40) - cp = Libburn_rom_as_profilE; -#endif /* Libburn_rom_as_profilE */ - - d->current_profile = cp; - strcpy(d->current_profile_text, mmc_obtain_profile_name(cp)); - - /* Read-only supported media */ - - if (cp == 0x08) /* CD-ROM */ - d->current_is_supported_profile = d->current_is_cd_profile = 1; - if (cp == 0x10) /* DVD-ROM */ - d->current_is_supported_profile = 1; - if (cp == 0x40) /* BD-ROM */ - d->current_is_supported_profile = 1; - -#ifdef Libburn_support_bd_r_readonlY - if (cp == 0x41 || cp == 0x42) /* BD-R sequential, BD-R random */ - d->current_is_supported_profile = 1; -#endif - - - /* Write supported media (they get declared suitable in - burn_disc_get_multi_caps) */ - - if (cp == 0x09 || cp == 0x0a) - d->current_is_supported_profile = d->current_is_cd_profile = 1; - -#ifdef Libburn_support_dvd_plus_rW - if (cp == 0x1a) - d->current_is_supported_profile = 1; -#endif -#ifdef Libburn_support_dvd_minusrw_overW - if (cp == 0x13) - d->current_is_supported_profile = 1; -#endif -#ifdef Libburn_support_dvd_raM - if (cp == 0x12 || cp == 0x43) { /* DVD-RAM , BD-RE */ - d->current_is_supported_profile = 1; - -#ifdef Libburn_dvd_ram_as_bd_rE - cp = d->current_profile = 0x43; - strcpy(d->current_profile_text, mmc_obtain_profile_name(cp)); -#endif - - } -#endif -#ifdef Libburn_support_dvd_r_seQ - if (cp == 0x11 || cp == 0x14) /* DVD-R, DVD-RW */ - d->current_is_supported_profile = 1; - if (cp == 0x15) /* DVD-R/DL . */ - /* Writeable only if burn_support_untested_profiles */ - d->current_is_supported_profile = 1; -#endif -#ifdef Libburn_support_dvd_plus_R - if (cp == 0x1b || cp == 0x2b) /* DVD+R , DVD+R/DL */ - d->current_is_supported_profile = 1; -#endif - -/* Enable this to get loud and repeated reports about the feature set : -#define Libburn_print_feature_descriptorS 1 -*/ - /* ts A70127 : Interpret list of profile and feature descriptors. - see mmc5r03c.pdf 5.2 - >>> Ouch: What to do if list is larger than buffer size. - Specs state that the call has to be repeated. - */ - up_to = c.page->data + (len < BUFFER_SIZE ? len : BUFFER_SIZE); - -#ifdef Libburn_print_feature_descriptorS - fprintf(stderr, - "-----------------------------------------------------------------\n"); - fprintf(stderr, - "LIBBURN_EXPERIMENTAL : feature list length = %d , shown = %d\n", - len, up_to - c.page->data); -#endif /* Libburn_print_feature_descriptorS */ - - for (descr = c.page->data + 8; descr + 3 < up_to; descr += descr_len) { - descr_len = 4 + descr[3]; - feature_code = (descr[0] << 8) | descr[1]; - if (only_current && !(descr[2] & 1)) - continue; - -#ifdef Libburn_print_feature_descriptorS - fprintf(stderr, - "LIBBURN_EXPERIMENTAL : %s feature %4.4Xh\n", - descr[2] & 1 ? "+" : "-", - feature_code); -#endif /* Libburn_print_feature_descriptorS */ - - if (feature_code == 0x0) { - prf_end = descr + 4 + descr[3]; - for (prf = descr + 4; prf + 2 < prf_end; prf += 4) { - if (only_current && !(prf[2] & 1)) - continue; - prf_number = (prf[0] << 8) | prf[1]; - -#ifdef Libburn_print_feature_descriptorS - fprintf(stderr, - "LIBBURN_EXPERIMENTAL : %s profile %4.4Xh \"%s\"\n", - prf[2] & 1 ? "+" : "-", - prf_number, - mmc_obtain_profile_name(prf_number)); -#endif /* Libburn_print_feature_descriptorS */ - - } - - } else if (feature_code == 0x21) { - int i; - - d->current_has_feat21h = (descr[2] & 1); - for (i = 0; i < descr[7]; i++) { - if (i == 0 || descr[8 + i] == 16) - d->current_feat21h_link_size = - descr[8 + i]; - -#ifdef Libburn_print_feature_descriptorS - fprintf(stderr, - "LIBBURN_EXPERIMENTAL : + Link Size = %d\n", - descr[8 + i]); -#endif /* Libburn_print_feature_descriptorS */ - - } - - } else if (feature_code == 0x2F) { - if (descr[2] & 1) - d->current_feat2fh_byte4 = descr[4]; - -#ifdef Libburn_print_feature_descriptorS - fprintf(stderr, "LIBBURN_EXPERIMENTAL : BUF = %d , Test Write = %d , DVD-RW = %d\n", - !!(descr[4] & 64), !!(descr[4] & 4), - !!(descr[4] & 2)); -#endif /* Libburn_print_feature_descriptorS */ - - } else if (feature_code == 0x01) { - phys_if_std = (descr[4] << 24) | (descr[5] << 16) | - (descr[6] << 8) | descr[9]; - if (phys_if_std == 1) - phys_name = "SCSI Family"; - else if(phys_if_std == 2) - phys_name = "ATAPI"; - else if(phys_if_std == 3 || phys_if_std == 4 || - phys_if_std == 6) - phys_name = "IEEE 1394 FireWire"; - else if(phys_if_std == 7) - phys_name = "Serial ATAPI"; - else if(phys_if_std == 8) - phys_name = "USB"; - - d->phys_if_std = phys_if_std; - strcpy(d->phys_if_name, phys_name); - -#ifdef Libburn_print_feature_descriptorS - - fprintf(stderr, - "LIBBURN_EXPERIMENTAL : Phys. Interface Standard %Xh \"%s\"\n", - phys_if_std, phys_name); - - } else if (feature_code == 0x107) { - - fprintf(stderr, "LIBBURN_EXPERIMENTAL : CD SPEED = %d , page 2Ah = %d , SET STREAMING = %d\n", - !!(descr[4] & 8), !!(descr[4] & 4), - !!(descr[4] & 2)); - - } else if (feature_code == 0x108 || feature_code == 0x10c) { - int i, c_limit; - - fprintf(stderr, "LIBBURN_EXPERIMENTAL : %s = ", - feature_code == 0x108 ? - "Drive Serial Number" : "Drive Firmware Date"); - c_limit = descr[3] - 2 * (feature_code == 0x10c); - for (i = 0; i < c_limit; i++) - if (descr[4 + i] < 0x20 || descr[4 + i] > 0x7e - || descr[4 + i] == '\\') - fprintf(stderr,"\\%2.2X",descr[4 + i]); - else - fprintf(stderr, "%c", descr[4 + i]); - fprintf(stderr, "\n"); - -#endif /* Libburn_print_feature_descriptorS */ - - } - } - return 1; -} - - -void mmc_get_configuration(struct burn_drive *d) -{ - int alloc_len = 8, ret; - - if (mmc_function_spy(d, "mmc_get_configuration") <= 0) - return; - - /* first command execution to learn Allocation Length */ - ret = mmc_get_configuration_al(d, &alloc_len); -/* - fprintf(stderr,"LIBBURN_DEBUG: 46h alloc_len = %d , ret = %d\n", - alloc_len, ret); -*/ - if (alloc_len > 8 && ret > 0) - /* second execution with announced length */ - mmc_get_configuration_al(d, &alloc_len); -} - - -/* ts A70108 */ -/* mmc5r03c.pdf 6.24 */ -static int mmc_read_format_capacities_al(struct burn_drive *d, - int *alloc_len, int top_wanted) -{ - struct buffer buf; - int len, type, score, num_descr, max_score = -2000000000, i, sign = 1; - int old_alloc_len; - off_t size, num_blocks; - struct command c; - unsigned char *dpt; -/* <<< - char msg[160]; -*/ - - if (*alloc_len < 4) - return 0; - - d->format_descr_type = 3; - d->format_curr_max_size = 0; - d->format_curr_blsas = 0; - d->best_format_type = -1; - d->best_format_size = 0; - - scsi_init_command(&c, MMC_READ_FORMAT_CAPACITIES, - sizeof(MMC_READ_FORMAT_CAPACITIES)); -/* - memcpy(c.opcode, MMC_READ_FORMAT_CAPACITIES, - sizeof(MMC_READ_FORMAT_CAPACITIES)); - c.oplen = sizeof(MMC_READ_FORMAT_CAPACITIES); -*/ - c.dxfer_len = *alloc_len; - c.retry = 1; - c.opcode[7]= (c.dxfer_len >> 8) & 0xff; - c.opcode[8]= c.dxfer_len & 0xff; - c.page = &buf; - c.page->sectors = 0; - c.page->bytes = 0; - c.dir = FROM_DRIVE; - - d->issue_command(d, &c); - if (c.error) - return 0; - - len = c.page->data[3]; - old_alloc_len = *alloc_len; - *alloc_len = len + 4; - if (old_alloc_len < 12) - return 1; - if (len + 4 > old_alloc_len) - len = old_alloc_len - 4; - if (len < 8) - return 0; - - dpt = c.page->data + 4; - /* decode 6.24.3.2 Current/Maximum Capacity Descriptor */ - d->format_descr_type = dpt[4] & 3; - d->format_curr_max_size = (((off_t) dpt[0]) << 24) - + (dpt[1] << 16) + (dpt[2] << 8) + dpt[3]; - if (d->format_descr_type == BURN_FORMAT_IS_UNKNOWN) - d->format_curr_max_size = 0; - d->format_curr_blsas = (dpt[5] << 16) + (dpt[6] << 8) + dpt[7]; - -/* <<< - sprintf(msg, - "Current/Maximum Capacity Descriptor : type = %d : %.f", - d->format_descr_type, (double) d->format_curr_max_size); - libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - msg, 0, 0); -*/ - - d->format_curr_max_size *= (off_t) 2048; - if((d->current_profile == 0x12 || d->current_profile == 0x43) - && d->media_capacity_remaining == 0) { - burn_drive_set_media_capacity_remaining(d, - d->format_curr_max_size); - d->media_lba_limit = d->format_curr_max_size / 2048; - } - - -#ifdef Libburn_dvd_ram_as_bd_rE - /* <<< dummy format descriptor list as obtained from - dvd+rw-mediainfo by Giulio Orsero in April 2008 - */ - d->num_format_descr = 5; - d->format_descriptors[0].type = 0x00; - d->format_descriptors[0].size = (off_t) 11826176 * (off_t) 2048; - d->format_descriptors[0].tdp = 0x3000; - d->format_descriptors[1].type = 0x30; - d->format_descriptors[1].size = (off_t) 11826176 * (off_t) 2048; - d->format_descriptors[1].tdp = 0x3000; - d->format_descriptors[2].type = 0x30; - d->format_descriptors[2].size = (off_t) 11564032 * (off_t) 2048; - d->format_descriptors[2].tdp = 0x5000; - d->format_descriptors[3].type = 0x30; - d->format_descriptors[3].size = (off_t) 12088320 * (off_t) 2048; - d->format_descriptors[3].tdp = 0x1000; - d->format_descriptors[4].type = 0x31; - d->format_descriptors[4].size = (off_t) 12219392 * (off_t) 2048; - d->format_descriptors[4].tdp = 0x800; - d->best_format_type = 0x00; - d->best_format_size = (off_t) 11826176 * (off_t) 2048; - - /* silencing compiler warnings about unused variables */ - num_blocks = size = sign = i = max_score = num_descr = score = type = 0; - - if (d->current_profile == 0x12 || d->current_profile == 0x43) - return 1; - d->num_format_descr = 0; - -#endif /* Libburn_dvd_ram_as_bd_rE */ - - if (top_wanted == 0x00 || top_wanted == 0x10) - sign = -1; /* the caller clearly desires full format */ - - /* 6.24.3.3 Formattable Capacity Descriptors */ - num_descr = (len - 8) / 8; - for (i = 0; i < num_descr; i++) { - dpt = c.page->data + 12 + 8 * i; - num_blocks = mmc_four_char_to_int(dpt); - size = num_blocks * (off_t) 2048; - type = dpt[4] >> 2; - - if (i < 32) { - d->format_descriptors[i].type = type; - d->format_descriptors[i].size = size; - d->format_descriptors[i].tdp = - (dpt[5] << 16) + (dpt[6] << 8) + dpt[7]; - d->num_format_descr = i + 1; - } - -/* <<< - sprintf(msg, "Capacity Descriptor %2.2Xh %.fs = %.1f MB",type, - ((double) size)/2048.0, ((double) size)/1024.0/1024.0); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - msg, 0, 0); -*/ - - /* Criterion is proximity to quick intermediate state */ - if (type == 0x00) { /* full format (with lead out) */ - score = 1 * sign; - } else if (type == 0x10) { /* DVD-RW full format */ - score = 10 * sign; - } else if(type == 0x13) { /* DVD-RW quick grow last session */ - score = 100 * sign; - } else if(type == 0x15) { /* DVD-RW Quick */ - score = 50 * sign; - if(d->current_profile == 0x13) { - burn_drive_set_media_capacity_remaining(d, - size); - d->media_lba_limit = num_blocks; - } - } else if(type == 0x26) { /* DVD+RW */ - score = 1 * sign; - burn_drive_set_media_capacity_remaining(d, size); - d->media_lba_limit = num_blocks; - } else { - continue; - } - if (type == top_wanted) - score += 1000000000; - if (score > max_score) { - d->best_format_type = type; - d->best_format_size = size; - max_score = score; - } - } - -/* <<< - sprintf(msg, - "best_format_type = %2.2Xh , best_format_size = %.f", - d->best_format_type, (double) d->best_format_size); - libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - msg, 0, 0); -*/ - - return 1; -} - - -int mmc_read_format_capacities(struct burn_drive *d, int top_wanted) -{ - int alloc_len = 4, ret; - - if (mmc_function_spy(d, "mmc_read_format_capacities") <= 0) - return 0; - - ret = mmc_read_format_capacities_al(d, &alloc_len, top_wanted); -/* - fprintf(stderr,"LIBBURN_DEBUG: 23h alloc_len = %d , ret = %d\n", - alloc_len, ret); -*/ - if (alloc_len >= 12 && ret > 0) - ret = mmc_read_format_capacities_al(d, &alloc_len, top_wanted); - - return ret; -} - - -void mmc_sync_cache(struct burn_drive *d) -{ - struct command c; - - if (mmc_function_spy(d, "mmc_sync_cache") <= 0) - return; - - scsi_init_command(&c, MMC_SYNC_CACHE, sizeof(MMC_SYNC_CACHE)); -/* - memcpy(c.opcode, MMC_SYNC_CACHE, sizeof(MMC_SYNC_CACHE)); - c.oplen = sizeof(MMC_SYNC_CACHE); -*/ - c.retry = 1; - - c.opcode[1] |= 2; /* ts A70918 : Immed */ - - c.page = NULL; - c.dir = NO_TRANSFER; - - libdax_msgs_submit(libdax_messenger, -1, 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - "syncing cache", 0, 0); - if(d->wait_for_buffer_free) { - char msg[80]; - - sprintf(msg, - "Checked buffer %u times. Waited %u+%u times = %.3f s", - d->pessimistic_writes, d->waited_writes, - d->waited_tries - d->waited_writes, - ((double) d->waited_usec) / 1.0e6); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x0002013f, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_LOW, - msg, 0,0); - } - - d->issue_command(d, &c); - - /* ts A70918 */ - if (c.error) { - d->cancel = 1; - return; - } - if (spc_wait_unit_attention(d, 3600, "SYNCHRONIZE CACHE", 0) <= 0) - d->cancel = 1; - else - d->needs_sync_cache = 0; -} - - -/* ts A61023 : http://libburn.pykix.org/ticket/14 - get size and free space of drive buffer -*/ -int mmc_read_buffer_capacity(struct burn_drive *d) -{ - struct buffer buf; - struct command c; - unsigned char *data; - int alloc_len = 12; - - if (mmc_function_spy(d, "mmc_read_buffer_capacity") <= 0) - return 0; - - scsi_init_command(&c, MMC_READ_BUFFER_CAPACITY, - sizeof(MMC_READ_BUFFER_CAPACITY)); -/* - memcpy(c.opcode, MMC_READ_BUFFER_CAPACITY, - sizeof(MMC_READ_BUFFER_CAPACITY)); - c.oplen = sizeof(MMC_READ_BUFFER_CAPACITY); -*/ - c.dxfer_len = alloc_len; - c.opcode[7] = (c.dxfer_len >> 8) & 0xff; - c.opcode[8] = c.dxfer_len & 0xff; - c.retry = 1; - c.page = &buf; - memset(c.page->data, 0, alloc_len); - c.page->bytes = 0; - c.page->sectors = 0; - - c.dir = FROM_DRIVE; - d->issue_command(d, &c); - - /* >>> ??? error diagnostics */ - if (c.error) - return 0; - - data = c.page->data; - - d->progress.buffer_capacity = - (data[4]<<24)|(data[5]<<16)|(data[6]<<8)|data[7]; - d->progress.buffer_available = - (data[8]<<24)|(data[9]<<16)|(data[10]<<8)|data[11]; - d->pessimistic_buffer_free = d->progress.buffer_available; - d->pbf_altered = 0; - if (d->progress.buffered_bytes >= d->progress.buffer_capacity){ - double fill; - - fill = d->progress.buffer_capacity - - d->progress.buffer_available; - if (fill < d->progress.buffer_min_fill && fill>=0) - d->progress.buffer_min_fill = fill; - } - return 1; -} - - -/* ts A61219 : learned much from dvd+rw-tools-7.0: plus_rw_format() - and mmc5r03c.pdf, 6.5 FORMAT UNIT */ -/* - @param size The size (in bytes) to be sent with the FORMAT comand - @param flag bit1+2: size mode - 0 = use parameter size as far as it makes sense - 1 = insist in size 0 even if there is a better default known - 2 = without bit7: format to maximum available size - with bit7 : take size from indexed format descriptor - 3 = format to default size - bit3= expand format up to at least size - bit4= enforce re-format of (partly) formatted media - bit5= try to disable eventual defect management - bit6= try to avoid lengthy media certification - bit7= bit8 to bit15 contain the index of the format to use - bit8-bit15 = see bit7 -*/ -int mmc_format_unit(struct burn_drive *d, off_t size, int flag) -{ - struct buffer buf; - struct command c; - int ret, tolerate_failure = 0, return_immediately = 0, i, format_type; - int index, format_sub_type = 0, format_00_index, size_mode; - int accept_count = 0; - off_t num_of_blocks = 0, diff, format_size, i_size, format_00_max_size; - char msg[160],descr[80]; - int full_format_type = 0x00; /* Full Format (or 0x10 for DVD-RW ?) */ - - if (mmc_function_spy(d, "mmc_format_unit") <= 0) - return 0; - size_mode = (flag >> 1) & 3; - - scsi_init_command(&c, MMC_FORMAT_UNIT, sizeof(MMC_FORMAT_UNIT)); -/* - c.oplen = sizeof(MMC_FORMAT_UNIT); - memcpy(c.opcode, MMC_FORMAT_UNIT, sizeof(MMC_FORMAT_UNIT)); -*/ - c.retry = 1; - c.page = &buf; - c.page->bytes = 12; - c.page->sectors = 0; - c.dir = TO_DRIVE; - memset(c.page->data, 0, c.page->bytes); - - descr[0] = 0; - c.page->data[1] = 0x02; /* Immed */ - c.page->data[3] = 8; /* Format descriptor length */ - num_of_blocks = size / 2048; - mmc_int_to_four_char(c.page->data + 4, num_of_blocks); - - if (flag & 128) { /* explicitely chosen format descriptor */ - /* use case: the app knows what to do */ - - ret = mmc_read_format_capacities(d, -1); - if (ret <= 0) - goto selected_not_suitable; - index = (flag >> 8) & 0xff; - if(index < 0 || index >= d->num_format_descr) { -selected_not_suitable:; - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020132, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Selected format is not suitable for libburn", - 0, 0); - return 0; - } - if (!(d->current_profile == 0x13 || - d->current_profile == 0x14 || - d->current_profile == 0x1a || - d->current_profile == 0x12 || - d->current_profile == 0x43)) - goto unsuitable_media; - - format_type = d->format_descriptors[index].type; - if (!(format_type == 0x00 || format_type == 0x01 || - format_type == 0x10 || - format_type == 0x11 || format_type == 0x13 || - format_type == 0x15 || format_type == 0x26 || - format_type == 0x30 || format_type == 0x31 )) - goto selected_not_suitable; - if (flag & 4) { - num_of_blocks = - d->format_descriptors[index].size / 2048; - mmc_int_to_four_char(c.page->data + 4, num_of_blocks); - } - if (format_type != 0x26) - for (i = 0; i < 3; i++) - c.page->data[9 + i] = - ( d->format_descriptors[index].tdp >> - (16 - 8 * i)) & 0xff; - if (format_type == 0x30 || format_type == 0x31) { - if (flag & 64) - format_sub_type = 3; /* Quick certification */ - else - format_sub_type = 2; /* Full certification */ - } - if (d->current_profile == 0x12 && format_type !=0x01 && - (flag & 64)) { - /* DCRT and CmpList, see below */ - c.page->data[1] |= 0x20; - c.opcode[1] |= 0x08; - } - c.page->data[1] |= 0x80; /* FOV = this flag vector is valid */ - sprintf(descr, "%s (descr %d)", d->current_profile_text,index); - return_immediately = 1; /* caller must do the waiting */ - - } else if (d->current_profile == 0x1a) { /* DVD+RW */ - /* use case: background formatting during write !(flag&4) - de-icing as explicit formatting action (flag&4) - */ - - /* mmc5r03c.pdf , 6.5.4.2.14, DVD+RW Basic Format */ - format_type = 0x26; - - /* >>> ??? is this "| 8" a bug ? */ - - if ((size <= 0 && !(flag & 2)) || (flag & (4 | 8))) { - /* maximum capacity */ - memset(c.page->data + 4, 0xff, 4); - num_of_blocks = 0xffffffff; - } - - if(d->bg_format_status == 2 || - (d->bg_format_status == 3 && !(flag & 16))) { - sprintf(msg,"FORMAT UNIT ignored. Already %s.", - (d->bg_format_status == 2 ? "in progress" : - "completed")); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020120, - LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH, - msg, 0,0); - return 2; - } - if (!(flag & 16)) /* if not re-format is desired */ - if (d->bg_format_status == 1) /* is partly formatted */ - c.page->data[11] = 1; /* Restart bit */ - sprintf(descr, "DVD+RW (fs=%d,rs=%d)", - d->bg_format_status, (c.page->data[11] == 1)); - if (flag & 4) - return_immediately = 1;/* caller must do the waiting */ - - } else if (d->current_profile == 0x13 && !(flag & 16)) { - /*DVD-RW restricted overwrite*/ - /* use case: quick grow formatting during write */ - - ret = mmc_read_format_capacities(d, 0x13); - if (ret > 0) { - if (d->best_format_type == 0x13) { - if (d->best_format_size <= 0) - return 1; - } else { - if (d->format_descr_type == 2) /* formatted */ - return 1; - if (d->format_descr_type == 3){/*intermediate*/ - d->needs_close_session = 1; - return 1; - } - /* does trying make sense at all ? */ - tolerate_failure = 1; - } - } - if (d->best_format_type == 0x13 && (flag & (4 | 8))) { - num_of_blocks = d->best_format_size / 2048; - if (flag & 8) { - /* num_of_blocks needed to reach size */ - diff = (size - d->format_curr_max_size) /32768; - if ((size - d->format_curr_max_size) % 32768) - diff++; - diff *= 16; - if (diff < num_of_blocks) - num_of_blocks = diff; - } - if (num_of_blocks > 0) - mmc_int_to_four_char(c.page->data + 4, - num_of_blocks); - } - /* 6.5.4.2.8 , DVD-RW Quick Grow Last Border */ - format_type = 0x13; - c.page->data[11] = 16; /* block size * 2k */ - sprintf(descr, "DVD-RW quick grow"); - - } else if (d->current_profile == 0x14 || - (d->current_profile == 0x13 && (flag & 16))) { - /* DVD-RW sequential recording (or Overwrite for re-format) */ - /* use case : transition from Sequential to Overwrite - re-formatting of Overwrite media */ - - /* To Restricted Overwrite */ - /* 6.5.4.2.10 Format Type = 15h (DVD-RW Quick) */ - /* or 6.5.4.2.1 Format Type = 00h (Full Format) */ - /* or 6.5.4.2.5 Format Type = 10h (DVD-RW Full Format) */ - mmc_read_format_capacities(d, - (flag & 4) ? full_format_type : 0x15); - if (d->best_format_type == 0x15 || - d->best_format_type == full_format_type) { - if ((flag & 4) - || d->best_format_type == full_format_type) { - num_of_blocks = d->best_format_size / 2048; - mmc_int_to_four_char(c.page->data + 4, - num_of_blocks); - } - - } else { -no_suitable_formatting_type:; - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020131, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "No suitable formatting type offered by drive", - 0, 0); - return 0; - } - format_type = d->best_format_type; - c.page->data[11] = 16; /* block size * 2k */ - sprintf(descr, "DVD-RW %s", - format_type == 0x15 ? "quick" : "full"); - return_immediately = 1; /* caller must do the waiting */ - - } else if (d->current_profile == 0x12) { - /* ts A80417 : DVD-RAM */ - /* 6.5.4.2.1 Format Type = 00h (Full Format) - 6.5.4.2.2 Format Type = 01h (Spare Area Expansion) - */ - index = format_00_index = -1; - format_size = format_00_max_size = -1; - for (i = 0; i < d->num_format_descr; i++) { - format_type = d->format_descriptors[i].type; - i_size = d->format_descriptors[i].size; - if (format_type != 0x00 && format_type != 0x01) - continue; - if (flag & 32) { /* No defect mgt */ - /* Search for largest 0x00 format descriptor */ - if (format_type != 0x00) - continue; - if (i_size < format_size) - continue; - format_size = i_size; - index = i; - continue; - } else if (flag & 4) { /*Max or default size with mgt*/ - /* Search for second largest 0x00 - format descriptor. For max size allow - format type 0x01. - */ - if (format_type == 0x00) { - if (i_size < format_size) - continue; - if (i_size < format_00_max_size) { - format_size = i_size; - index = i; - continue; - } - format_size = format_00_max_size; - index = format_00_index; - format_00_max_size = i_size; - format_00_index = i; - continue; - } - if (size_mode==3) - continue; - if (i_size > format_size) { - format_size = i_size; - index = i; - } - continue; - } - /* Search for smallest 0x0 or 0x01 - descriptor >= size */; - if (d->format_descriptors[i].size >= size && - (format_size < 0 || i_size < format_size) - ) { - format_size = i_size; - index = i; - } - } - if(index < 0 && (flag & 4) && !(flag & 32)) { - format_size = format_00_max_size; - index = format_00_index; - } - if(index < 0) - goto no_suitable_formatting_type; - format_type = d->format_descriptors[index].type; - num_of_blocks = d->format_descriptors[index].size / 2048; - mmc_int_to_four_char(c.page->data + 4, num_of_blocks); - for (i = 0; i < 3; i++) - c.page->data[9 + i] = - ( d->format_descriptors[index].tdp >> - (16 - 8 * i)) & 0xff; - sprintf(descr, "%s", d->current_profile_text); - return_immediately = 1; /* caller must do the waiting */ - c.page->data[1] |= 0x80; /* FOV = this flag vector is valid */ - - if ((flag & 64) && format_type != 0x01) { - /* MMC-5 6.5.3.2 , 6.5.4.2.1.2 - DCRT: Disable Certification and maintain number - of blocks - CmpList: Override maintaining of number of blocks - with DCRT - */ - /* ts A80426 : prevents change of formatted size - with PHILIPS SPD3300L and Verbatim 3x DVD-RAM - and format_type 0x00. Works on TSSTcorp SH-S203B - */ - c.page->data[1] |= 0x20; - c.opcode[1] |= 0x08; - } - - } else if (d->current_profile == 0x43) { - /* BD-RE */ - index = -1; - format_size = -1; - if (d->num_format_descr <= 0) - goto no_suitable_formatting_type; - if (d->format_descriptors[0].type != 0) - goto no_suitable_formatting_type; - for (i = 0; i < d->num_format_descr; i++) { - format_type = d->format_descriptors[i].type; - i_size = d->format_descriptors[i].size; - if (format_type != 0x00 && format_type != 0x30 && - format_type != 0x31) - continue; - if (flag & 32) { /* No defect mgt */ - /* search largest format 0x31 */ - if(format_type != 0x31) - continue; - } else if(size_mode == 2) { /* max payload size */ - /* search largest 0x30 format descriptor */ - if(format_type != 0x30) - continue; - } else if(size_mode == 3) { /* default payload size */ - if (accept_count < 1) - index = 0; /* this cannot certify */ - if(format_type != 0x30) - continue; - accept_count++; - if (accept_count == 1) - index = i; - continue; - } else { /* defect managed format with size wish */ - /* search for smallest 0x30 >= size */ - if(format_type != 0x30) - continue; - if (i_size < size) - continue; - if (format_size >= 0 && i_size >= format_size) - continue; - index = i; - format_size = i_size; - continue; - } - /* common for all cases which search largest - descriptors */ - if (i_size > format_size) { - format_size = i_size; - index = i; - } - } - if (size_mode == 2 && index < 0 && !(flag & 32)) - index = 0; - if (index < 0) - goto no_suitable_formatting_type; - format_type = d->format_descriptors[index].type; - if (format_type == 0x30 || format_type == 0x31) { - if (flag & 64) - format_sub_type = 3; /* Quick certification */ - else - format_sub_type = 2; /* Full certification */ - } - num_of_blocks = d->format_descriptors[index].size / 2048; - mmc_int_to_four_char(c.page->data + 4, num_of_blocks); - for (i = 0; i < 3; i++) - c.page->data[9 + i] = - ( d->format_descriptors[index].tdp >> - (16 - 8 * i)) & 0xff; - sprintf(descr, "%s", d->current_profile_text); - return_immediately = 1; /* caller must do the waiting */ - c.page->data[1] |= 0x80; /* FOV = this flag vector is valid */ - - } else { - - /* >>> other formattable types to come */ - -unsuitable_media:; - sprintf(msg, "Unsuitable media detected. Profile %4.4Xh %s", - d->current_profile, d->current_profile_text); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x0002011e, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - return 0; - } - c.page->data[8] = (format_type << 2) | (format_sub_type & 3); - - sprintf(msg, "Format type %2.2Xh \"%s\", blocks = %.f", - format_type, descr, (double) num_of_blocks); - libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - msg, 0, 0); - sprintf(msg, "CDB: "); - for (i = 0; i < 6; i++) - sprintf(msg + strlen(msg), "%2.2X ", c.opcode[i]); - libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - msg, 0, 0); - sprintf(msg, "Format list: "); - for (i = 0; i < 12; i++) - sprintf(msg + strlen(msg), "%2.2X ", c.page->data[i]); - strcat(msg, "\n"); - libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - msg, 0, 0); - -#ifdef Libburn_do_not_format_dvd_ram_or_bd_rE - if(d->current_profile == 0x43 || d->current_profile == 0x12) { - sprintf(msg, - "Formatting of %s not implemented yet - This is a dummy", - d->current_profile_text); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00000002, - LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_ZERO, - msg, 0, 0); - return 1; - } -#endif /* Libburn_do_not_format_dvd_ram_or_bd_rE */ - - d->issue_command(d, &c); - if (c.error && !tolerate_failure) { - if (c.sense[2]!=0) { - sprintf(msg, - "SCSI error on format_unit(%s): key=%X asc=%2.2Xh ascq=%2.2Xh", - descr, - c.sense[2],c.sense[12],c.sense[13]); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020122, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - } - return 0; - } else if ((!c.error) && (format_type == 0x13 || format_type == 0x15)) - d->needs_close_session = 1; - if (return_immediately) - return 1; - usleep(1000000); /* there seems to be a little race condition */ - for (ret = 0; ret <= 0 ;) { - usleep(50000); - ret = spc_test_unit_ready(d); - } - mmc_sync_cache(d); - return 1; -} - - -/* ts A61225 */ -static int mmc_get_write_performance_al(struct burn_drive *d, - int *alloc_len, int *max_descr) -{ - struct buffer buf; - int len, i, b, num_descr, ret, old_alloc_len; - int exact_bit, read_speed, write_speed; - /* if this call delivers usable data then they should override - previously recorded min/max speed and not compete with them */ - int min_write_speed = 0x7fffffff, max_write_speed = 0; - int min_read_speed = 0x7fffffff, max_read_speed = 0; - struct command c; - unsigned long end_lba; - unsigned char *pd; - struct burn_speed_descriptor *sd; - - /* A61225 : 1 = report about speed descriptors */ - static int speed_debug = 0; - - if (d->current_profile <= 0) - mmc_get_configuration(d); - - if (*alloc_len < 8) - return 0; - - scsi_init_command(&c, MMC_GET_PERFORMANCE, - sizeof(MMC_GET_PERFORMANCE)); -/* - memcpy(c.opcode, MMC_GET_PERFORMANCE, sizeof(MMC_GET_PERFORMANCE)); - c.oplen = sizeof(MMC_GET_PERFORMANCE); -*/ -/* ts A70519 : now controlled externally - max_descr = ( BUFFER_SIZE - 8 ) / 16 - 1; -*/ - - /* >>> future: maintain a list of write descriptors - if (max_descr > d->max_write_descr - d->num_write_descr) - max_descr = d->max_write_descr; - */ - c.dxfer_len = *alloc_len; - - c.opcode[8] = ( *max_descr >> 8 ) & 0xff; - c.opcode[9] = ( *max_descr >> 0 ) & 0xff; - c.opcode[10] = 3; - c.retry = 1; - c.page = &buf; - c.page->sectors = 0; - c.page->bytes = 0; - c.dir = FROM_DRIVE; - d->issue_command(d, &c); - if (c.error) - return 0; - len = mmc_four_char_to_int(c.page->data); - old_alloc_len = *alloc_len; - *alloc_len = len + 4; - if (len + 4 > old_alloc_len) - len = old_alloc_len - 4; - num_descr = ( *alloc_len - 8 ) / 16; - if (*max_descr == 0) { - *max_descr = num_descr; - return 1; - } - if (old_alloc_len < 16) - return 1; - if (len < 12) - return 0; - - pd = c.page->data; - if (num_descr > *max_descr) - num_descr = *max_descr; - for (i = 0; i < num_descr; i++) { - exact_bit = !!(pd[8 + i*16] & 2); - end_lba = read_speed = write_speed = 0; - for (b = 0; b < 4 ; b++) { - end_lba += pd[8 + i*16 + 4 + b] << (24 - 8 * b); - read_speed += pd[8 + i*16 + 8 + b] << (24 - 8 * b); - write_speed += pd[8 + i*16 + 12 + b] << (24 - 8 * b); - } - if (end_lba > 0x7ffffffe) - end_lba = 0x7ffffffe; - - if (speed_debug) - fprintf(stderr, - "LIBBURN_DEBUG: kB/s: write=%d read=%d end=%lu exact=%d\n", - write_speed, read_speed, end_lba, exact_bit); - - /* ts A61226 */ - ret = burn_speed_descriptor_new(&(d->mdata->speed_descriptors), - NULL, d->mdata->speed_descriptors, 0); - if (ret > 0) { - sd = d->mdata->speed_descriptors; - sd->source = 2; - if (d->current_profile > 0) { - sd->profile_loaded = d->current_profile; - strcpy(sd->profile_name, - d->current_profile_text); - } - sd->wrc = (pd[8 + i*16] >> 3 ) & 3; - sd->exact = exact_bit; - sd->mrw = pd[8 + i*16] & 1; - sd->end_lba = end_lba; - sd->write_speed = write_speed; - sd->read_speed = read_speed; - } - - if (end_lba > d->mdata->max_end_lba) - d->mdata->max_end_lba = end_lba; - if (end_lba < d->mdata->min_end_lba) - d->mdata->min_end_lba = end_lba; - if (write_speed < min_write_speed) - min_write_speed = write_speed; - if (write_speed > max_write_speed) - max_write_speed = write_speed; - if (read_speed < min_read_speed) - min_read_speed = read_speed; - if (read_speed > max_read_speed) - max_read_speed = read_speed; - } - if (min_write_speed < 0x7fffffff) - d->mdata->min_write_speed = min_write_speed; - if (max_write_speed > 0) - d->mdata->max_write_speed = max_write_speed; - /* there is no mdata->min_read_speed yet - if (min_read_speed < 0x7fffffff) - d->mdata->min_read_speed = min_read_speed; - */ - if (max_read_speed > 0) - d->mdata->max_read_speed = max_read_speed; - return num_descr; -} - - -int mmc_get_write_performance(struct burn_drive *d) -{ - int alloc_len = 8, max_descr = 0, ret; - - if (mmc_function_spy(d, "mmc_get_write_performance") <= 0) - return 0; - - /* first command execution to learn number of descriptors and - dxfer_len */ - ret = mmc_get_write_performance_al(d, &alloc_len, &max_descr); -/* - fprintf(stderr,"LIBBURN_DEBUG: ACh alloc_len = %d , ret = %d\n", - alloc_len, ret); -*/ - if (max_descr > 0 && ret > 0) - /* second execution with announced length */ - ret = mmc_get_write_performance_al(d, &alloc_len, &max_descr); - return ret; -} - - -/* ts A61229 : outsourced from spc_select_write_params() */ -/* Note: Page data is not zeroed here to allow preset defaults. Thus - memset(pd, 0, 2 + d->mdata->write_page_length); - is the eventual duty of the caller. -*/ -int mmc_compose_mode_page_5(struct burn_drive *d, - const struct burn_write_opts *o, - unsigned char *pd) -{ - pd[0] = 5; - pd[1] = d->mdata->write_page_length; - - if (d->current_profile == 0x13) { - /* A61229 : DVD-RW restricted overwrite */ - /* learned from transport.hxx : page05_setup() - and mmc3r10g.pdf table 347 */ - /* BUFE (burnproof), no LS_V (i.e. default Link Size, i hope), - no simulate, write type 0 = packet */ - pd[2] = (1 << 6); - /* no multi, fixed packet, track mode 5 */ - pd[3] = (1 << 5) | 5; - /* Data Block Type */ - pd[4] = 8; - /* Link size dummy */ - pd[5] = 0; - - } else if ((d->current_profile == 0x14 || d->current_profile == 0x11 || - d->current_profile == 0x15) - && o->write_type == BURN_WRITE_SAO) { - /* ts A70205 : DVD-R[W][/DL] : Disc-at-once, DAO */ - /* Learned from dvd+rw-tools and mmc5r03c.pdf . - See doc/cookbook.txt for more detailed references. */ - - /* BUFE , LS_V = 0, Test Write, Write Type = 2 SAO (DAO) */ - pd[2] = ((!!o->underrun_proof) << 6) - | ((!!o->simulate) << 4) - | 2; - /* No multi-session , FP = 0 , Track Mode = 5 */ - pd[3] = 5; - /* Data Block Type = 8 */ - pd[4] = 8; - - } else if (d->current_profile == 0x14 || d->current_profile == 0x11 || - d->current_profile == 0x15) { - /* ts A70128 : DVD-R[W][/DL] Incremental Streaming */ - /* Learned from transport.hxx : page05_setup() - and mmc5r03c.pdf 7.5, 4.2.3.4 Table 17 - and spc3r23.pdf 6.8, 7.4.3 */ - - /* BUFE , LS_V = 1, Test Write, - Write Type = 0 Packet/Incremental */ - pd[2] = ((!!o->underrun_proof) << 6) - | (1 << 5) - | ((!!o->simulate) << 4); - /* Multi-session , FP = 1 , Track Mode = 5 */ - pd[3] = ((3 * !!o->multi) << 6) | (1 << 5) | 5; - /* Data Block Type = 8 */ - pd[4] = 8; - /* Link Size */ - if (d->current_feat21h_link_size >= 0) - pd[5] = d->current_feat21h_link_size; - else - pd[5] = 16; - if (d->current_feat21h_link_size != 16) { - char msg[80]; - - sprintf(msg, - "Feature 21h Link Size = %d (expected 16)\n", - d->current_feat21h_link_size); - libdax_msgs_submit(libdax_messenger, -1, 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - msg, 0, 0); - } - /* Packet Size */ - pd[13] = 16; - - } else if (d->current_profile == 0x1a || d->current_profile == 0x1b || - d->current_profile == 0x2b || d->current_profile == 0x12 || - d->current_profile == 0x43) { - /* not with DVD+R[W][/DL] or DVD-RAM or BD-RE */; - return 0; - } else { - /* Traditional setup for CD */ - - pd[2] = ((!!o->underrun_proof) << 6) - | ((!!o->simulate) << 4) - | (o->write_type & 0x0f); - - /* ts A61106 : MMC-1 table 110 : multi==0 or multi==3 */ - pd[3] = ((3 * !!o->multi) << 6) | (o->control & 0x0f); - - pd[4] = spc_block_type(o->block_type); - - /* ts A61104 */ - if(!(o->control&4)) /* audio (MMC-1 table 61) */ - if(o->write_type == BURN_WRITE_TAO) - pd[4] = 0; /* Data Block Type: Raw Data */ - - pd[14] = 0; /* audio pause length MSB */ - pd[15] = 150; /* audio pause length LSB */ - -/*XXX need session format! */ -/* ts A61229 : but session format (pd[8]) = 0 seems ok */ - - } - return 1; -} - - -/* A70812 ts */ -int mmc_read_10(struct burn_drive *d, int start,int amount, struct buffer *buf) -{ - struct command c; - - if (mmc_function_spy(d, "mmc_read_10") <= 0) - return -1; -; - if (amount > BUFFER_SIZE / 2048) - return -1; - - scsi_init_command(&c, MMC_READ_10, sizeof(MMC_READ_10)); - c.dxfer_len = amount * 2048; - c.retry = 1; - mmc_int_to_four_char(c.opcode + 2, start); - c.opcode[7] = (amount >> 8) & 0xFF; - c.opcode[8] = amount & 0xFF; - c.page = buf; - c.page->bytes = 0; - c.page->sectors = 0; - c.dir = FROM_DRIVE; - d->issue_command(d, &c); - if (c.error) { - char msg[160]; - sprintf(msg, - "SCSI error on read_10(%d,%d): key=%X asc=%2.2Xh ascq=%2.2Xh", - start, amount, - c.sense[2],c.sense[12],c.sense[13]); - if(!d->silent_on_scsi_error) - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020144, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - return BE_CANCELLED; - } - - buf->sectors = amount; - buf->bytes = amount * 2048; - return 0; -} - - -/* ts A61021 : the mmc specific part of sg.c:enumerate_common() -*/ -int mmc_setup_drive(struct burn_drive *d) -{ - d->read_atip = mmc_read_atip; - d->read_toc = mmc_read_toc; - d->write = mmc_write; - d->erase = mmc_erase; - d->read_sectors = mmc_read_sectors; - d->perform_opc = mmc_perform_opc; - d->set_speed = mmc_set_speed; - d->send_cue_sheet = mmc_send_cue_sheet; - d->reserve_track = mmc_reserve_track; - d->sync_cache = mmc_sync_cache; - d->get_nwa = mmc_get_nwa; - d->read_multi_session_c1 = mmc_read_multi_session_c1; - d->close_disc = mmc_close_disc; - d->close_session = mmc_close_session; - d->close_track_session = mmc_close; - d->read_buffer_capacity = mmc_read_buffer_capacity; - d->format_unit = mmc_format_unit; - d->read_format_capacities = mmc_read_format_capacities; - d->read_10 = mmc_read_10; - - - /* ts A70302 */ - d->phys_if_std = -1; - d->phys_if_name[0] = 0; - - /* ts A61020 */ - d->start_lba = -2000000000; - d->end_lba = -2000000000; - - /* ts A61201 - A70223*/ - d->erasable = 0; - d->current_profile = -1; - d->current_profile_text[0] = 0; - d->current_is_cd_profile = 0; - d->current_is_supported_profile = 0; - d->current_has_feat21h = 0; - d->current_feat21h_link_size = -1; - d->current_feat2fh_byte4 = -1; - d->needs_close_session = 0; - d->needs_sync_cache = 0; - d->bg_format_status = -1; - d->num_format_descr = 0; - d->complete_sessions = 0; - d->last_track_no = 1; - d->media_capacity_remaining = 0; - d->media_lba_limit = 0; - d->pessimistic_buffer_free = 0; - d->pbf_altered = 0; - d->wait_for_buffer_free = Libburn_wait_for_buffer_freE; - d->nominal_write_speed = 0; - d->pessimistic_writes = 0; - d->waited_writes = 0; - d->waited_tries = 0; - d->waited_usec = 0; - d->wfb_min_usec = Libburn_wait_for_buffer_min_useC; - d->wfb_max_usec = Libburn_wait_for_buffer_max_useC; - d->wfb_timeout_sec = Libburn_wait_for_buffer_tio_seC; - d->wfb_min_percent = Libburn_wait_for_buffer_min_perC; - d->wfb_max_percent = Libburn_wait_for_buffer_max_perC; - - return 1; -} - - diff --git a/libburn/mmc.h b/libburn/mmc.h deleted file mode 100644 index 9b07597..0000000 --- a/libburn/mmc.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef __MMC -#define __MMC - -struct burn_drive; -struct burn_write_opts; -struct command; -struct buffer; -struct cue_sheet; - -/* MMC commands */ - -void mmc_read(struct burn_drive *); - -/* ts A61009 : removed redundant parameter d in favor of o->drive */ -/* void mmc_close_session(struct burn_drive *, struct burn_write_opts *); */ -/* void mmc_close_disc(struct burn_drive *, struct burn_write_opts *); */ -void mmc_close_session(struct burn_write_opts *o); -void mmc_close_disc(struct burn_write_opts *o); - -void mmc_close(struct burn_drive *, int session, int track); -void mmc_get_event(struct burn_drive *); -int mmc_write(struct burn_drive *, int start, struct buffer *buf); -void mmc_write_12(struct burn_drive *d, int start, struct buffer *buf); -void mmc_sync_cache(struct burn_drive *); -void mmc_load(struct burn_drive *); -void mmc_eject(struct burn_drive *); -void mmc_erase(struct burn_drive *, int); -void mmc_read_toc(struct burn_drive *); -void mmc_read_disc_info(struct burn_drive *); -void mmc_read_atip(struct burn_drive *); -void mmc_read_sectors(struct burn_drive *, - int, - int, const struct burn_read_opts *, struct buffer *); -void mmc_set_speed(struct burn_drive *, int, int); -void mmc_read_lead_in(struct burn_drive *, struct buffer *); -void mmc_perform_opc(struct burn_drive *); -void mmc_get_configuration(struct burn_drive *); - -/* ts A61110 : added parameters trackno, lba, nwa. Redefined return value. - @return 1=nwa is valid , 0=nwa is not valid , -1=error */ -int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa); - -void mmc_send_cue_sheet(struct burn_drive *, struct cue_sheet *); - -/* ts A61023 : get size and free space of drive buffer */ -int mmc_read_buffer_capacity(struct burn_drive *d); - -/* ts A61021 : the mmc specific part of sg.c:enumerate_common() -*/ -int mmc_setup_drive(struct burn_drive *d); - -/* ts A61219 : learned much from dvd+rw-tools-7.0: plus_rw_format() - and mmc5r03c.pdf, 6.5 FORMAT UNIT */ -int mmc_format_unit(struct burn_drive *d, off_t size, int flag); - -/* ts A61225 : obtain write speed descriptors via ACh GET PERFORMANCE */ -int mmc_get_write_performance(struct burn_drive *d); - - -/* ts A61229 : outsourced from spc_select_write_params() */ -/* Note: Page data is not zeroed here to allow preset defaults. Thus - memset(pd, 0, 2 + d->mdata->write_page_length); - is the eventual duty of the caller. -*/ -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 - -#endif /*__MMC*/ diff --git a/libburn/null.c b/libburn/null.c deleted file mode 100644 index 3840339..0000000 --- a/libburn/null.c +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#include "null.h" -#include "libburn.h" -#include <stdlib.h> - -#include <string.h> -int null_read(struct burn_source *source, unsigned char *buffer, int size) -{ - memset(buffer, 0, size); - return size; -} - -struct burn_source *burn_null_source_new(void) -{ - struct burn_source *src; - - src = malloc(sizeof(struct burn_source)); - src->refcount = 1; - src->read = null_read; - src->read_sub = NULL; - - src->get_size = 0; - - /* ts A70126 */ - src->set_size = NULL; - - src->free_data = NULL; - src->data = NULL; - return src; -} diff --git a/libburn/null.h b/libburn/null.h deleted file mode 100644 index 1a7aae3..0000000 --- a/libburn/null.h +++ /dev/null @@ -1,10 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef BURN__NULL_H -#define BURN__NULL_H - -struct burn_source; -int null_read(struct burn_source *source, unsigned char *buffer, int size); -struct burn_source *burn_null_source_new(void); - -#endif /* LIBBURN__NULL_H */ diff --git a/libburn/options.c b/libburn/options.c deleted file mode 100644 index 4b8cf45..0000000 --- a/libburn/options.c +++ /dev/null @@ -1,447 +0,0 @@ -#include "libburn.h" -#include "options.h" -#include "drive.h" -#include "transport.h" - -/* ts A61007 */ -/* #include <a ssert.h> */ - -#include <stdlib.h> -#include <string.h> - -#include "libdax_msgs.h" -extern struct libdax_msgs *libdax_messenger; - - -struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive) -{ - struct burn_write_opts *opts; - - opts = malloc(sizeof(struct burn_write_opts)); - if (opts == NULL) { - libdax_msgs_submit(libdax_messenger, -1, 0x00020111, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "Could not allocate new auxiliary object", 0, 0); - return NULL; - } - opts->drive = drive; - opts->refcount = 1; - opts->write_type = BURN_WRITE_TAO; - opts->block_type = BURN_BLOCK_MODE1; - opts->toc_entry = NULL; - opts->toc_entries = 0; - opts->simulate = 0; - opts->underrun_proof = drive->mdata->underrun_proof; - opts->perform_opc = 1; - opts->obs = -1; - opts->obs_pad = 0; - 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; - opts->control = 0; - return opts; -} - -void burn_write_opts_free(struct burn_write_opts *opts) -{ - if (--opts->refcount <= 0) - free(opts); -} - -struct burn_read_opts *burn_read_opts_new(struct burn_drive *drive) -{ - struct burn_read_opts *opts; - - opts = malloc(sizeof(struct burn_read_opts)); - opts->drive = drive; - opts->refcount = 1; - opts->raw = 0; - opts->c2errors = 0; - opts->subcodes_audio = 0; - opts->subcodes_data = 0; - opts->hardware_error_recovery = 0; - opts->report_recovered_errors = 0; - opts->transfer_damaged_blocks = 0; - opts->hardware_error_retries = 3; - - return opts; -} - -void burn_read_opts_free(struct burn_read_opts *opts) -{ - if (--opts->refcount <= 0) - free(opts); -} - -int burn_write_opts_set_write_type(struct burn_write_opts *opts, - enum burn_write_types write_type, - int block_type) -{ - int sector_get_outmode(enum burn_write_types write_type, - enum burn_block_types block_type); - int spc_block_type(enum burn_block_types b); - - /* ts A61007 */ - if (! ( (write_type == BURN_WRITE_SAO && block_type == BURN_BLOCK_SAO) - || (opts->drive->block_types[write_type] & block_type) ) ) { -bad_combination:; - libdax_msgs_submit(libdax_messenger, -1, 0x00020112, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Bad combination of write_type and block_type", 0, 0); - return 0; - } - /* ts A61007 : obsoleting Assert in sector.c:get_outmode() */ - if (sector_get_outmode(write_type, (enum burn_block_types) block_type) - == -1) - goto bad_combination; - /* ts A61007 : obsoleting Assert in spc.c:spc_block_type() */ - if (spc_block_type((enum burn_block_types) block_type) == -1) - goto bad_combination; - - opts->write_type = write_type; - opts->block_type = block_type; - return 1; - - /* a ssert(0); */ -} - -void burn_write_opts_set_toc_entries(struct burn_write_opts *opts, int count, - struct burn_toc_entry *toc_entries) -{ - opts->toc_entries = count; - opts->toc_entry = malloc(count * sizeof(struct burn_toc_entry)); - memcpy(opts->toc_entry, &toc_entries, - sizeof(struct burn_toc_entry) * count); -} - -void burn_write_opts_set_format(struct burn_write_opts *opts, int format) -{ - opts->format = format; -} - -int burn_write_opts_set_simulate(struct burn_write_opts *opts, int sim) -{ -/* <<< ts A70529 : - One cannot predict the ability to simulate from page 05h - information alone. This check is now done later in - function burn_write_opts_auto_write_type(). - - if (opts->drive->mdata->simulate) { - opts->simulate = sim; - return 1; - } - return 0; -*/ - opts->simulate = !!sim; - return 1; -} - -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; - } - return 0; -} - -void burn_write_opts_set_perform_opc(struct burn_write_opts *opts, int opc) -{ - opts->perform_opc = opc; -} - -void burn_write_opts_set_has_mediacatalog(struct burn_write_opts *opts, - int has_mediacatalog) -{ - opts->has_mediacatalog = has_mediacatalog; -} - -void burn_write_opts_set_mediacatalog(struct burn_write_opts *opts, - unsigned char mediacatalog[13]) -{ - memcpy(opts->mediacatalog, &mediacatalog, 13); -} - - -/* ts A61106 */ -void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi) -{ - opts->multi = !!multi; -} - - -/* ts A61222 */ -void burn_write_opts_set_start_byte(struct burn_write_opts *opts, off_t value) -{ - opts->start_byte = value; -} - - -/* ts A70207 API */ -/** @param flag Bitfield for control purposes: - bit0= do not choose type but check the one that is already set - bit1= do not issue error messages via burn_msgs queue -*/ -enum burn_write_types burn_write_opts_auto_write_type( - struct burn_write_opts *opts, struct burn_disc *disc, - char reasons[BURN_REASONS_LEN], int flag) -{ - struct burn_multi_caps *caps = NULL; - struct burn_drive *d = opts->drive; - struct burn_disc_mode_demands demands; - enum burn_write_types wt; - int ret, would_do_sao = 0; - char *reason_pt; - - reasons[0] = 0; - - if (d->status != BURN_DISC_BLANK && - d->status != BURN_DISC_APPENDABLE){ - if (d->status == BURN_DISC_FULL) - strcat(reasons, "MEDIA: closed or not recordable, "); - else - strcat(reasons,"MEDIA: no writeable media detected, "); - if (!(flag & 3)) - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x0002013a, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "No suitable media detected", 0, 0); - return BURN_WRITE_NONE; - } - ret = burn_disc_get_write_mode_demands(disc, opts, &demands, - !!opts->fill_up_media); - if (ret <= 0) { - strcat(reasons, "cannot recognize job demands, "); - {wt = BURN_WRITE_NONE; goto ex;} - } - if (demands.exotic_track && !d->current_is_cd_profile) { - if (demands.audio) - strcat(reasons, "audio track prohibited by non-CD, "); - else - strcat(reasons, "exotic track prohibited by non-CD, "); - {wt = BURN_WRITE_NONE; goto ex;} - } - if ((flag & 1) && opts->write_type != BURN_WRITE_SAO) - goto try_tao; - reason_pt = reasons + strlen(reasons); - strcat(reasons, "SAO: "); - if (d->status != BURN_DISC_BLANK) { - strcat(reasons, "write type SAO works only on blank media, "); - goto try_tao; - } - burn_disc_free_multi_caps(&caps); - ret = burn_disc_get_multi_caps(d, BURN_WRITE_SAO, &caps, 0); - if (ret < 0) { -no_caps:; - strcat(reasons, "cannot inquire write mode capabilities, "); - {wt = BURN_WRITE_NONE; goto ex;} - } else if (ret == 0) { - strcat(reasons, "no SAO offered by drive and media, "); - goto no_sao; - } - if ((opts->multi || demands.multi_session) && - !caps->multi_session) - strcat(reasons, "multi session capability lacking, "); - if (demands.will_append) - strcat(reasons, "appended session capability lacking, "); - if (demands.multi_track && !caps->multi_track) - strcat(reasons, "multi track capability lacking, "); - if (demands.unknown_track_size == 1 && - (caps->might_do_sao == 1 || caps->might_do_sao == 3)) - strcat(reasons, "track size unpredictable, "); - if (demands.mixed_mode) - strcat(reasons, "tracks of different modes mixed, "); - if (demands.exotic_track && !d->current_is_cd_profile) - strcat(reasons, "non-data track on non-cd, "); - else if (d->current_is_cd_profile) - if ((d->block_types[BURN_WRITE_TAO] & demands.block_types) != - demands.block_types) - strcat(reasons, "drive dislikes block type, "); - if (d->current_is_cd_profile && opts->fill_up_media) - strcat(reasons, "cd sao cannot do media fill up yet, "); - if (strcmp(reason_pt, "SAO: ") != 0) - goto no_sao; - would_do_sao = 1; - if (demands.unknown_track_size == 2 && (!(flag & 1)) && - (caps->might_do_sao == 1 || caps->might_do_sao == 3)) { - strcat(reasons, "would have to use default track sizes, "); - goto no_sao; - } else if (caps->might_do_sao >= 3 && !(flag & 1)) - goto try_tao; -do_sao:; - if (caps->might_simulate == 0 && opts->simulate && !opts->force_is_set) - goto no_simulate; - if (!(flag & 1)) - burn_write_opts_set_write_type( - opts, BURN_WRITE_SAO, BURN_BLOCK_SAO); - {wt = BURN_WRITE_SAO; goto ex;} -no_sao:; -try_tao:; - if ((flag & 1) && opts->write_type != BURN_WRITE_TAO) - goto try_raw; - reason_pt = reasons + strlen(reasons); - strcat(reasons, "TAO: "); - burn_disc_free_multi_caps(&caps); - ret = burn_disc_get_multi_caps(d, BURN_WRITE_TAO, &caps, 0); - if (ret < 0) - goto no_caps; - if (ret == 0) { - strcat(reasons, "no TAO offered by drive and media, "); - goto no_tao; - } - if ((opts->multi || demands.multi_session) && !caps->multi_session) - strcat(reasons, "multi session capability lacking, "); - if (demands.multi_track && !caps->multi_track) - strcat(reasons, "multi track capability lacking, "); - if (demands.exotic_track && !d->current_is_cd_profile) - strcat(reasons, "non-data track on non-cd, "); - if (d->current_is_cd_profile && !opts->force_is_set) - if ((d->block_types[BURN_WRITE_TAO] & demands.block_types) != - demands.block_types) - strcat(reasons, "drive dislikes block type, "); - if (strcmp(reason_pt, "TAO: ") != 0) - goto no_tao; - /* ( TAO data/audio block size will be handled automatically ) */ - if (caps->might_simulate == 0 && opts->simulate && !opts->force_is_set) - goto no_simulate; - if (!(flag & 1)) - burn_write_opts_set_write_type( - opts, BURN_WRITE_TAO, BURN_BLOCK_MODE1); - {wt = BURN_WRITE_TAO; goto ex;} -no_tao:; - if (would_do_sao && !(flag & 1)) - goto do_sao; - if (!d->current_is_cd_profile) - goto no_write_mode; -try_raw:; - if ((flag & 1) && opts->write_type != BURN_WRITE_RAW) - goto no_write_mode; - - if (!(flag & 1)) /* For now: no automatic raw write modes */ - goto no_write_mode; - - reason_pt = reasons + strlen(reasons); - strcat(reasons, "RAW: "); - if (!d->current_is_cd_profile) - strcat(reasons, "write type RAW prohibited by non-cd, "); - else if (d->status != BURN_DISC_BLANK) - strcat(reasons, "write type RAW works only on blank media, "); - else if ((d->block_types[BURN_WRITE_TAO] & demands.block_types) != - demands.block_types) - strcat(reasons, "drive dislikes block type, "); - if (strcmp(reason_pt, "RAW: ") != 0) - goto no_write_mode; - if (!opts->force_is_set) - goto no_simulate; - - /* For now: no setting of raw write modes */ - - {wt = BURN_WRITE_RAW; goto ex;} - -no_write_mode:; - {wt = BURN_WRITE_NONE; goto ex;} - -no_simulate:; - strcat(reasons, - "simulation of write job not supported by drive and media, "); - {wt = BURN_WRITE_NONE; goto ex;} - -ex:; - burn_disc_free_multi_caps(&caps); - if (wt == BURN_WRITE_NONE && !(flag & 3)) { - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x0002012b, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Drive offers no suitable write mode with this job", - 0, 0); - } - return wt; -} - - -/* ts A70213 : new API function */ -void burn_write_opts_set_fillup(struct burn_write_opts *opts,int fill_up_media) -{ - opts->fill_up_media = !!fill_up_media; - return; -} - - -/* ts A70303: API */ -void burn_write_opts_set_force(struct burn_write_opts *opts, int use_force) -{ - opts->force_is_set = !!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; -} - -void burn_read_opts_set_c2errors(struct burn_read_opts *opts, int c2errors) -{ - opts->c2errors = c2errors; -} - -void burn_read_opts_read_subcodes_audio(struct burn_read_opts *opts, - int subcodes_audio) -{ - opts->subcodes_audio = subcodes_audio; -} - -void burn_read_opts_read_subcodes_data(struct burn_read_opts *opts, - int subcodes_data) -{ - opts->subcodes_data = subcodes_data; -} - -void burn_read_opts_set_hardware_error_recovery(struct burn_read_opts *opts, - int hardware_error_recovery) -{ - opts->hardware_error_recovery = hardware_error_recovery; -} - -void burn_read_opts_report_recovered_errors(struct burn_read_opts *opts, - int report_recovered_errors) -{ - opts->report_recovered_errors = report_recovered_errors; -} - -void burn_read_opts_transfer_damaged_blocks(struct burn_read_opts *opts, - int transfer_damaged_blocks) -{ - opts->transfer_damaged_blocks = transfer_damaged_blocks; -} - -void burn_read_opts_set_hardware_error_retries(struct burn_read_opts *opts, - unsigned char - hardware_error_retries) -{ - opts->hardware_error_retries = hardware_error_retries; -} - diff --git a/libburn/options.h b/libburn/options.h deleted file mode 100644 index 17c961d..0000000 --- a/libburn/options.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef BURN__OPTIONS_H -#define BURN__OPTIONS_H - -#include "libburn.h" - -/** Options for disc writing operations. This should be created with - burn_write_opts_new() and freed with burn_write_opts_free(). */ -struct burn_write_opts -{ - /** Drive the write opts are good for */ - struct burn_drive *drive; - - /** For internal use. */ - int refcount; - - /** The method/style of writing to use. */ - enum burn_write_types write_type; - /** format of the data to send to the drive */ - enum burn_block_types block_type; - - /** Number of toc entries. if this is 0, they will be auto generated*/ - int toc_entries; - /** Toc entries for the disc */ - struct burn_toc_entry *toc_entry; - - /** Simulate the write so that the disc is not actually written */ - unsigned int simulate:1; - /** If available, enable a drive feature which prevents buffer - underruns if not enough data is available to keep up with the - drive. */ - unsigned int underrun_proof:1; - /** Perform calibration of the drive's laser before beginning the - write. */ - unsigned int perform_opc:1; - - /* ts A61219 : Output block size to trigger buffer flush if hit. - -1 with CD, 32 kB with DVD */ - int obs; - int obs_pad; /* 1=pad up last block to obs */ - - /* ts A61222 : Start address for media which allow a choice */ - off_t start_byte; - - /* ts A70213 : Wether to fill up the available space on media */ - int fill_up_media; - - /* ts A70303 : Wether to override conformance checks: - - the check wether CD write+block type is supported by the drive - */ - 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]; - /** Session format */ - int format; - /* internal use only */ - unsigned char control; - unsigned char multi; -}; - -/** Options for disc reading operations. This should be created with - burn_read_opts_new() and freed with burn_read_opts_free(). */ -struct burn_read_opts -{ - /** Drive the read opts are good for */ - struct burn_drive *drive; - - /** For internal use. */ - int refcount; - - /** Read in raw mode, so that everything in the data tracks on the - disc is read, including headers. Not needed if just reading a - filesystem off a disc, but it should usually be used when making a - disc image or copying a disc. */ - unsigned int raw:1; - /** Report c2 errors. Useful for statistics reporting */ - unsigned int c2errors:1; - /** Read subcodes from audio tracks on the disc */ - unsigned int subcodes_audio:1; - /** Read subcodes from data tracks on the disc */ - unsigned int subcodes_data:1; - /** Have the drive recover errors if possible */ - unsigned int hardware_error_recovery:1; - /** Report errors even when they were recovered from */ - unsigned int report_recovered_errors:1; - /** Read blocks even when there are unrecoverable errors in them */ - unsigned int transfer_damaged_blocks:1; - - /** The number of retries the hardware should make to correct - errors. */ - unsigned char hardware_error_retries; -}; - -#endif /* BURN__OPTIONS_H */ diff --git a/libburn/os-freebsd.h b/libburn/os-freebsd.h deleted file mode 100644 index 29b8771..0000000 --- a/libburn/os-freebsd.h +++ /dev/null @@ -1,61 +0,0 @@ - -/* os-freebsd.h - Operating system specific libburn definitions and declarations. Included - by os.h in case of compilation for - FreeBSD with CAM - - Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL -*/ - -/** List of all signals which shall be caught by signal handlers and trigger - a graceful abort of libburn. (See man 7 signal.) -*/ -/* Once as system defined macros */ -#define BURN_OS_SIGNAL_MACRO_LIST \ - SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, \ - SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, \ - SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN, \ - SIGTTOU, \ - SIGBUS, SIGPROF, SIGSYS, SIGTRAP, \ - SIGVTALRM, SIGXCPU, SIGXFSZ - -/* Once as text 1:1 list of strings for messages and interpreters */ -#define BURN_OS_SIGNAL_NAME_LIST \ - "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT", \ - "SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM", \ - "SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN", \ - "SIGTTOU", \ - "SIGBUS", "SIGPROF", "SIGSYS", "SIGTRAP", \ - "SIGVTALRM", "SIGXCPU", "SIGXFSZ" - -/* The number of above list items */ -#define BURN_OS_SIGNAL_COUNT 23 - -/** To list all signals which shall surely not be caught */ -#define BURN_OS_NON_SIGNAL_MACRO_LIST \ -SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH - -/* The number of above list items */ -#define BURN_OS_NON_SIGNAL_COUNT 5 - - -/* The maximum size for a (SCSI) i/o transaction */ -/* Important : MUST be at least 32768 ! */ -#define BURN_OS_TRANSPORT_BUFFER_SIZE 32768 - - -/** To hold all state information of BSD device enumeration - which are now local in sg_enumerate() . So that sg_give_next_adr() - can work in BSD and sg_enumerate() can use it. -*/ -#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \ -struct burn_drive_enumeration_state; \ -typedef struct burn_drive_enumeration_state *burn_drive_enumerator_t; - - -/* The list of operating system dependent elements in struct burn_drive. - To be initialized and used within sg-*.c . -*/ -#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \ -struct cam_device* cam; - diff --git a/libburn/os-linux.h b/libburn/os-linux.h deleted file mode 100644 index dcd4c46..0000000 --- a/libburn/os-linux.h +++ /dev/null @@ -1,76 +0,0 @@ - -/* os-linux.h - Operating system specific libburn definitions and declarations. Included - by os.h in case of compilation for - Linux kernels 2.4 and 2.6 with Linux SCSI Generic (sg) - - Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL -*/ - - -/** List of all signals which shall be caught by signal handlers and trigger - a graceful abort of libburn. (See man 7 signal.) -*/ -/* Once as system defined macros */ -#define BURN_OS_SIGNAL_MACRO_LIST \ - SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, \ - SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, \ - SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN, \ - SIGTTOU, \ - SIGBUS, SIGPOLL, SIGPROF, SIGSYS, SIGTRAP, \ - SIGVTALRM, SIGXCPU, SIGXFSZ - -/* Once as text 1:1 list of strings for messages and interpreters */ -#define BURN_OS_SIGNAL_NAME_LIST \ - "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT", \ - "SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM", \ - "SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN", \ - "SIGTTOU", \ - "SIGBUS", "SIGPOLL", "SIGPROF", "SIGSYS", "SIGTRAP", \ - "SIGVTALRM", "SIGXCPU", "SIGXFSZ" - -/* The number of above list items */ -#define BURN_OS_SIGNAL_COUNT 24 - -/** To list all signals which shall surely not be caught */ -#define BURN_OS_NON_SIGNAL_MACRO_LIST \ -SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH - -/* The number of above list items */ -#define BURN_OS_NON_SIGNAL_COUNT 5 - - -/* The maximum size for a (SCSI) i/o transaction */ -/* Important : MUST be at least 32768 ! */ -/* 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 - - -/* To hold the index number of the most recently delivered address from - device enumeration. -*/ -#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \ -typedef int burn_drive_enumerator_t; - - -/* Parameters for sibling list. See sibling_fds, sibling_fnames */ -#define BURN_OS_SG_MAX_SIBLINGS 5 -#define BURN_OS_SG_MAX_NAMELEN 16 - -/* The list of operating system dependent elements in struct burn_drive. - Usually they are initialized in sg-*.c:enumerate_common(). -*/ -#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \ -int fd; \ - \ -/* ts A60926 : trying to lock against growisofs /dev/srN, /dev/scdN */ \ -int sibling_count; \ -int sibling_fds[BURN_OS_SG_MAX_SIBLINGS]; \ -/* ts A70409 : DDLP */ \ -char sibling_fnames[BURN_OS_SG_MAX_SIBLINGS][BURN_OS_SG_MAX_NAMELEN]; - diff --git a/libburn/os.h b/libburn/os.h deleted file mode 100644 index 3b7a0f4..0000000 --- a/libburn/os.h +++ /dev/null @@ -1,34 +0,0 @@ - -/* os.h - Operating system specific libburn definitions and declarations. - The macros defined here are used by libburn modules in order to - avoid own system dependent case distinctions. - Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL -*/ - -#ifndef BURN_OS_H_INCLUDED -#define BURN_OS_H_INCLUDED 1 - -/* - Operating system case distinction -*/ - -#ifdef __FreeBSD__ - - -/* ----------------------------- FreeBSD with CAM -------------------------- */ -#include "os-freebsd.h" - - -#else /* operating system case distinction */ - - -/* --------- Linux kernels 2.4 and 2.6 with Linux SCSI Generic (sg) -------- */ -#include "os-linux.h" - - -#endif /* End of operating system case distinction */ - - -#endif /* ! BURN_OS_H_INCLUDED */ - diff --git a/libburn/read.c b/libburn/read.c deleted file mode 100644 index f965662..0000000 --- a/libburn/read.c +++ /dev/null @@ -1,490 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -/* #include <m alloc.h> ts A61013 : not in Linux man 3 malloc */ - -#include <stdlib.h> -#include <unistd.h> -#include <signal.h> - -/* ts A61007 */ -/* #include <a ssert.h> */ - -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <fcntl.h> -#include <errno.h> - -#include "sector.h" -#include "libburn.h" -#include "drive.h" -#include "transport.h" - -/* ts A60925 : obsoleted by libdax_msgs.h -#include "message.h" -*/ - -#include "crc.h" -#include "debug.h" -#include "init.h" -#include "lec.h" -#include "toc.h" -#include "util.h" -#include "sg.h" -#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 - int i, end, maxsects, finish; - int seclen; - int drive_lba; - unsigned short crc; - unsigned char fakesub[96]; - struct buffer page; - int speed; - - /* ts A61007 : if this function gets revived, then these - tests have to be done more graceful */ - a ssert((o->version & 0xfffff000) == (OPTIONS_VERSION & 0xfffff000)); - a ssert(!d->busy); - a ssert(d->toc->valid); - a ssert(o->datafd != -1); - - /* moved up from spc_select_error_params alias d->send_parameters() */ - a ssert(d->mdata->valid); - -/* XXX not sure this is a good idea. copy it? */ -/* XXX also, we have duplicated data now, do we remove the fds from struct -drive, or only store a subset of the _opts structs in drives */ - - /* set the speed on the drive */ - speed = o->speed > 0 ? o->speed : d->mdata->max_read_speed; - d->set_speed(d, speed, 0); - - d->params.retries = o->hardware_error_retries; - - d->send_parameters(d, o); - - d->cancel = 0; - d->busy = BURN_DRIVE_READING; - d->currsession = 0; -/* drive_lba = 232000; - d->currtrack = 18; -*/ - d->currtrack = 0; - drive_lba = 0; -/* XXX removal of this line obviously breaks * - d->track_end = burn_track_end(d, d->currsession, d->currtrack);*/ - printf("track ends at %d\n", d->track_end); - page.sectors = 0; - page.bytes = 0; - - if (o->subfd != -1) { - memset(fakesub, 0xFF, 12); - memset(fakesub + 12, 0, 84); - fakesub[13] = 1; - fakesub[14] = 1; - fakesub[20] = 2; - fakesub[12] = (d->toc->toc_entry[0].control << 4) + - d->toc->toc_entry[0].adr; - crc = crc_ccitt(fakesub + 12, 10); - fakesub[22] = crc >> 8; - fakesub[23] = crc & 0xFF; - write(o->subfd, fakesub, 96); - } - while (1) { - seclen = burn_sector_length_read(d, o); - - burn_print(12, "received %d blocks\n", page.sectors); - for (i = 0; i < page.sectors; i++) { - burn_packet_process(d, page.data + seclen * i, o); - d->track_end--; - drive_lba++; - } - - if ((d->cancel) || (drive_lba == LAST_SESSION_END(d))) { - burn_print(1, "finished or cancelled\n"); - d->busy = BURN_DRIVE_IDLE; - if (!d->cancel) - d->toc->complete = 1; - return; - } -/* XXX: removal of this line obviously breaks * - end = burn_track_end(d, d->currsession, d->currtrack); */ - - if (drive_lba == end) { - d->currtrack++; - if (d->currtrack > - d->toc->session[d->currsession].lasttrack) { - d->currsession++; - burn_print(12, "session switch to %d\n", - d->currsession); - burn_print(12, "skipping a lead out\n"); - drive_lba = CURRENT_SESSION_START(d); - burn_print(12, "new lba %d\n", drive_lba); -/* XXX more of the same - end = burn_track_end(d, d->currsession, - d->currtrack); -*/ } - burn_print(12, "track switch to %d\n", d->currtrack); - } - - page.sectors = 0; - page.bytes = 0; - - maxsects = BUFFER_SIZE / seclen; - finish = end - drive_lba; - - d->track_end = finish; - - page.sectors = (finish < maxsects) ? finish : maxsects; - printf("reading %d sectors from %d\n", page.sectors, - drive_lba); - - /* >>> ts A61009 : ensure page.sectors >= 0 before calling */ - d->r ead_sectors(d, drive_lba, page.sectors, o, &page); - - printf("Read %d\n", page.sectors); - } -#endif -} -int burn_sector_length_read(struct burn_drive *d, - const struct burn_read_opts *o) -{ - int dlen = 2352; - int data; - -/*XXX how do we handle this crap now?*/ -/* data = d->toc->track[d->currtrack].toc_entry->control & 4;*/ - data = 1; - if (o->report_recovered_errors) - dlen += 294; - if ((o->subcodes_data) && data) - dlen += 96; - if ((o->subcodes_audio) && !data) - dlen += 96; - return dlen; -} - -static int bitcount(unsigned char *data, int n) -{ - int i, j, count = 0; - unsigned char tem; - - for (i = 0; i < n; i++) { - tem = data[i]; - for (j = 0; j < 8; j++) { - count += tem & 1; - tem >>= 1; - } - } - return count; -} - -void burn_packet_process(struct burn_drive *d, unsigned char *data, - const struct burn_read_opts *o) -{ - unsigned char sub[96]; - unsigned short crc; - int ptr = 2352, i, j, code, fb; - int audio = 1; - - if (o->c2errors) { - fb = bitcount(data + ptr, 294); - if (fb) { - burn_print(1, "%d damaged bits\n", - bitcount(data + ptr, 294)); - burn_print(1, "sending error on %s %s\n", - d->idata->vendor, d->idata->product); - /* XXX send a burn_message! burn_message_error(d, - something); */ - } - ptr += 294; - } -/* - if (d->toc->track[d->currtrack].mode == BURN_MODE_UNINITIALIZED) { - if ((d->toc->track[d->currtrack].toc_entry->control & 4) == 0) - d->toc->track[d->currtrack].mode = BURN_MODE_AUDIO; - else - switch (data[15]) { - case 0: - d->toc->track[d->currtrack].mode = BURN_MODE0; - break; - case 1: - d->toc->track[d->currtrack].mode = BURN_MODE1; - break; - case 2: - d->toc->track[d->currtrack].mode = - BURN_MODE2_FORMLESS; - break; - } - } -*/ - if ((audio && o->subcodes_audio) - || (!audio && o->subcodes_data)) { - memset(sub, 0, sizeof(sub)); - for (i = 0; i < 12; i++) { - for (j = 0; j < 8; j++) { - for (code = 0; code < 8; code++) { - sub[code * 12 + i] <<= 1; - if (data[ptr + j + i * 8] & - (1 << (7 - code))) - sub[code * 12 + i]++; - } - } - } - crc = (*(sub + 22) << 8) + *(sub + 23); - if (crc != crc_ccitt(sub + 12, 10)) { - burn_print(1, "sending error on %s %s\n", - d->idata->vendor, d->idata->product); -/* e = burn_error(); - e->drive = d; -*/ - burn_print(1, "crc mismatch in Q\n"); - } - /* else process_q(d, sub + 12); */ - /* - if (o->subfd != -1) write(o->subfd, sub, 96); */ - } -/* - if ((d->track_end <= 150) - && (drive_lba + 150 < CURRENT_SESSION_END(d)) - && (TOC_ENTRY(d->toc, d->currtrack).control == 4) - && (TOC_ENTRY(d->toc, d->currtrack + 1).control == 0)) { - burn_print(12, "pregap : %d\n", d->track_end); - write(o->binfd, zeros, 2352); - -#warning XXX WHERE ARE MY SUBCODES - } else -*//* write(o->datafd, data, 2352); */ -} - -/* so yeah, when you uncomment these, make them write zeros insted of crap -static void write_empty_sector(int fd) -{ - char sec[2352]; - - burn_print(1, "writing an 'empty' sector\n"); - write(fd, sec, 2352); -} - -static void write_empty_subcode(int fd) -{ - char sub[96]; - - write(fd, sub, 96); -} - -static void flipq(unsigned char *sub) -{ - *(sub + 12 + 10) = ~*(sub + 12 + 10); - *(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; - -/* -#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 */ - 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 = NULL; - d->busy = BURN_DRIVE_IDLE; - return ret; -} diff --git a/libburn/read.h b/libburn/read.h deleted file mode 100644 index fc07958..0000000 --- a/libburn/read.h +++ /dev/null @@ -1,14 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef __LIBBURN_READ -#define __LIBBURN_READ - -struct burn_drive; -struct burn_read_opts; - -int burn_sector_length_read(struct burn_drive *d, - const struct burn_read_opts *o); -void burn_packet_process(struct burn_drive *d, unsigned char *data, - const struct burn_read_opts *o); - -#endif /* __LIBBURN_READ */ diff --git a/libburn/sbc.c b/libburn/sbc.c deleted file mode 100644 index b7726be..0000000 --- a/libburn/sbc.c +++ /dev/null @@ -1,114 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -/* scsi block commands */ - -#include <string.h> -#include <unistd.h> - -#include "transport.h" -#include "sbc.h" -#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 }; -static unsigned char SBC_START_UNIT[] = { 0x1b, 0, 0, 0, 1, 0 }; - -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)); - c.oplen = sizeof(SBC_LOAD); - 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); -} - -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 ? */ -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)); - c.oplen = sizeof(SBC_START_UNIT); - 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); -} - - -/* ts A61021 : the sbc specific part of sg.c:enumerate_common() -*/ -int sbc_setup_drive(struct burn_drive *d) -{ - d->eject = sbc_eject; - d->load = sbc_load; - d->start_unit = sbc_start_unit; - return 1; -} - diff --git a/libburn/sbc.h b/libburn/sbc.h deleted file mode 100644 index dc7a991..0000000 --- a/libburn/sbc.h +++ /dev/null @@ -1,18 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef __SBC -#define __SBC - -struct burn_drive; - -void sbc_load(struct burn_drive *); -void sbc_eject(struct burn_drive *); - -/* ts A61118 */ -int sbc_start_unit(struct burn_drive *); - -/* ts A61021 : the sbc specific part of sg.c:enumerate_common() -*/ -int sbc_setup_drive(struct burn_drive *d); - -#endif /* __SBC */ diff --git a/libburn/sector.c b/libburn/sector.c deleted file mode 100644 index 3551314..0000000 --- a/libburn/sector.c +++ /dev/null @@ -1,846 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#include <stdio.h> - -/* ts A61010 */ -/* #include <a ssert.h> */ - -#include <unistd.h> -#include <string.h> -#include "error.h" -#include "options.h" -#include "transport.h" -#include "libburn.h" -#include "drive.h" -#include "sector.h" -#include "crc.h" -#include "debug.h" -#include "lec.h" -#include "toc.h" -#include "write.h" - - -#ifdef Libburn_log_in_and_out_streaM -/* <<< ts A61031 */ -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#endif /* Libburn_log_in_and_out_streaM */ - - -/*static unsigned char isrc[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";*/ - -#define sector_common(X) d->alba++; d->rlba X; - -static void uncook_subs(unsigned char *dest, unsigned char *source) -{ - int i, j, code; - - memset(dest, 0, 96); - - for (i = 0; i < 12; i++) { - for (j = 0; j < 8; j++) { - for (code = 0; code < 8; code++) { - if (source[code * 12 + i] & 0x80) - dest[j + i * 8] |= (1 << (7 - code)); - source[code * 12 + i] <<= 1; - } - } - } -} - -/* @return >=0 : valid , <0 invalid */ -int sector_get_outmode(enum burn_write_types write_type, - enum burn_block_types block_type) -{ - /* ts A61103 : extended SAO condition to TAO */ - if (write_type == BURN_WRITE_SAO || write_type == BURN_WRITE_TAO) - return 0; - else - switch (block_type) { - case BURN_BLOCK_RAW0: - return BURN_MODE_RAW; - case BURN_BLOCK_RAW16: - return BURN_MODE_RAW | BURN_SUBCODE_P16; - case BURN_BLOCK_RAW96P: - return BURN_MODE_RAW | BURN_SUBCODE_P96; - case BURN_BLOCK_RAW96R: - return BURN_MODE_RAW | BURN_SUBCODE_R96; - case BURN_BLOCK_MODE1: - return BURN_MODE1; - default: - return -1; - } - - /* ts A61007 : now handled in burn_write_opts_set_write_type() */ - /* a ssert(0); */ /* return BURN_MODE_UNIMPLEMENTED :) */ -} - -/* 0 means "same as inmode" */ -static int get_outmode(struct burn_write_opts *o) -{ - /* ts A61007 */ - return sector_get_outmode(o->write_type, o->block_type); - - /* -1 is prevented by check in burn_write_opts_set_write_type() */ - /* a ssert(0); */ /* return BURN_MODE_UNIMPLEMENTED :) */ -} - - -static void get_bytes(struct burn_track *track, int count, unsigned char *data) -{ - int valid, shortage, curr, i, tr; - -#ifdef Libburn_log_in_and_out_streaM - /* <<< ts A61031 */ - static int tee_fd= -1; - if(tee_fd==-1) - tee_fd= open("/tmp/libburn_sg_readin", - O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR); -#endif /* Libburn_log_in_and_out_streaM */ - - -/* no track pointer means we're just generating 0s */ - if (!track) { - memset(data, 0, count); - return; - } - -/* first we use up any offset */ - valid = track->offset - track->offsetcount; - if (valid > count) - valid = count; - - if (valid) { - track->offsetcount += valid; - memset(data, 0, valid); - } - shortage = count - valid; - - if (!shortage) - goto ex; - -/* 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); - } else valid = 0; - - if (valid <= 0) { /* ts A61031 : extended from (valid == -1) */ - track->eos = 1; - valid = 0; - } - track->sourcecount += valid; - -#ifdef Libburn_log_in_and_out_streaM - /* <<< ts A61031 */ - if(tee_fd!=-1 && valid>0) { - write(tee_fd, data + curr, valid); - } -#endif /* Libburn_log_in_and_out_streaM */ - - curr += valid; - shortage = count - curr; - - if (!shortage) - goto ex; - -/* Before going to the next track, we run through any tail */ - - valid = track->tail - track->tailcount; - if (valid > count - curr) - valid = count - curr; - - if (valid) { - track->tailcount += valid; - memset(data + curr, 0, valid); - } - curr += valid; - shortage -= valid; - - if (!shortage) - goto ex; - - /* ts A61031 */ - if (shortage >= count) - track->track_data_done = 1; - if (track->open_ended) - goto ex; - -/* If we're still short, and there's a "next" pointer, we pull from that. - if that depletes, we'll just fill with 0s. -*/ - if (track->source->next) { - struct burn_source *src; - printf("pulling from next track\n"); - src = track->source->next; - valid = src->read(src, data + curr, shortage); - if (valid > 0) { - shortage -= valid; - curr += valid; - } - } -ex:; - /* ts A61024 : general finalizing processing */ - if(shortage) - memset(data + curr, 0, shortage); /* this is old icculus.org */ - if (track->swap_source_bytes == 1) { - for (i = 1; i < count; i += 2) { - tr = data[i]; - data[i] = data[i-1]; - data[i-1] = tr; - } - } -} - -/* ts A61009 : seems to hand out sector start pointer in opts->drive->buffer - and to count hand outs as well as reserved bytes */ -/* ts A61101 : added parameter track for counting written bytes */ -static unsigned char *get_sector(struct burn_write_opts *opts, - struct burn_track *track, int inmode) -{ - struct burn_drive *d = opts->drive; - struct buffer *out = d->buffer; - int outmode; - int seclen; - unsigned char *ret; - - outmode = get_outmode(opts); - if (outmode == 0) - outmode = inmode; - - /* ts A61009 : react on eventual failure of burn_sector_length() - (should not happen if API tested properly). - Ensures out->bytes >= out->sectors */ - seclen = burn_sector_length(outmode); - if (seclen <= 0) - return NULL; - seclen += burn_subcode_length(outmode); - - /* ts A61219 : opts->obs is eventually a 32k trigger for DVD */ - if (out->bytes + seclen > BUFFER_SIZE || - (opts->obs > 0 && out->bytes + seclen > opts->obs)) { - int err; - err = d->write(d, d->nwa, out); - if (err == BE_CANCELLED) - return NULL; - - /* ts A61101 */ - if(track != NULL) { - track->writecount += out->bytes; - track->written_sectors += out->sectors; - } - /* ts A61119 */ - d->progress.buffered_bytes += out->bytes; - - d->nwa += out->sectors; - out->bytes = 0; - out->sectors = 0; - } - - ret = out->data + out->bytes; - out->bytes += seclen; - out->sectors++; - - return ret; -} - -/* ts A61031 */ -/* Revoke the counting of the most recent sector handed out by get_sector() */ -static void unget_sector(struct burn_write_opts *opts, int inmode) -{ - struct burn_drive *d = opts->drive; - struct buffer *out = d->buffer; - int outmode; - int seclen; - - outmode = get_outmode(opts); - if (outmode == 0) - outmode = inmode; - - /* ts A61009 : react on eventual failure of burn_sector_length() - (should not happen if API tested properly). - Ensures out->bytes >= out->sectors */ - seclen = burn_sector_length(outmode); - if (seclen <= 0) - return; - seclen += burn_subcode_length(outmode); - - out->bytes -= seclen; - out->sectors--; -} - - -/* either inmode == outmode, or outmode == raw. anything else is bad news */ -/* ts A61010 : changed type to int in order to propagate said bad news */ -/** @return 1 is ok, <= 0 is failure */ -static int convert_data(struct burn_write_opts *o, struct burn_track *track, - int inmode, unsigned char *data) -{ - int outlen, inlen; - int offset = -1; - int outmode; - - outmode = get_outmode(o); - if (outmode == 0) - outmode = inmode; - - outlen = burn_sector_length(outmode); - inlen = burn_sector_length(inmode); - - /* ts A61010 */ - /* a ssert(outlen >= inlen); */ - if (outlen < inlen) - return 0; - - if ((outmode & BURN_MODE_BITS) == (inmode & BURN_MODE_BITS)) { - get_bytes(track, inlen, data); - return 1; - } - - /* ts A61010 */ - /* a ssert(outmode & BURN_MODE_RAW); */ - if (!(outmode & BURN_MODE_RAW)) - return 0; - - if (inmode & BURN_MODE1) - offset = 16; - if (inmode & BURN_MODE_RAW) - offset = 0; - if (inmode & BURN_AUDIO) - offset = 0; - - /* ts A61010 */ - /* a ssert(offset != -1); */ - if (offset == -1) - return 0; - - get_bytes(track, inlen, data + offset); - return 1; -} - -static void convert_subs(struct burn_write_opts *o, int inmode, - unsigned char *subs, unsigned char *sector) -{ - unsigned char *out; - int outmode; - - outmode = get_outmode(o); - if (outmode == 0) - outmode = inmode; - sector += burn_sector_length(outmode); -/* XXX for sao with subs, we'd need something else... */ - - switch (o->block_type) { - case BURN_BLOCK_RAW96R: - uncook_subs(sector, subs); - break; - - case BURN_BLOCK_RAW16: - memcpy(sector, subs + 12, 12); - out = sector + 12; - out[0] = 0; - out[1] = 0; - out[2] = 0; -/*XXX find a better way to deal with partially damaged P channels*/ - if (subs[2] != 0) - out[3] = 0x80; - else - out[3] = 0; - out = sector + 10; - - out[0] = ~out[0]; - out[1] = ~out[1]; - break; - /* ts A61119 : to silence compiler warnings */ - default:; - } -} - -static void subcode_toc(struct burn_drive *d, int mode, unsigned char *data) -{ - unsigned char *q; - int track; - int crc; - int min, sec, frame; - - track = d->toc_temp / 3; - memset(data, 0, 96); - q = data + 12; - - burn_lba_to_msf(d->rlba, &min, &sec, &frame); -/*XXX track numbers are BCD -a0 - 1st track ctrl -a1 - last track ctrl -a2 - lout ctrl -*/ - q[0] = (d->toc_entry[track].control << 4) + 1; - q[1] = 0; - if (d->toc_entry[track].point < 100) - q[2] = dec_to_bcd(d->toc_entry[track].point); - else - q[2] = d->toc_entry[track].point; - q[3] = dec_to_bcd(min); - q[4] = dec_to_bcd(sec); - q[5] = dec_to_bcd(frame); - q[6] = 0; - q[7] = dec_to_bcd(d->toc_entry[track].pmin); - q[8] = dec_to_bcd(d->toc_entry[track].psec); - q[9] = dec_to_bcd(d->toc_entry[track].pframe); - crc = crc_ccitt(q, 10); - q[10] = crc >> 8; - q[11] = crc & 0xFF; - d->toc_temp++; - d->toc_temp %= (d->toc_entries * 3); -} - -int sector_toc(struct burn_write_opts *o, int mode) -{ - struct burn_drive *d = o->drive; - unsigned char *data; - unsigned char subs[96]; - - data = get_sector(o, NULL, mode); - if (data == NULL) - return 0; - /* ts A61010 */ - if (convert_data(o, NULL, mode, data) <= 0) - return 0; - subcode_toc(d, mode, subs); - convert_subs(o, mode, subs, data); - sector_headers(o, data, mode, 1); - sector_common(++) - return 1; -} - -int sector_pregap(struct burn_write_opts *o, - unsigned char tno, unsigned char control, int mode) -{ - struct burn_drive *d = o->drive; - unsigned char *data; - unsigned char subs[96]; - - data = get_sector(o, NULL, mode); - if (data == NULL) - return 0; - /* ts A61010 */ - if (convert_data(o, NULL, mode, data) <= 0) - return 0; - subcode_user(o, subs, tno, control, 0, NULL, 1); - convert_subs(o, mode, subs, data); - sector_headers(o, data, mode, 0); - sector_common(--) - return 1; -} - -int sector_postgap(struct burn_write_opts *o, - unsigned char tno, unsigned char control, int mode) -{ - struct burn_drive *d = o->drive; - unsigned char subs[96]; - unsigned char *data; - - data = get_sector(o, NULL, mode); - if (data == NULL) - return 0; - /* ts A61010 */ - if (convert_data(o, NULL, mode, data) <= 0) - return 0;; -/* use last index in track */ - subcode_user(o, subs, tno, control, 1, NULL, 1); - convert_subs(o, mode, subs, data); - sector_headers(o, data, mode, 0); - sector_common(++) - return 1; -} - -static void subcode_lout(struct burn_write_opts *o, unsigned char control, - unsigned char *data) -{ - struct burn_drive *d = o->drive; - unsigned char *q; - int crc; - int rmin, min, rsec, sec, rframe, frame; - - memset(data, 0, 96); - q = data + 12; - - burn_lba_to_msf(d->alba, &min, &sec, &frame); - burn_lba_to_msf(d->rlba, &rmin, &rsec, &rframe); - - if (((rmin == 0) && (rsec == 0) && (rframe == 0)) || - ((rsec >= 2) && !((rframe / 19) % 2))) - memset(data, 0xFF, 12); - q[0] = (control << 4) + 1; - q[1] = 0xAA; - q[2] = 0x01; - q[3] = dec_to_bcd(rmin); - q[4] = dec_to_bcd(rsec); - q[5] = dec_to_bcd(rframe); - q[6] = 0; - q[7] = dec_to_bcd(min); - q[8] = dec_to_bcd(sec); - q[9] = dec_to_bcd(frame); - crc = crc_ccitt(q, 10); - q[10] = crc >> 8; - q[11] = crc & 0xFF; -} - -static char char_to_isrc(char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'A' && c <= 'Z') - return 0x11 + (c - 'A'); - if (c >= 'a' && c <= 'z') - return 0x11 + (c - 'a'); - - /* ts A61008 : obsoleted by test in burn_track_set_isrc() */ - /* a ssert(0); */ - return 0; -} - -void subcode_user(struct burn_write_opts *o, unsigned char *subcodes, - unsigned char tno, unsigned char control, - unsigned char indx, struct isrc *isrc, int psub) -{ - struct burn_drive *d = o->drive; - unsigned char *p, *q; - int crc; - int m, s, f, c, qmode; /* 1, 2 or 3 */ - - memset(subcodes, 0, 96); - - p = subcodes; - if ((tno == 1) && (d->rlba == -150)) - memset(p, 0xFF, 12); - - if (psub) - memset(p, 0xFF, 12); - q = subcodes + 12; - - qmode = 1; - /* every 1 in 10 we can do something different */ - if (d->rlba % 10 == 0) { - /* each of these can occur 1 in 100 */ - if ((d->rlba / 10) % 10 == 0) { - if (o->has_mediacatalog) - qmode = 2; - } else if ((d->rlba / 10) % 10 == 1) { - if (isrc && isrc->has_isrc) - qmode = 3; - } - } - - /* ts A61010 : this cannot happen. Assert for fun ? */ - /* a ssert(qmode == 1 || qmode == 2 || qmode == 3); */ - - switch (qmode) { - case 1: - q[1] = dec_to_bcd(tno); /* track number */ - q[2] = dec_to_bcd(indx); /* index XXX read this shit - from the track array */ - burn_lba_to_msf(d->rlba, &m, &s, &f); - q[3] = dec_to_bcd(m); /* rel min */ - q[4] = dec_to_bcd(s); /* rel sec */ - q[5] = dec_to_bcd(f); /* rel frame */ - q[6] = 0; /* zero */ - burn_lba_to_msf(d->alba, &m, &s, &f); - q[7] = dec_to_bcd(m); /* abs min */ - q[8] = dec_to_bcd(s); /* abs sec */ - q[9] = dec_to_bcd(f); /* abs frame */ - break; - case 2: - /* media catalog number */ - q[1] = (o->mediacatalog[0] << 4) + o->mediacatalog[1]; - q[2] = (o->mediacatalog[2] << 4) + o->mediacatalog[3]; - q[3] = (o->mediacatalog[4] << 4) + o->mediacatalog[5]; - q[4] = (o->mediacatalog[6] << 4) + o->mediacatalog[7]; - q[5] = (o->mediacatalog[8] << 4) + o->mediacatalog[9]; - q[6] = (o->mediacatalog[10] << 4) + o->mediacatalog[11]; - q[7] = o->mediacatalog[12] << 4; - - q[8] = 0; - burn_lba_to_msf(d->alba, &m, &s, &f); - q[9] = dec_to_bcd(f); /* abs frame */ - break; - case 3: - c = char_to_isrc(isrc->country[0]); - /* top 6 bits of [1] is the first country code */ - q[1] = c << 2; - c = char_to_isrc(isrc->country[1]); - /* bottom 2 bits of [1] is part of the second country code */ - q[1] += (c >> 4); - /* top 4 bits if [2] is the rest of the second country code */ - q[2] = c << 4; - - c = char_to_isrc(isrc->owner[0]); - /* bottom 4 bits of [2] is part of the first owner code */ - q[2] += (c >> 2); - /* top 2 bits of [3] is the rest of the first owner code */ - q[3] = c << 6; - c = char_to_isrc(isrc->owner[1]); - /* bottom 6 bits of [3] is the entire second owner code */ - q[3] += c; - c = char_to_isrc(isrc->owner[2]); - /* top 6 bits of [4] are the third owner code */ - q[4] = c << 2; - - /* [5] is the year in 2 BCD numbers */ - q[5] = dec_to_bcd(isrc->year % 100); - /* [6] is the first 2 digits in the serial */ - q[6] = dec_to_bcd(isrc->serial % 100); - /* [7] is the next 2 digits in the serial */ - q[7] = dec_to_bcd((isrc->serial / 100) % 100); - /* the top 4 bits of [8] is the last serial digit, the rest is - zeros */ - q[8] = dec_to_bcd((isrc->serial / 10000) % 10) << 4; - burn_lba_to_msf(d->alba, &m, &s, &f); - q[9] = dec_to_bcd(f); /* abs frame */ - break; - } - q[0] = (control << 4) + qmode; - - crc = crc_ccitt(q, 10); - q[10] = crc >> 8; - q[11] = crc & 0xff; -} - -int sector_lout(struct burn_write_opts *o, unsigned char control, int mode) -{ - struct burn_drive *d = o->drive; - unsigned char subs[96]; - unsigned char *data; - - data = get_sector(o, NULL, mode); - if (!data) - return 0; - /* ts A61010 */ - if (convert_data(o, NULL, mode, data) <= 0) - return 0; - subcode_lout(o, control, subs); - convert_subs(o, mode, subs, data); - sector_headers(o, data, mode, 0); - sector_common(++) - return 1; -} - -int sector_data(struct burn_write_opts *o, struct burn_track *t, int psub) -{ - struct burn_drive *d = o->drive; - unsigned char subs[96]; - unsigned char *data; - - data = get_sector(o, t, t->mode); - if (!data) - return 0; - /* ts A61010 */ - if (convert_data(o, t, t->mode, data) <= 0) - return 0; - - /* ts A61031 */ - if (t->open_ended && t->track_data_done) { - unget_sector(o, t->mode); - return 2; - } - - /* ts A61219 : allow track without .entry */ - if (t->entry == NULL) - ; - else if (!t->source->read_sub) - subcode_user(o, subs, t->entry->point, - t->entry->control, 1, &t->isrc, psub); - else if (!t->source->read_sub(t->source, subs, 96)) - subcode_user(o, subs, t->entry->point, - t->entry->control, 1, &t->isrc, psub); - convert_subs(o, t->mode, subs, data); - - sector_headers(o, data, t->mode, 0); - sector_common(++) - return 1; -} - -int burn_msf_to_lba(int m, int s, int f) -{ - if (m < 90) - return (m * 60 + s) * 75 + f - 150; - else - return (m * 60 + s) * 75 + f - 450150; -} - -void burn_lba_to_msf(int lba, int *m, int *s, int *f) -{ - if (lba >= -150) { - *m = (lba + 150) / (60 * 75); - *s = (lba + 150 - *m * 60 * 75) / 75; - *f = lba + 150 - *m * 60 * 75 - *s * 75; - } else { - *m = (lba + 450150) / (60 * 75); - *s = (lba + 450150 - *m * 60 * 75) / 75; - *f = lba + 450150 - *m * 60 * 75 - *s * 75; - } -} - -int dec_to_bcd(int d) -{ - int top, bottom; - - top = d / 10; - bottom = d - (top * 10); - return (top << 4) + bottom; -} - -int sector_headers_is_ok(struct burn_write_opts *o, int mode) -{ - if (mode & BURN_AUDIO) /* no headers for "audio" */ - return 1; - if (o->write_type == BURN_WRITE_SAO) - return 1; - - /* ts A61031 */ - if (o->write_type == BURN_WRITE_TAO) - return 1; - - if (mode & BURN_MODE1) - return 2; - return 0; -} - -void sector_headers(struct burn_write_opts *o, unsigned char *out, - int mode, int leadin) -{ - struct burn_drive *d = o->drive; - unsigned int crc; - int min, sec, frame; - int modebyte = -1; - - /* ts A61009 */ -#if 1 - int ret; - - ret = sector_headers_is_ok(o, mode); - if (ret != 2) - return; - modebyte = 1; - -#else - - if (mode & BURN_AUDIO) /* no headers for "audio" */ - return; - if (o->write_type == BURN_WRITE_SAO) - return; - - /* ts A61031 */ - if (o->write_type == BURN_WRITE_TAO) - return; - - if (mode & BURN_MODE1) - modebyte = 1; - -#endif - - /* ts A61009 : now ensured by burn_disc_write_is_ok() */ - /* a ssert(modebyte == 1); */ - - out[0] = 0; - memset(out + 1, 0xFF, 10); /* sync */ - out[11] = 0; - - if (leadin) { - burn_lba_to_msf(d->rlba, &min, &sec, &frame); - out[12] = dec_to_bcd(min) + 0xA0; - out[13] = dec_to_bcd(sec); - out[14] = dec_to_bcd(frame); - out[15] = modebyte; - } else { - burn_lba_to_msf(d->alba, &min, &sec, &frame); - out[12] = dec_to_bcd(min); - out[13] = dec_to_bcd(sec); - out[14] = dec_to_bcd(frame); - out[15] = modebyte; - } - if (mode & BURN_MODE1) { - crc = crc_32(out, 2064); - out[2064] = crc & 0xFF; - crc >>= 8; - out[2065] = crc & 0xFF; - crc >>= 8; - out[2066] = crc & 0xFF; - crc >>= 8; - out[2067] = crc & 0xFF; - } - if (mode & BURN_MODE1) { - memset(out + 2068, 0, 8); - parity_p(out); - parity_q(out); - } - scramble(out); -} - -#if 0 -void process_q(struct burn_drive *d, unsigned char *q) -{ - unsigned char i[5]; - int mode; - - mode = q[0] & 0xF; -/* burn_print(12, "mode: %d : ", mode);*/ - switch (mode) { - case 1: -/* burn_print(12, "tno = %d : ", q[1]); - burn_print(12, "index = %d\n", q[2]); -*/ - /* q[1] is the track number (starting at 1) q[2] is the index - number (starting at 0) */ -#warning this is totally bogus - if (q[1] - 1 > 99) - break; - if (q[2] > d->toc->track[q[1] - 1].indices) { - burn_print(12, "new index at %d\n", d->alba); - d->toc->track[q[1] - 1].index[q[2]] = d->alba; - d->toc->track[q[1] - 1].indices++; - } - break; - case 2: - /* XXX dont ignore these */ - break; - case 3: -/* burn_print(12, "ISRC data in mode 3 q\n");*/ - i[0] = isrc[(q[1] << 2) >> 2]; -/* burn_print(12, "0x%x 0x%x 0x%x 0x%x 0x%x\n", q[1], q[2], q[3], q[4], q[5]); - burn_print(12, "ISRC - %c%c%c%c%c\n", i[0], i[1], i[2], i[3], i[4]); -*/ - break; - default: - - /* ts A61009 : if reactivated then witout Assert */ - a ssert(0); - } -} -#endif - -/* this needs more info. subs in the data? control/adr? */ - -/* ts A61119 : One should not use inofficial compiler extensions. - >>> Some day this function needs to be implemented. At least for now - the result does not match the "mode" of cdrecord -toc. - */ -/* -#warning sector_identify needs to be written -*/ -int sector_identify(unsigned char *data) -{ - scramble(data); -/* -check mode byte for 1 or 2 -test parity to see if it's a valid sector -if invalid, return BURN_MODE_AUDIO; -else return mode byte (what about mode 2 formless? heh) -*/ - return BURN_MODE1; -} diff --git a/libburn/sector.h b/libburn/sector.h deleted file mode 100644 index ecb609a..0000000 --- a/libburn/sector.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef __SECTOR -#define __SECTOR - -#include "libburn.h" -#include "transport.h" - -struct burn_drive; -struct isrc; - -int dec_to_bcd(int); - -int sector_toc(struct burn_write_opts *, int mode); -int sector_pregap(struct burn_write_opts *, unsigned char tno, - unsigned char control, int mode); -int sector_postgap(struct burn_write_opts *, unsigned char tno, - unsigned char control, int mode); -int sector_lout(struct burn_write_opts *, unsigned char control, int mode); -int sector_data(struct burn_write_opts *, struct burn_track *t, int psub); - -/* ts A61009 */ -int sector_headers_is_ok(struct burn_write_opts *o, int mode); - -void sector_headers(struct burn_write_opts *, unsigned char *, - int mode, int leadin); -void subcode_user(struct burn_write_opts *, unsigned char *s, - unsigned char tno, unsigned char control, - unsigned char index, struct isrc *isrc, int psub); - -int sector_identify(unsigned char *); - -void process_q(struct burn_drive *d, unsigned char *q); - -#endif /* __SECTOR */ diff --git a/libburn/sg-freebsd-port.c b/libburn/sg-freebsd-port.c deleted file mode 100644 index e7e8168..0000000 --- a/libburn/sg-freebsd-port.c +++ /dev/null @@ -1,631 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -/* - -This is the main operating system dependent SCSI part of libburn. It implements -the transport level aspects of SCSI control and command i/o. - -Present implementation: FreeBSD CAM (untested) - - -PORTING: - -Porting libburn typically will consist of adding a new operating system case -to the following switcher files: - os.h Operating system specific libburn definitions and declarations. - sg.c Operating system dependent transport level modules. -and of deriving the following system specific files from existing examples: - os-*.h Included by os.h. You will need some general system knowledge - about signals and knowledge about the storage object needs of your - transport level module sg-*.c. - - sg-*.c This source module. You will need special system knowledge about - how to detect all potentially available drives, how to open them, - eventually how to exclusively reserve them, how to perform - SCSI transactions, how to inquire the (pseudo-)SCSI driver. - You will not need to care about CD burning, MMC or other high-level - SCSI aspects. - -Said sg-*.c operations are defined by a public function interface, which has -to be implemented in a way that provides libburn with the desired services: - -sg_give_next_adr() iterates over the set of potentially useful drive - address strings. - -scsi_enumerate_drives() brings all available, not-whitelist-banned, and - accessible drives into libburn's list of drives. - -sg_drive_is_open() tells wether libburn has the given drive in use. - -sg_grab() opens the drive for SCSI commands and ensures - undisturbed access. - -sg_release() closes a drive opened by sg_grab() - -sg_issue_command() sends a SCSI command to the drive, receives reply, - and evaluates wether the command succeeded or shall - be retried or finally failed. - -sg_obtain_scsi_adr() tries to obtain SCSI address parameters. - -burn_os_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 . - -*/ - - -/** PORTING : ------- OS dependent headers and definitions ------ */ - -#include <errno.h> -#include <unistd.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/ioctl.h> -#include <stdlib.h> -#include <string.h> -#include <sys/poll.h> -#include <camlib.h> -#include <cam/scsi/scsi_message.h> -#include <cam/scsi/scsi_pass.h> - -#include <err.h> /* XXX */ - - -/* ts A70909 : >>> untestet yet wether this compiles */ -#include <sys/statvfs.h> - - -/** PORTING : ------ libburn portable headers and definitions ----- */ - -#include "transport.h" -#include "drive.h" -#include "sg.h" -#include "spc.h" -#include "mmc.h" -#include "sbc.h" -#include "debug.h" -#include "toc.h" -#include "util.h" - -#include "libdax_msgs.h" -extern struct libdax_msgs *libdax_messenger; - - -/* is in portable part of libburn */ -int burn_drive_is_banned(char *device_address); - - - -/* ------------------------------------------------------------------------ */ -/* ts A61115: Private functions. Port only if needed by public functions */ -/* (Public functions are listed below) */ -/* ------------------------------------------------------------------------ */ - - -/* Helper function for scsi_give_next_adr() */ -static int sg_init_enumerator(burn_drive_enumerator_t *idx) -{ - idx->skip_device = 0; - - if ((idx->fd = open(XPT_DEVICE, O_RDWR)) == -1) { - warn("couldn't open %s", XPT_DEVICE); - return -1; - } - - bzero(&(idx->ccb), sizeof(union ccb)); - - idx->ccb.ccb_h.path_id = CAM_XPT_PATH_ID; - idx->ccb.ccb_h.target_id = CAM_TARGET_WILDCARD; - idx->ccb.ccb_h.target_lun = CAM_LUN_WILDCARD; - - idx->ccb.ccb_h.func_code = XPT_DEV_MATCH; - idx->bufsize = sizeof(struct dev_match_result) * 100; - idx->ccb.cdm.match_buf_len = idx->bufsize; - idx->ccb.cdm.matches = (struct dev_match_result *)malloc(idx->bufsize); - if (idx->ccb.cdm.matches == NULL) { - warnx("can't malloc memory for matches"); - close(idx->fd); - return -1; - } - idx->ccb.cdm.num_matches = 0; - idx->i = idx->ccb.cdm.num_matches; /* to trigger buffer load */ - - /* - * We fetch all nodes, since we display most of them in the default - * case, and all in the verbose case. - */ - idx->ccb.cdm.num_patterns = 0; - idx->ccb.cdm.pattern_buf_len = 0; - - return 1; -} - - -/* Helper function for scsi_give_next_adr() */ -static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx) -{ - /* - * We do the ioctl multiple times if necessary, in case there are - * more than 100 nodes in the EDT. - */ - if (ioctl(idx->fd, CAMIOCOMMAND, &(idx->ccb)) == -1) { - warn("error sending CAMIOCOMMAND ioctl"); - return -1; - } - - if ((idx->ccb.ccb_h.status != CAM_REQ_CMP) - || ((idx->ccb.cdm.status != CAM_DEV_MATCH_LAST) - && (idx->ccb.cdm.status != CAM_DEV_MATCH_MORE))) { - warnx("got CAM error %#x, CDM error %d\n", - idx->ccb.ccb_h.status, idx->ccb.cdm.status); - return -1; - } - return 1; -} - - -static int sg_close_drive(struct burn_drive * d) -{ - if (d->cam != NULL) { - cam_close_device(d->cam); - d->cam = NULL; - } - return 0; -} - - -/* ----------------------------------------------------------------------- */ -/* PORTING: Private functions which contain publicly needed functionality. */ -/* Their portable part must be performed. So it is probably best */ -/* to replace the non-portable part and to call these functions */ -/* in your port, too. */ -/* ----------------------------------------------------------------------- */ - - -/** Wraps a detected drive into libburn structures and hands it over to - libburn drive list. -*/ -static void enumerate_common(char *fname, int bus_no, int host_no, - int channel_no, int target_no, int lun_no) -{ - int ret; - struct burn_drive out; - - /* General libburn drive setup */ - burn_setup_drive(&out, fname); - - /* This transport adapter uses SCSI-family commands and models - (seems the adapter would know better than its boss, if ever) */ - ret = burn_scsi_setup_drive(&out, bus_no, host_no, channel_no, - target_no, lun_no, 0); - if (ret<=0) - return; - - /* PORTING: ------------------- non portable part --------------- */ - - /* Operating system adapter is CAM */ - /* Adapter specific handles and data */ - out.cam = NULL; - - /* PORTING: ---------------- end of non portable part ------------ */ - - /* Adapter specific functions with standardized names */ - out.grab = sg_grab; - out.release = sg_release; - out.drive_is_open = sg_drive_is_open; - out.issue_command = sg_issue_command; - /* Finally register drive and inquire drive information */ - burn_drive_finish_enum(&out); -} - - -/* ts A61115 */ -/* ------------------------------------------------------------------------ */ -/* PORTING: Public functions. These MUST be ported. */ -/* ------------------------------------------------------------------------ */ - - -/** Returns the next index number and the next enumerated drive address. - The enumeration has to cover all available and accessible drives. It is - allowed to return addresses of drives which are not available but under - some (even exotic) circumstances could be available. It is on the other - hand allowed, only to hand out addresses which can really be used right - in the moment of this call. (This implementation chooses the latter.) - @param idx An opaque handle. Make no own theories about it. - @param adr Takes the reply - @param adr_size Gives maximum size of reply including final 0 - @param initialize 1 = start new, - 0 = continue, use no other values for now - -1 = finish - @return 1 = reply is a valid address , 0 = no further address available - -1 = severe error (e.g. adr_size too small) -*/ -int sg_give_next_adr(burn_drive_enumerator_t *idx, - char adr[], int adr_size, int initialize) -{ - int ret; - - if (initialize == 1) { - ret = sg_init_enumerator(idx); - if (ret<=0) - return ret; - } else if (initialize == -1) { - if(idx->fd != -1) - close(idx->fd); - idx->fd = -1; - return 0; - } - - -try_item:; /* This spaghetti loop keeps the number of tabs small */ - - /* Loop content from old scsi_enumerate_drives() */ - - while (idx->i >= idx->ccb.cdm.num_matches) { - ret = sg_next_enumeration_buffer(idx); - if (ret<=0) - return -1; - if (!((idx->ccb.ccb_h.status == CAM_REQ_CMP) - && (idx->ccb.cdm.status == CAM_DEV_MATCH_MORE)) ) - return 0; - idx->i = 0; - } - - switch (idx->ccb.cdm.matches[idx->i].type) { - case DEV_MATCH_BUS: - break; - case DEV_MATCH_DEVICE: { - struct device_match_result* result; - - result = &(idx->ccb.cdm.matches[i].result.device_result); - if (result->flags & DEV_RESULT_UNCONFIGURED) - idx->skip_device = 1; - else - idx->skip_device = 0; - break; - } - case DEV_MATCH_PERIPH: { - struct periph_match_result* result; - char buf[64]; - - result = &(idx->ccb.cdm.matches[i].result.periph_result); - if (idx->skip_device || - strcmp(result->periph_name, "pass") == 0) - break; - snprintf(buf, sizeof (buf), "/dev/%s%d", - result->periph_name, result->unit_number); - if(adr_size <= strlen(buf) - return -1; - strcpy(adr, buf); - - /* Found next enumerable address */ - return 1; - - } - default: - /* printf(stderr, "unknown match type\n"); */ - break; - } - - (idx->i)++; - goto try_item; /* Regular function exit is return 1 above */ -} - - -/** Brings all available, not-whitelist-banned, and accessible drives into - libburn's list of drives. -*/ -int scsi_enumerate_drives(void) -{ - burn_drive_enumerator_t idx; - int initialize = 1; - char buf[64]; - - while(1) { - ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize); - initialize = 0; - if (ret <= 0) - break; - if (burn_drive_is_banned(buf)) - continue; - enumerate_common(buf, idx.result->path_id, idx.result->path_id, - 0, idx.result->target_id, - idx.result->target_lun); - } - sg_give_next_adr(&idx, buf, sizeof(buf), -1); -} - - -/** Tells wether libburn has the given drive in use or exclusively reserved. - If it is "open" then libburn will eventually call sg_release() on it when - it is time to give up usage resp. reservation. -*/ -/** Published as burn_drive.drive_is_open() */ -int sg_drive_is_open(struct burn_drive * d) -{ - return (d->cam != NULL); -} - - -/** Opens the drive for SCSI commands and - if burn activities are prone - to external interference on your system - obtains an exclusive access lock - on the drive. (Note: this is not physical tray locking.) - A drive that has been opened with sg_grab() will eventually be handed - over to sg_release() for closing and unreserving. -*/ -int sg_grab(struct burn_drive *d) -{ - int count; - struct cam_device *cam; - - if(d->cam != NULL) - return 0; - - cam = cam_open_device(d->devname, O_RDWR); - if (cam == NULL) { - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020003, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Could not grab drive", 0/*os_errno*/, 0); - return 0; - } - d->cam = cam; - fcntl(cam->fd, F_SETOWN, getpid()); - d->released = 0; - return 1; -} - - -/** PORTING: Is mainly about the call to sg_close_drive() and wether it - implements the demanded functionality. -*/ -/** Gives up the drive for SCSI commands and releases eventual access locks. - (Note: this is not physical tray locking.) -*/ -int sg_release(struct burn_drive *d) -{ - if (d->cam == NULL) { - burn_print(1, "release an ungrabbed drive. die\n"); - return 0; - } - sg_close_drive(d); - return 0; -} - - -/** Sends a SCSI command to the drive, receives reply and evaluates wether - the command succeeded or shall be retried or finally failed. - Returned SCSI errors shall not lead to a return value indicating failure. - The callers get notified by c->error. An SCSI failure which leads not to - a retry shall be notified via scsi_notify_error(). - The Libburn_log_sg_commandS facility might be of help when problems with - a drive have to be examined. It shall stay disabled for normal use. - @return: 1 success , <=0 failure -*/ -int sg_issue_command(struct burn_drive *d, struct command *c) -{ - int done = 0; - int err; - union ccb *ccb; - - if (d->cam == NULL) { - c->error = 0; - return 0; - } - - c->error = 0; - - ccb = cam_getccb(d->cam); - cam_fill_csio(&ccb->csio, - 1, /* retries */ - NULL, /* cbfncp */ - CAM_DEV_QFRZDIS, /* flags */ - MSG_SIMPLE_Q_TAG, /* tag_action */ - NULL, /* data_ptr */ - 0, /* dxfer_len */ - sizeof (ccb->csio.sense_data), /* sense_len */ - 0, /* cdb_len */ - 30*1000); /* timeout */ - switch (c->dir) { - case TO_DRIVE: - ccb->csio.ccb_h.flags |= CAM_DIR_OUT; - break; - case FROM_DRIVE: - ccb->csio.ccb_h.flags |= CAM_DIR_IN; - break; - case NO_TRANSFER: - ccb->csio.ccb_h.flags |= CAM_DIR_NONE; - break; - } - - ccb->csio.cdb_len = c->oplen; - memcpy(&ccb->csio.cdb_io.cdb_bytes, &c->opcode, c->oplen); - - memset(&ccb->csio.sense_data, 0, sizeof (ccb->csio.sense_data)); - - if (c->page) { - ccb->csio.data_ptr = c->page->data; - if (c->dir == FROM_DRIVE) { - ccb->csio.dxfer_len = BUFFER_SIZE; -/* touch page so we can use valgrind */ - memset(c->page->data, 0, BUFFER_SIZE); - } else { - - /* ts A61115: removed a ssert() */ - if(c->page->bytes <= 0) - return 0; - - ccb->csio.dxfer_len = c->page->bytes; - } - } else { - ccb->csio.data_ptr = NULL; - ccb->csio.dxfer_len = 0; - } - - do { - err = cam_send_ccb(d->cam, ccb); - if (err == -1) { - libdax_msgs_submit(libdax_messenger, - d->global_index, 0x0002010c, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "Failed to transfer command to drive", - errno, 0); - cam_freeccb(ccb); - sg_close_drive(d); - d->released = 1; - d->busy = BURN_DRIVE_IDLE; - c->error = 1; - return -1; - } - /* XXX */ - memcpy(c->sense, &ccb->csio.sense_data, ccb->csio.sense_len); - if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { - if (!c->retry) { - c->error = 1; - cam_freeccb(ccb); - return 1; - } - switch (scsi_error(d, c->sense, 0)) { - case RETRY: - done = 0; - break; - case FAIL: - done = 1; - c->error = 1; - break; - } - } else { - done = 1; - } - } while (!done); - cam_freeccb(ccb); - return 1; -} - - -/** Tries to obtain SCSI address parameters. - @return 1 is success , 0 is failure -*/ -int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no, - int *target_no, int *lun_no) -{ - burn_drive_enumerator_t idx; - int initialize = 1; - char buf[64]; - struct periph_match_result* result; - - while(1) { - ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize); - initialize = 0; - if (ret <= 0) - break; - if (strcmp(adr, buf) != 0) - continue; - result = &(idx->ccb.cdm.matches[i].result.periph_result); - *bus_no = result->path_id; - *host_no = result->path_id; - *channel_no = 0; - *target_no = result->target_id - *lun_no = result->target_lun; - sg_give_next_adr(&idx, buf, sizeof(buf), -1); - return 1; - } - sg_give_next_adr(&idx, buf, sizeof(buf), -1); - return (0); -} - - -/** Tells wether a text is a persistent address as listed by the enumeration - functions. -*/ -int sg_is_enumerable_adr(char* adr) -{ - burn_drive_enumerator_t idx; - int initialize = 1; - char buf[64]; - - while(1) { - ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize); - initialize = 0; - if (ret <= 0) - break; - if (strcmp(adr, buf) == 0) { - sg_give_next_adr(&idx, buf, sizeof(buf), -1); - return 1; - } - } - sg_give_next_adr(&idx, buf, sizeof(buf), -1); - return (0); -} - - -/* 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; -} - diff --git a/libburn/sg-freebsd.c b/libburn/sg-freebsd.c deleted file mode 100644 index 67e2993..0000000 --- a/libburn/sg-freebsd.c +++ /dev/null @@ -1,673 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#include <assert.h> -#include <errno.h> -#include <unistd.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/ioctl.h> -#include <stdlib.h> -#include <string.h> -#include <sys/poll.h> -#include <camlib.h> -#include <cam/scsi/scsi_message.h> -#include <cam/scsi/scsi_pass.h> - -#include <err.h> /* XXX */ - - -/* ts A70909 : >>> untestet yet wether this compiles */ -#include <sys/statvfs.h> - - -#include "transport.h" -#include "drive.h" -#include "sg.h" -#include "spc.h" -#include "mmc.h" -#include "sbc.h" -#include "debug.h" -#include "toc.h" -#include "util.h" - -#include "libdax_msgs.h" -extern struct libdax_msgs *libdax_messenger; - -struct burn_drive_enumeration_state { - int fd; - union ccb ccb; - unsigned int i; - int skip_device; -}; - -static void enumerate_common(char *fname, int bus_no, int host_no, - int channel_no, int target_no, int lun_no); - -/* ts A51221 */ -int burn_drive_is_banned(char *device_address); - - -/* ts A60821 - debug: for tracing calls which might use open drive fds - or for catching SCSI usage of emulated drives. */ -int mmc_function_spy(struct burn_drive *d, char * text); - - -/* ts A61021 : Moved most code from scsi_enumerate_drives under - sg_give_next_adr() */ -/* Some helper functions for scsi_give_next_adr() */ - -static int sg_init_enumerator(burn_drive_enumerator_t *idx_) -{ - struct burn_drive_enumeration_state *idx; - int bufsize; - - idx = malloc(sizeof(*idx)); - if (idx == NULL) { - warnx("can't malloc memory for enumerator"); - return -1; - } - idx->skip_device = 0; - - if ((idx->fd = open(XPT_DEVICE, O_RDWR)) == -1) { - warn("couldn't open %s", XPT_DEVICE); - return -1; - } - - bzero(&(idx->ccb), sizeof(union ccb)); - - idx->ccb.ccb_h.path_id = CAM_XPT_PATH_ID; - idx->ccb.ccb_h.target_id = CAM_TARGET_WILDCARD; - idx->ccb.ccb_h.target_lun = CAM_LUN_WILDCARD; - - idx->ccb.ccb_h.func_code = XPT_DEV_MATCH; - bufsize = sizeof(struct dev_match_result) * 100; - idx->ccb.cdm.match_buf_len = bufsize; - idx->ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize); - if (idx->ccb.cdm.matches == NULL) { - warnx("can't malloc memory for matches"); - close(idx->fd); - free(idx); - return -1; - } - idx->ccb.cdm.num_matches = 0; - idx->i = idx->ccb.cdm.num_matches; /* to trigger buffer load */ - - /* - * We fetch all nodes, since we display most of them in the default - * case, and all in the verbose case. - */ - idx->ccb.cdm.num_patterns = 0; - idx->ccb.cdm.pattern_buf_len = 0; - - *idx_ = idx; - - return 1; -} - -static void sg_destroy_enumerator(burn_drive_enumerator_t *idx_) -{ - struct burn_drive_enumeration_state *idx = *idx_; - - if(idx->fd != -1) - close(idx->fd); - - free(idx->ccb.cdm.matches); - free(idx); - - *idx_ = NULL; -} - -static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx_) -{ - struct burn_drive_enumeration_state *idx = *idx_; - - /* - * We do the ioctl multiple times if necessary, in case there are - * more than 100 nodes in the EDT. - */ - if (ioctl(idx->fd, CAMIOCOMMAND, &(idx->ccb)) == -1) { - warn("error sending CAMIOCOMMAND ioctl"); - return -1; - } - - if ((idx->ccb.ccb_h.status != CAM_REQ_CMP) - || ((idx->ccb.cdm.status != CAM_DEV_MATCH_LAST) - && (idx->ccb.cdm.status != CAM_DEV_MATCH_MORE))) { - warnx("got CAM error %#x, CDM error %d\n", - idx->ccb.ccb_h.status, idx->ccb.cdm.status); - return -1; - } - return 1; -} - - -/** Returns the next index number and the next enumerated drive address. - @param idx An opaque handle. Make no own theories about it. - @param adr Takes the reply - @param adr_size Gives maximum size of reply including final 0 - @param initialize 1 = start new, - 0 = continue, use no other values for now - -1 = finish - @return 1 = reply is a valid address , 0 = no further address available - -1 = severe error (e.g. adr_size too small) -*/ -int sg_give_next_adr(burn_drive_enumerator_t *idx_, - char adr[], int adr_size, int initialize) -{ - struct burn_drive_enumeration_state *idx; - int ret; - - if (initialize == 1) { - ret = sg_init_enumerator(idx_); - if (ret<=0) - return ret; - } else if (initialize == -1) { - sg_destroy_enumerator(idx_); - return 0; - } - - idx = *idx_; - - do { - if (idx->i >= idx->ccb.cdm.num_matches) { - ret = sg_next_enumeration_buffer(idx_); - if (ret<=0) - return -1; - idx->i = 0; - } else - (idx->i)++; - - while (idx->i < idx->ccb.cdm.num_matches) { - switch (idx->ccb.cdm.matches[idx->i].type) { - case DEV_MATCH_BUS: - break; - case DEV_MATCH_DEVICE: { - struct device_match_result* result; - - result = &(idx->ccb.cdm.matches[idx->i].result.device_result); - if (result->flags & DEV_RESULT_UNCONFIGURED) - idx->skip_device = 1; - else - idx->skip_device = 0; - break; - } - case DEV_MATCH_PERIPH: { - struct periph_match_result* result; - - result = &(idx->ccb.cdm.matches[idx->i].result.periph_result); - if (idx->skip_device || - strcmp(result->periph_name, "pass") == 0) - break; - ret = snprintf(adr, adr_size, "/dev/%s%d", - result->periph_name, result->unit_number); - if(ret >= adr_size) - return -1; - - /* Found next enumerable address */ - return 1; - - } - default: - /* printf(stderr, "unknown match type\n"); */ - break; - } - (idx->i)++; - } - } while ((idx->ccb.ccb_h.status == CAM_REQ_CMP) - && (idx->ccb.cdm.status == CAM_DEV_MATCH_MORE)); - - return 0; -} - - -int sg_is_enumerable_adr(char* adr) -{ - burn_drive_enumerator_t idx; - int ret; - char buf[64]; - - ret = sg_init_enumerator(&idx); - if (ret <= 0) - return 0; - while(1) { - ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0); - if (ret <= 0) - break; - if (strcmp(adr, buf) == 0) { - sg_destroy_enumerator(&idx); - return 1; - } - } - sg_destroy_enumerator(&idx); - return (0); -} - - -/** Try to obtain SCSI address parameters. - @return 1 is success , 0 is failure -*/ -int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no, - int *target_no, int *lun_no) -{ - burn_drive_enumerator_t idx; - int ret; - char buf[64]; - struct periph_match_result* result; - - ret = sg_init_enumerator(&idx); - if (ret <= 0) - return 0; - while(1) { - ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0); - if (ret <= 0) - break; - if (strcmp(path, buf) == 0) { - result = &(idx->ccb.cdm.matches[idx->i].result.periph_result); - *bus_no = result->path_id; - *host_no = result->path_id; - *channel_no = 0; - *target_no = result->target_id; - *lun_no = result->target_lun; - sg_destroy_enumerator(&idx); - return 1; - } - } - sg_destroy_enumerator(&idx); - return (0); -} - - -int sg_close_drive(struct burn_drive * d) -{ - if (d->cam != NULL) { - cam_close_device(d->cam); - d->cam = NULL; - } - return 0; -} - -int sg_drive_is_open(struct burn_drive * d) -{ - return (d->cam != NULL); -} - -int scsi_enumerate_drives(void) -{ - burn_drive_enumerator_t idx; - int ret; - char buf[64]; - struct periph_match_result* result; - - ret = sg_init_enumerator(&idx); - if (ret <= 0) - return 0; - while(1) { - ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0); - if (ret <= 0) - break; - if (burn_drive_is_banned(buf)) - continue; - result = &idx->ccb.cdm.matches[idx->i].result.periph_result; - enumerate_common(buf, result->path_id, result->path_id, - 0, result->target_id, - result->target_lun); - } - sg_destroy_enumerator(&idx); - - return 1; -} - - -#ifdef Scsi_freebsd_make_own_enumeratE - -/* ts A61021: The old version which mixes SCSI and operating system adapter -*/ -static void enumerate_common(char *fname, int bus_no, int host_no, - int channel_no, int target_no, int lun_no) -{ - struct burn_drive *t; - struct burn_drive out; - - /* ts A60923 */ - out.bus_no = bus_no; - out.host = host_no; - out.id = target_no; - out.channel = channel_no; - out.lun = lun_no; - - out.devname = burn_strdup(fname); - out.cam = NULL; - - out.start_lba= -2000000000; - out.end_lba= -2000000000; - out.read_atip = mmc_read_atip; - - out.grab = sg_grab; - out.release = sg_release; - out.drive_is_open= sg_drive_is_open; - out.issue_command = sg_issue_command; - out.getcaps = spc_getcaps; - out.released = 1; - out.status = BURN_DISC_UNREADY; - - out.eject = sbc_eject; - out.load = sbc_load; - out.lock = spc_prevent; - out.unlock = spc_allow; - out.read_disc_info = spc_sense_write_params; - out.get_erase_progress = spc_get_erase_progress; - out.test_unit_ready = spc_test_unit_ready; - out.probe_write_modes = spc_probe_write_modes; - out.read_toc = mmc_read_toc; - out.write = mmc_write; - out.erase = mmc_erase; - out.read_sectors = mmc_read_sectors; - out.perform_opc = mmc_perform_opc; - out.set_speed = mmc_set_speed; - out.send_parameters = spc_select_error_params; - out.send_write_parameters = spc_select_write_params; - out.send_cue_sheet = mmc_send_cue_sheet; - out.sync_cache = mmc_sync_cache; - out.get_nwa = mmc_get_nwa; - out.close_disc = mmc_close_disc; - out.close_session = mmc_close_session; - out.close_track_session = mmc_close; - out.read_buffer_capacity = mmc_read_buffer_capacity; - out.idata = malloc(sizeof(struct burn_scsi_inquiry_data)); - out.idata->valid = 0; - out.mdata = malloc(sizeof(struct scsi_mode_data)); - out.mdata->valid = 0; - if (out.idata == NULL || out.mdata == NULL) { - libdax_msgs_submit(libdax_messenger, -1, 0x00020108, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "Could not allocate new drive object", 0, 0); - return; - } - memset(&out.params, 0, sizeof(struct params)); - t = burn_drive_register(&out); - -/* ts A60821 - <<< debug: for tracing calls which might use open drive fds */ - mmc_function_spy(NULL, "enumerate_common : -------- doing grab"); - -/* try to get the drive info */ - if (t->grab(t)) { - burn_print(2, "getting drive info\n"); - t->getcaps(t); - t->unlock(t); - t->released = 1; - } else { - burn_print(2, "unable to grab new located drive\n"); - } - -/* ts A60821 - <<< debug: for tracing calls which might use open drive fds */ - mmc_function_spy(NULL, "enumerate_common : ----- would release "); - -} - -#else /* Scsi_freebsd_make_own_enumeratE */ - -/* The new, more concise version of enumerate_common */ -static void enumerate_common(char *fname, int bus_no, int host_no, - int channel_no, int target_no, int lun_no) -{ - int ret; - struct burn_drive out; - - /* General libburn drive setup */ - burn_setup_drive(&out, fname); - - /* This transport adapter uses SCSI-family commands and models - (seems the adapter would know better than its boss, if ever) */ - ret = burn_scsi_setup_drive(&out, bus_no, host_no, channel_no, - target_no, lun_no, 0); - if (ret<=0) - return; - - /* Operating system adapter is CAM */ - /* Adapter specific handles and data */ - out.cam = NULL; - /* Adapter specific functions */ - out.grab = sg_grab; - out.release = sg_release; - out.drive_is_open = sg_drive_is_open; - out.issue_command = sg_issue_command; - - /* Finally register drive and inquire drive information */ - burn_drive_finish_enum(&out); -} - -#endif /* ! Scsi_freebsd_make_own_enumeratE */ - -/* ts A61021: do not believe this: - we use the sg reference count to decide whether we can use the - drive or not. - if refcount is not one, drive is open somewhere else. -*/ -int sg_grab(struct burn_drive *d) -{ - int count; - struct cam_device *cam; - - if (mmc_function_spy(d, "sg_grab") <= 0) - return 0; - - if (burn_drive_is_open(d)) { - d->released = 0; - return 1; - } - - cam = cam_open_device(d->devname, O_RDWR); - if (cam == NULL) { - libdax_msgs_submit(libdax_messenger, d->global_index, 0x00020003, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Could not grab drive", 0/*os_errno*/, 0); - return 0; - } -/* er = ioctl(fd, SG_GET_ACCESS_COUNT, &count);*/ - count = 1; - if (1 == count) { - d->cam = cam; - fcntl(cam->fd, F_SETOWN, getpid()); - d->released = 0; - return 1; - } - burn_print(1, "could not acquire drive - already open\n"); - sg_close_drive(d); - return 0; -} - - -/* - non zero return means you still have the drive and it's not - in a state to be released? (is that even possible?) -*/ - -int sg_release(struct burn_drive *d) -{ - if (mmc_function_spy(d, "sg_release") <= 0) - return 0; - - if (d->cam == NULL) { - burn_print(1, "release an ungrabbed drive. die\n"); - return 0; - } - - mmc_function_spy(NULL, "sg_release ----------- closing."); - - sg_close_drive(d); - d->released = 1; - return 0; -} - -int sg_issue_command(struct burn_drive *d, struct command *c) -{ - int done = 0; - int err; - union ccb *ccb; - - char buf[161]; - snprintf(buf, sizeof (buf), "sg_issue_command d->cam=%p d->released=%d", - (void*)d->cam, d->released); - mmc_function_spy(NULL, buf); - - if (d->cam == NULL) { - c->error = 0; - return 0; - } - - c->error = 0; - - ccb = cam_getccb(d->cam); - cam_fill_csio(&ccb->csio, - 1, /* retries */ - NULL, /* cbfncp */ - CAM_DEV_QFRZDIS, /* flags */ - MSG_SIMPLE_Q_TAG, /* tag_action */ - NULL, /* data_ptr */ - 0, /* dxfer_len */ - sizeof (ccb->csio.sense_data), /* sense_len */ - 0, /* cdb_len */ - 30*1000); /* timeout */ - switch (c->dir) { - case TO_DRIVE: - ccb->csio.ccb_h.flags |= CAM_DIR_OUT; - break; - case FROM_DRIVE: - ccb->csio.ccb_h.flags |= CAM_DIR_IN; - break; - case NO_TRANSFER: - ccb->csio.ccb_h.flags |= CAM_DIR_NONE; - break; - } - - ccb->csio.cdb_len = c->oplen; - memcpy(&ccb->csio.cdb_io.cdb_bytes, &c->opcode, c->oplen); - - memset(&ccb->csio.sense_data, 0, sizeof (ccb->csio.sense_data)); - - if (c->page) { - ccb->csio.data_ptr = c->page->data; - if (c->dir == FROM_DRIVE) { - ccb->csio.dxfer_len = BUFFER_SIZE; -/* touch page so we can use valgrind */ - memset(c->page->data, 0, BUFFER_SIZE); - } else { - assert(c->page->bytes > 0); - ccb->csio.dxfer_len = c->page->bytes; - } - } else { - ccb->csio.data_ptr = NULL; - ccb->csio.dxfer_len = 0; - } - - do { - err = cam_send_ccb(d->cam, ccb); - if (err == -1) { - libdax_msgs_submit(libdax_messenger, - d->global_index, 0x0002010c, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "Failed to transfer command to drive", - errno, 0); - cam_freeccb(ccb); - sg_close_drive(d); - d->released = 1; - d->busy = BURN_DRIVE_IDLE; - c->error = 1; - return -1; - } - /* XXX */ - memcpy(c->sense, &ccb->csio.sense_data, ccb->csio.sense_len); - if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { - if (!c->retry) { - c->error = 1; - cam_freeccb(ccb); - return 1; - } - switch (scsi_error(d, c->sense, 0)) { - case RETRY: - done = 0; - break; - case FAIL: - done = 1; - c->error = 1; - break; - } - } else { - done = 1; - } - } while (!done); - cam_freeccb(ccb); - return 1; -} - - -/* 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; -} - diff --git a/libburn/sg-linux.c b/libburn/sg-linux.c deleted file mode 100644 index 8f70f7d..0000000 --- a/libburn/sg-linux.c +++ /dev/null @@ -1,1444 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -/* - -This is the main operating system dependent SCSI part of libburn. It implements -the transport level aspects of SCSI control and command i/o. - -Present implementation: Linux SCSI Generic (sg) - - -PORTING: - -Porting libburn typically will consist of adding a new operating system case -to the following switcher files: - os.h Operating system specific libburn definitions and declarations. - sg.c Operating system dependent transport level modules. -and of deriving the following system specific files from existing examples: - os-*.h Included by os.h. You will need some general system knowledge - about signals and knowledge about the storage object needs of your - transport level module sg-*.c. - - sg-*.c This source module. You will need special system knowledge about - how to detect all potentially available drives, how to open them, - eventually how to exclusively reserve them, how to perform - SCSI transactions, how to inquire the (pseudo-)SCSI driver. - You will not need to care about CD burning, MMC or other high-level - SCSI aspects. - -Said sg-*.c operations are defined by a public function interface, which has -to be implemented in a way that provides libburn with the desired services: - -sg_give_next_adr() iterates over the set of potentially useful drive - address strings. - -scsi_enumerate_drives() brings all available, not-whitelist-banned, and - accessible drives into libburn's list of drives. - -sg_drive_is_open() tells wether libburn has the given drive in use. - -sg_grab() opens the drive for SCSI commands and ensures - undisturbed access. - -sg_release() closes a drive opened by sg_grab() - -sg_issue_command() sends a SCSI command to the drive, receives reply, - and evaluates wether the command succeeded or shall - be retried or finally failed. - -sg_obtain_scsi_adr() tries to obtain SCSI address parameters. - -burn_os_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 . - -Hint: You should also look into sg-freebsd-port.c, which is a younger and - in some aspects more straightforward implementation of this interface. - -*/ - - -/** PORTING : ------- OS dependent headers and definitions ------ */ - -#include <errno.h> -#include <unistd.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/ioctl.h> -#include <string.h> -#include <sys/poll.h> -#include <linux/hdreg.h> -#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) : */ -/* .host_status : from http://tldp.org/HOWTO/SCSI-Generic-HOWTO/x291.html */ -#define Libburn_sg_host_oK 0 -/* .driver_status : from http://tldp.org/HOWTO/SCSI-Generic-HOWTO/x322.html */ -#define Libburn_sg_driver_oK 0 - - -/* ts A61211 : to eventually recognize CD devices on /dev/sr* */ -#include <limits.h> -#include <linux/cdrom.h> - - -/** Indication of the Linux kernel this software is running on */ -/* -1 = not evaluated , 0 = unrecognizable , 1 = 2.4 , 2 = 2.6 */ -static int sg_kernel_age = -1; - - -/** PORTING : Device file families for bus scanning and drive access. - Both device families must support the following ioctls: - SG_IO, - SG_GET_SCSI_ID - SCSI_IOCTL_GET_BUS_NUMBER - SCSI_IOCTL_GET_IDLUN - as well as mutual exclusively locking with open(O_EXCL). - If a device family is left empty, then it will not be used. - - To avoid misunderstandings: both families are used via identical - transport methods as soon as a device file is accepted as CD drive - by the family specific function <family>_enumerate(). - One difference remains throughout usage: Host,Channel,Id,Lun and Bus - address parameters of ATA devices are considered invalid. -*/ - -/* Set this to 1 in order to get on stderr messages from sg_enumerate() */ -static int linux_sg_enumerate_debug = 0; - - -/* The device file family to use for (emulated) generic SCSI transport. - This must be a printf formatter with one single placeholder for int - in the range of 0 to 31 . The resulting addresses must provide SCSI - address parameters Host, Channel, Id, Lun and also Bus. - E.g.: "/dev/sg%d" - sr%d is supposed to map only CD-ROM style devices. Additionally a test - with ioctl(CDROM_DRIVE_STATUS) is made to assert that it is such a drive, - - This initial setting may be overridden in sg_select_device_family() by - settings made via burn_preset_device_open(). -*/ -static char linux_sg_device_family[80] = {"/dev/sg%d"}; - -/* Set this to 1 if you want the default linux_sg_device_family chosen - depending on kernel release: sg for <2.6 , sr for >=2.6 -*/ -static int linux_sg_auto_family = 1; - - -/* Set this to 1 in order to accept any TYPE_* (see scsi/scsi.h) */ -/* But try with 0 first. There is hope via CDROM_DRIVE_STATUS. */ -/* !!! DO NOT SET TO 1 UNLESS YOU PROTECTED ALL INDISPENSIBLE DEVICES - chmod -rw !!! */ -static int linux_sg_accept_any_type = 0; - - -/* The device file family to use for SCSI transport over ATA. - This must be a printf formatter with one single placeholder for a - _single_ char in the range of 'a' to 'z'. This placeholder _must_ be - at the end of the formatter string. - E.g. "/dev/hd%c" -*/ -static char linux_ata_device_family[80] = {"/dev/hd%c"}; - -/* Set this to 1 in order to get on stderr messages from ata_enumerate() -*/ -static int linux_ata_enumerate_verbous = 0; - - - -/** PORTING : ------ libburn portable headers and definitions ----- */ - -#include "transport.h" -#include "drive.h" -#include "sg.h" -#include "spc.h" -#include "mmc.h" -#include "sbc.h" -#include "debug.h" -#include "toc.h" -#include "util.h" - -#include "libdax_msgs.h" -extern struct libdax_msgs *libdax_messenger; - -/* ts A51221 */ -int burn_drive_is_banned(char *device_address); - - -/* ------------------------------------------------------------------------ */ -/* PORTING: Private definitions. Port only if needed by public functions. */ -/* (Public functions are listed below) */ -/* ------------------------------------------------------------------------ */ - - -static void enumerate_common(char *fname, int bus_no, int host_no, - int channel_no, int target_no, int lun_no); - - -/* ts A60813 : storage objects are in libburn/init.c - wether to use O_EXCL with open(2) of devices - wether to use fcntl(,F_SETLK,) after open(2) of devices - what device family to use : 0=default, 1=sr, 2=scd, (3=st), 4=sg - wether to use O_NOBLOCK with open(2) on devices - wether to take O_EXCL rejection as fatal error */ -extern int burn_sg_open_o_excl; -extern int burn_sg_fcntl_f_setlk; -extern int burn_sg_use_family; -extern int burn_sg_open_o_nonblock; -extern int burn_sg_open_abort_busy; - - -/* ts A60821 - debug: for tracing calls which might use open drive fds - or for catching SCSI usage of emulated drives. */ -int mmc_function_spy(struct burn_drive *d, char * text); - - -/* ------------------------------------------------------------------------ */ -/* PORTING: Private functions. Port only if needed by public functions */ -/* (Public functions are listed below) */ -/* ------------------------------------------------------------------------ */ - -/* ts A70413 */ -/* This finds out wether the software is running on kernel >= 2.6 -*/ -static void sg_evaluate_kernel(void) -{ - struct utsname buf; - if (sg_kernel_age >= 0) - return; - - sg_kernel_age = 0; - if (uname(&buf) == -1) - return; - sg_kernel_age = 1; - if (strcmp(buf.release, "2.6") >= 0) - sg_kernel_age = 2; -} - - -/* ts A70314 */ -/* This installs the device file family if one was chosen explicitely - by burn_preset_device_open() -*/ -static void sg_select_device_family(void) -{ - - /* >>> ??? do we need a mutex here ? */ - /* >>> (It might be concurrent but is supposed to have always - the same effect. Any race condition should be harmless.) */ - - if (burn_sg_use_family == 1) - strcpy(linux_sg_device_family, "/dev/sr%d"); - else if (burn_sg_use_family == 2) - strcpy(linux_sg_device_family, "/dev/scd%d"); - else if (burn_sg_use_family == 3) - strcpy(linux_sg_device_family, "/dev/st%d"); - else if (burn_sg_use_family == 4) - strcpy(linux_sg_device_family, "/dev/sg%d"); - else if (linux_sg_auto_family) { - sg_evaluate_kernel(); - if (sg_kernel_age >= 2) - strcpy(linux_sg_device_family, "/dev/sr%d"); - else - strcpy(linux_sg_device_family, "/dev/sg%d"); - linux_sg_auto_family = 0; - } -} - - -static int sgio_test(int fd) -{ - unsigned char test_ops[] = { 0, 0, 0, 0, 0, 0 }; - sg_io_hdr_t s; - - memset(&s, 0, sizeof(sg_io_hdr_t)); - s.interface_id = 'S'; - s.dxfer_direction = SG_DXFER_NONE; - s.cmd_len = 6; - s.cmdp = test_ops; - s.timeout = 12345; - return ioctl(fd, SG_IO, &s); -} - - -/* ts A60924 */ -static int sg_handle_busy_device(char *fname, int os_errno) -{ - char msg[4096]; - - /* ts A60814 : i saw no way to do this more nicely */ - if (burn_sg_open_abort_busy) { - fprintf(stderr, - "\nlibburn: FATAL : Application triggered abort on busy device '%s'\n", - fname); - - /* ts A61007 */ - abort(); - /* a ssert("drive busy" == "non fatal"); */ - } - - /* ts A60924 : now reporting to libdax_msgs */ - sprintf(msg, "Cannot open busy device '%s'", fname); - libdax_msgs_submit(libdax_messenger, -1, 0x00020001, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_LOW, - msg, os_errno, 0); - return 1; -} - - -/* ts A60925 : ticket 74 */ -static int sg_close_drive_fd(char *fname, int driveno, int *fd, int sorry) -{ - int ret, os_errno, sevno= LIBDAX_MSGS_SEV_DEBUG; - char msg[4096+100]; - - if(*fd < 0) - return(0); - -#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) { - /* ts A70409 : DDLP-B */ - /* >>> release single lock on fname */ - return 1; - } - os_errno= errno; - - sprintf(msg, "Encountered error when closing drive '%s'", fname); - if (sorry) - sevno = LIBDAX_MSGS_SEV_SORRY; - libdax_msgs_submit(libdax_messenger, driveno, 0x00020002, - sevno, LIBDAX_MSGS_PRIO_HIGH, msg, os_errno, 0); - return 0; -} - - -/* ts A70401 : - fcntl() has the unappealing property to work only after open(). - So libburn will by default use open(O_EXCL) first and afterwards - as second assertion will use fcntl(F_SETLK). One lock more should not harm. -*/ -static int sg_fcntl_lock(int *fd, char *fd_name, int l_type, int verbous) -{ - struct flock lockthing; - char msg[81]; - int ret; - - if (!burn_sg_fcntl_f_setlk) - return 1; - - memset(&lockthing, 0, sizeof(lockthing)); - lockthing.l_type = l_type; - lockthing.l_whence = SEEK_SET; - lockthing.l_start = 0; - lockthing.l_len = 0; -/* - fprintf(stderr,"LIBBURN_EXPERIMENTAL: fcntl(%d, F_SETLK, %s)\n", - *fd, l_type == F_WRLCK ? "F_WRLCK" : "F_RDLCK"); -*/ - - ret = fcntl(*fd, F_SETLK, &lockthing); - if (ret == -1) { - if (verbous) { - sprintf(msg, "Device busy. Failed to fcntl-lock '%s'", - fd_name); - libdax_msgs_submit(libdax_messenger, -1, 0x00020008, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - msg, errno, 0); - } - close(*fd); - *fd = -1; - - /* ts A70409 : DDLP-B */ - /* >>> release single lock on fd_name */ - - return(0); - } - return 1; -} - - -/* ts A60926 */ -static int sg_open_drive_fd(char *fname, int scan_mode) -{ - int open_mode = O_RDWR, fd; - char msg[81]; - - /* ts A70409 : DDLP-B */ - /* >>> obtain single lock on fname */ - - /* ts A60813 - A60927 - O_EXCL with devices is a non-POSIX feature - of Linux kernels. Possibly introduced 2002. - Mentioned in "The Linux SCSI Generic (sg) HOWTO" */ - if(burn_sg_open_o_excl) - open_mode |= O_EXCL; - /* ts A60813 - O_NONBLOCK was already hardcoded in ata_ but not in sg_. - There must be some reason for this. So O_NONBLOCK is - default mode for both now. Disable on own risk. - ts A70411 - Switched to O_NDELAY for LKML statement 2007/4/11/141 by Alan Cox: - "open() has side effects. The CD layer allows you to open - with O_NDELAY if you want to avoid them." - */ - if(burn_sg_open_o_nonblock) - open_mode |= O_NDELAY; - -/* <<< debugging - fprintf(stderr, - "\nlibburn: experimental: o_excl= %d , o_nonblock= %d, abort_on_busy= %d\n", - burn_sg_open_o_excl,burn_sg_open_o_nonblock,burn_sg_open_abort_busy); - fprintf(stderr, - "libburn: experimental: O_EXCL= %d , O_NDELAY= %d\n", - !!(open_mode&O_EXCL),!!(open_mode&O_NDELAY)); -*/ - - fd = open(fname, open_mode); - if (fd == -1) { -/* <<< debugging - fprintf(stderr, - "\nlibburn: experimental: fname= %s , errno= %d\n", - fname,errno); -*/ - if (errno == EBUSY) { - sg_handle_busy_device(fname, errno); - return -1; - - } - if (scan_mode) - return -1; - sprintf(msg, "Failed to open device '%s'",fname); - libdax_msgs_submit(libdax_messenger, -1, 0x00020005, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - msg, errno, 0); - return -1; - } - sg_fcntl_lock(&fd, fname, F_WRLCK, 1); - return fd; -} - - -/* ts A60926 */ -static int sg_release_siblings(int sibling_fds[], - char sibling_fnames[][BURN_OS_SG_MAX_NAMELEN], - int *sibling_count) -{ - int i; - char msg[81]; - - for(i= 0; i < *sibling_count; i++) - sg_close_drive_fd(sibling_fnames[i], -1, &(sibling_fds[i]), 0); - if(*sibling_count > 0) { - sprintf(msg, "Closed %d O_EXCL scsi siblings", *sibling_count); - libdax_msgs_submit(libdax_messenger, -1, 0x00020007, - LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH, msg, 0,0); - } - *sibling_count = 0; - return 1; -} - - -/* ts A60926 */ -static int sg_close_drive(struct burn_drive *d) -{ - int ret; - - if (!burn_drive_is_open(d)) - return 0; - sg_release_siblings(d->sibling_fds, d->sibling_fnames, - &(d->sibling_count)); - ret = sg_close_drive_fd(d->devname, d->global_index, &(d->fd), 0); - return ret; -} - - -/* ts A60926 */ -static int sg_open_scsi_siblings(char *path, int driveno, - int sibling_fds[], - char sibling_fnames[][BURN_OS_SG_MAX_NAMELEN], - int *sibling_count, - int host_no, int channel_no, int id_no, int lun_no) -{ - int tld, i, ret, fd, i_bus_no = -1; - int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1; - char msg[161], fname[81]; - struct stat stbuf; - dev_t last_rdev = 0, path_rdev; - - static char tldev[][81]= {"/dev/sr%d", "/dev/scd%d", "/dev/sg%d", ""}; - /* ts A70609: removed "/dev/st%d" */ - - if(stat(path, &stbuf) == -1) - return 0; - path_rdev = stbuf.st_rdev; - - sg_select_device_family(); - if (linux_sg_device_family[0] == 0) - return 1; - - if(host_no < 0 || id_no < 0 || channel_no < 0 || lun_no < 0) - return(2); - if(*sibling_count > 0) - sg_release_siblings(sibling_fds, sibling_fnames, - sibling_count); - - for (tld = 0; tldev[tld][0] != 0; tld++) { - if (strcmp(tldev[tld], linux_sg_device_family)==0) - continue; - for (i = 0; i < 32; i++) { - sprintf(fname, tldev[tld], i); - if(stat(fname, &stbuf) == -1) - continue; - if (path_rdev == stbuf.st_rdev) - continue; - if (*sibling_count > 0 && last_rdev == stbuf.st_rdev) - continue; - ret = sg_obtain_scsi_adr(fname, &i_bus_no, &i_host_no, - &i_channel_no, &i_target_no, &i_lun_no); - if (ret <= 0) - continue; - if (i_host_no != host_no || i_channel_no != channel_no) - continue; - if (i_target_no != id_no || i_lun_no != lun_no) - continue; - - fd = sg_open_drive_fd(fname, 0); - if (fd < 0) - goto failed; - - if (*sibling_count>=BURN_OS_SG_MAX_SIBLINGS) { - sprintf(msg, "Too many scsi siblings of '%s'", - path); - libdax_msgs_submit(libdax_messenger, - driveno, 0x00020006, - LIBDAX_MSGS_SEV_FATAL, - LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0); - goto failed; - } - sprintf(msg, "Opened O_EXCL scsi sibling '%s' of '%s'", - fname, path); - libdax_msgs_submit(libdax_messenger, driveno, - 0x00020004, - LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - sibling_fds[*sibling_count] = fd; - strcpy(sibling_fnames[*sibling_count], fname); - (*sibling_count)++; - last_rdev= stbuf.st_rdev; - } - } - return 1; -failed:; - sg_release_siblings(sibling_fds, sibling_fnames, sibling_count); - return 0; -} - - -/** 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) -{ - struct hd_driveid tm; - int i, fd; - char fname[10]; - - if (linux_ata_enumerate_verbous) - fprintf(stderr, "libburn_debug: linux_ata_device_family = %s\n", - linux_ata_device_family); - - if (linux_ata_device_family[0] == 0) - return; - - for (i = 0; i < 26; i++) { - sprintf(fname, linux_ata_device_family, 'a' + i); - if (linux_ata_enumerate_verbous) - fprintf(stderr, "libburn_debug: %s : ", fname); - - /* ts A51221 */ - if (burn_drive_is_banned(fname)) { - if (linux_ata_enumerate_verbous) - fprintf(stderr, "not in whitelist\n"); - continue; - } - 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)); - continue; - } - - /* found a drive */ - 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); - continue; - } - - /* 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; - } - 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)); - continue; - } - if (linux_ata_enumerate_verbous) - fprintf(stderr, "accepting as drive without SCSI address\n"); - enumerate_common(fname, -1, -1, -1, -1, -1); - } -} - - -/** Detects (probably emulated) SCSI drives */ -static void sg_enumerate(void) -{ - struct sg_scsi_id sid; - int i, fd, sibling_fds[BURN_OS_SG_MAX_SIBLINGS], sibling_count= 0, ret; - int sid_ret = 0; - int bus_no= -1, host_no= -1, channel_no= -1, target_no= -1, lun_no= -1; - char fname[10]; - char sibling_fnames[BURN_OS_SG_MAX_SIBLINGS][BURN_OS_SG_MAX_NAMELEN]; - - sg_select_device_family(); - - if (linux_sg_enumerate_debug) - fprintf(stderr, "libburn_debug: linux_sg_device_family = %s\n", - linux_sg_device_family); - - if (linux_sg_device_family[0] == 0) - return; - - for (i = 0; i < 32; i++) { - sprintf(fname, linux_sg_device_family, i); - - if (linux_sg_enumerate_debug) - fprintf(stderr, "libburn_debug: %s : ", fname); - - /* ts A51221 */ - if (burn_drive_is_banned(fname)) { - if (linux_sg_enumerate_debug) - fprintf(stderr, "not in whitelist\n"); - continue; - } - - /* ts A60927 */ - 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)); - continue; - } - - /* found a drive */ - 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); - continue; - } - -#ifdef CDROM_DRIVE_STATUS - /* ts A61211 : not widening old acceptance range */ - if (strcmp(linux_sg_device_family,"/dev/sg%d") != 0) { - /* 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)); - continue; - } - 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); - continue; - } - - 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"); - continue; - } - } - - /* ts A60927 : trying to do locking with growisofs */ - if(burn_sg_open_o_excl>1) { - ret = sg_open_scsi_siblings( - fname, -1, sibling_fds, sibling_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); - continue; - } - /* 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 - 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); - } -} - - -/* ts A61115 */ -/* ----------------------------------------------------------------------- */ -/* PORTING: Private functions which contain publicly needed functionality. */ -/* Their portable part must be performed. So it is probably best */ -/* to replace the non-portable part and to call these functions */ -/* in your port, too. */ -/* ----------------------------------------------------------------------- */ - - -/** Wraps a detected drive into libburn structures and hands it over to - libburn drive list. -*/ -/* ts A60923 - A61005 : introduced new SCSI parameters */ -/* ts A61021 : moved non os-specific code to spc,sbc,mmc,drive */ -static void enumerate_common(char *fname, int bus_no, int host_no, - int channel_no, int target_no, int lun_no) -{ - int ret, i; - struct burn_drive out; - - /* General libburn drive setup */ - burn_setup_drive(&out, fname); - - /* This transport adapter uses SCSI-family commands and models - (seems the adapter would know better than its boss, if ever) */ - ret = burn_scsi_setup_drive(&out, bus_no, host_no, channel_no, - target_no, lun_no, 0); - if (ret<=0) - return; - - /* PORTING: ------------------- non portable part --------------- */ - - /* Operating system adapter is Linux Generic SCSI (sg) */ - /* Adapter specific handles and data */ - out.fd = -1337; - out.sibling_count = 0; - for(i= 0; i<BURN_OS_SG_MAX_SIBLINGS; i++) - out.sibling_fds[i] = -1337; - - /* PORTING: ---------------- end of non portable part ------------ */ - - /* Adapter specific functions with standardized names */ - out.grab = sg_grab; - out.release = sg_release; - out.drive_is_open= sg_drive_is_open; - out.issue_command = sg_issue_command; - - /* Finally register drive and inquire drive information */ - burn_drive_finish_enum(&out); -} - - -/* ts A61115 */ -/* ------------------------------------------------------------------------ */ -/* PORTING: Public functions. These MUST be ported. */ -/* ------------------------------------------------------------------------ */ - - -/** PORTING: - In this Linux implementation, this function mirrors the enumeration - done in sg_enumerate and ata_enumerate(). It would be better to base those - functions on this sg_give_next_adr() but the situation is not inviting. -*/ -/* ts A60922 ticket 33 : called from drive.c */ -/** Returns the next index number and the next enumerated drive address. - The enumeration has to cover all available and accessible drives. It is - allowed to return addresses of drives which are not available but under - some (even exotic) circumstances could be available. It is on the other - hand allowed, only to hand out addresses which can really be used right - in the moment of this call. (This implementation chooses the former.) - @param idx An opaque handle. Make no own theories about it. - @param adr Takes the reply - @param adr_size Gives maximum size of reply including final 0 - @param initialize 1 = start new, - 0 = continue, use no other values for now - -1 = finish - @return 1 = reply is a valid address , 0 = no further address available - -1 = severe error (e.g. adr_size too small) -*/ -int sg_give_next_adr(burn_drive_enumerator_t *idx, - char adr[], int adr_size, int initialize) -{ - /* os-linux.h : typedef int burn_drive_enumerator_t; */ - static int sg_limit = 32, ata_limit = 26; - int baseno = 0; - - if (initialize == -1) - return 0; - - sg_select_device_family(); - if (linux_sg_device_family[0] == 0) - sg_limit = 0; - if (linux_ata_device_family[0] == 0) - ata_limit = 0; - - if (initialize == 1) - *idx = -1; - (*idx)++; - if (*idx >= sg_limit) - goto next_ata; - if (adr_size < 10) - return -1; - sprintf(adr, linux_sg_device_family, *idx); - return 1; -next_ata:; - baseno += sg_limit; - if (*idx - baseno >= ata_limit) - goto next_nothing; - if (adr_size < 9) - return -1; - sprintf(adr, linux_ata_device_family, 'a' + (*idx - baseno)); - return 1; -next_nothing:; - baseno += ata_limit; - return 0; -} - - -/** Brings all available, not-whitelist-banned, and accessible drives into - libburn's list of drives. -*/ -/** PORTING: - If not stricken with an incompletely unified situation like in Linux - one would rather implement this by a loop calling sg_give_next_adr(). - If needed with your sg_give_next_adr() results, do a test for existence - and accessability. If burn activities are prone to external interference - on your system it is also necessary to obtain exclusive access locks on - the drives. - Hand over each accepted drive to enumerate_common() resp. its replacement - within your port. - - See FreeBSD port sketch sg-freebsd-port.c for such an implementation. -*/ -/* ts A61115: replacing call to sg-implementation internals from drive.c */ -int scsi_enumerate_drives(void) -{ - sg_enumerate(); - ata_enumerate(); - return 1; -} - - -/** Tells wether libburn has the given drive in use or exclusively reserved. - If it is "open" then libburn will eventually call sg_release() on it when - it is time to give up usage resp. reservation. -*/ -/** Published as burn_drive.drive_is_open() */ -int sg_drive_is_open(struct burn_drive * d) -{ - /* a bit more detailed case distinction than needed */ - if (d->fd == -1337) - return 0; - if (d->fd < 0) - return 0; - return 1; -} - - -/** Opens the drive for SCSI commands and - if burn activities are prone - to external interference on your system - obtains an exclusive access lock - on the drive. (Note: this is not physical tray locking.) - A drive that has been opened with sg_grab() will eventually be handed - over to sg_release() for closing and unreserving. -*/ -int sg_grab(struct burn_drive *d) -{ - int fd, os_errno= 0, ret; - - /* ts A60813 */ - int open_mode = O_RDWR; - -/* ts A60821 - <<< debug: for tracing calls which might use open drive fds */ - if (mmc_function_spy(d, "sg_grab") <= 0) - return 0; - - - /* ts A60813 - A60927 - O_EXCL with devices is a non-POSIX feature - of Linux kernels. Possibly introduced 2002. - Mentioned in "The Linux SCSI Generic (sg) HOWTO". - */ - if(burn_sg_open_o_excl) - open_mode |= O_EXCL; - - /* ts A60813 - O_NONBLOCK was hardcoded here. So it should stay default mode. - ts A70411 - Switched to O_NDELAY for LKML statement 2007/4/11/141 - */ - if(burn_sg_open_o_nonblock) - open_mode |= O_NDELAY; - - /* ts A60813 - A60822 - After enumeration the drive fd is probably still open. - -1337 is the initial value of burn_drive.fd and the value after - relase of drive. Unclear why not the official error return - value -1 of open(2) war used. */ - if(! burn_drive_is_open(d)) { - - /* ts A60821 - <<< debug: for tracing calls which might use open drive fds */ - mmc_function_spy(NULL, "sg_grab ----------- opening"); - - /* ts A70409 : DDLP-B */ - /* >>> obtain single lock on d->devname */ - - /* ts A60926 */ - if(burn_sg_open_o_excl>1) { - fd = -1; - ret = sg_open_scsi_siblings(d->devname, - d->global_index,d->sibling_fds, - d->sibling_fnames,&(d->sibling_count), - d->host, d->channel, d->id, d->lun); - if(ret <= 0) - goto drive_is_in_use; - } - - fd = open(d->devname, open_mode); - os_errno = errno; - if (fd >= 0) { - sg_fcntl_lock(&fd, d->devname, F_WRLCK, 1); - if (fd < 0) - goto drive_is_in_use; - } - } else - fd= d->fd; - - if (fd >= 0) { - d->fd = fd; - fcntl(fd, F_SETOWN, getpid()); - d->released = 0; - return 1; - } - libdax_msgs_submit(libdax_messenger, d->global_index, 0x00020003, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Could not grab drive", os_errno, 0); - return 0; - -drive_is_in_use:; - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020003, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Could not grab drive - already in use", 0, 0); - sg_close_drive(d); - d->fd = -1337; - return 0; -} - - -/** PORTING: Is mainly about the call to sg_close_drive() and wether it - implements the demanded functionality. -*/ -/** Gives up the drive for SCSI commands and releases eventual access locks. - (Note: this is not physical tray locking.) -*/ -int sg_release(struct burn_drive *d) -{ - /* ts A60821 - <<< debug: for tracing calls which might use open drive fds */ - if (mmc_function_spy(d, "sg_release") <= 0) - return 0; - - if (d->fd < 1) { - burn_print(1, "release an ungrabbed drive. die\n"); - return 0; - } - - /* ts A60821 - <<< debug: for tracing calls which might use open drive fds */ - mmc_function_spy(NULL, "sg_release ----------- closing"); - - sg_close_drive(d); - return 0; -} - - -/** ts A70518: - Debugging log facility. Controlled by existence of macros: - Libburn_log_sg_commandS enables logging to file - /tmp/libburn_sg_command_log - Libburn_fflush_log_sg_commandS enables fflush after each output line - Libburn_log_sg_command_stderR enables additional log to stderr -*/ -/* -#define Libburn_log_sg_commandS 1 -#define Libburn_fflush_log_sg_commandS 1 -#define Libburn_log_sg_command_stderR 1 -*/ - -#ifdef Libburn_log_sg_commandS - -/** Logs command (before execution) */ -static int sg_log_cmd(struct command *c, FILE *fp, int flag) -{ - int i; - - if (fp != NULL) { - for(i = 0; i < 16 && i < c->oplen; i++) - fprintf(fp,"%2.2x ", c->opcode[i]); - fprintf(fp, "\n"); -#ifdef Libburn_fflush_log_sg_commandS - fflush(fp); -#endif - } - if (fp == stderr) - return 1; -#ifdef Libburn_log_sg_command_stderR - sg_log_cmd(c, stderr, flag); -#endif - return 1; -} - - -/** logs outcome of a sg command. flag&1 causes an error message */ -static int sg_log_err(struct command *c, FILE *fp, - sg_io_hdr_t *s, - int flag) -{ - if(fp!=NULL) { - if(flag & 1) - fprintf(fp, - "+++ key=%X asc=%2.2Xh ascq=%2.2Xh (%6d ms)\n", - s->sbp[2], s->sbp[12], s->sbp[13],s->duration); - else - fprintf(fp,"%6d ms\n", s->duration); -#ifdef Libburn_fflush_log_sg_commandS - fflush(fp); -#endif - } - if (fp == stderr) - return 1; -#ifdef Libburn_log_sg_command_stderR - sg_log_err(c, stderr, s, flag); -#endif - return 1; -} - - -#endif /* Libburn_log_sg_commandS */ - - -/** Sends a SCSI command to the drive, receives reply and evaluates wether - the command succeeded or shall be retried or finally failed. - Returned SCSI errors shall not lead to a return value indicating failure. - The callers get notified by c->error. An SCSI failure which leads not to - a retry shall be notified via scsi_notify_error(). - The Libburn_log_sg_commandS facility might be of help when problems with - a drive have to be examined. It shall stay disabled for normal use. - @return: 1 success , <=0 failure -*/ -int sg_issue_command(struct burn_drive *d, struct command *c) -{ - int done = 0, no_c_page = 0; - int err; - sg_io_hdr_t s; - -#ifdef Libburn_log_sg_commandS - /* ts A61030 */ - static FILE *fp= NULL; -#endif /* Libburn_log_sg_commandS */ - - /* <<< ts A60821 - debug: for tracing calls which might use open drive fds */ - char buf[161]; - sprintf(buf,"sg_issue_command d->fd= %d d->released= %d\n", - d->fd,d->released); - mmc_function_spy(NULL, buf); - -#ifdef Libburn_log_sg_commandS - /* ts A61030 */ - if(fp==NULL) { - fp= fopen("/tmp/libburn_sg_command_log","a"); - fprintf(fp,"\n-----------------------------------------\n"); - } - sg_log_cmd(c,fp,0); -#endif /* Libburn_log_sg_commandS */ - - - /* ts A61010 : with no fd there is no chance to send an ioctl */ - if (d->fd < 0) { - c->error = 1; - return 0; - } - - c->error = 0; - memset(&s, 0, sizeof(sg_io_hdr_t)); - - s.interface_id = 'S'; - - if (c->dir == TO_DRIVE) - s.dxfer_direction = SG_DXFER_TO_DEV; - else if (c->dir == FROM_DRIVE) - s.dxfer_direction = SG_DXFER_FROM_DEV; - else if (c->dir == NO_TRANSFER) { - s.dxfer_direction = SG_DXFER_NONE; - - /* ts A61007 */ - /* a ssert(!c->page); */ - no_c_page = 1; - } - s.cmd_len = c->oplen; - s.cmdp = c->opcode; - s.mx_sb_len = 32; - s.sbp = c->sense; - memset(c->sense, 0, sizeof(c->sense)); - s.timeout = 200000; - if (c->page && !no_c_page) { - s.dxferp = c->page->data; - if (c->dir == FROM_DRIVE) { - - /* ts A70519 : kernel 2.4 usb-storage seems to - expect exact dxfer_len for data - fetching commands. - */ - if (c->dxfer_len >= 0) - s.dxfer_len = c->dxfer_len; - else - s.dxfer_len = BUFFER_SIZE; -/* touch page so we can use valgrind */ - memset(c->page->data, 0, BUFFER_SIZE); - } else { - - /* ts A61010 */ - /* a ssert(c->page->bytes > 0); */ - if (c->page->bytes <= 0) { - c->error = 1; - return 0; - } - - s.dxfer_len = c->page->bytes; - } - } else { - s.dxferp = NULL; - s.dxfer_len = 0; - } - s.usr_ptr = c; - - do { - err = ioctl(d->fd, SG_IO, &s); - - /* ts A61010 */ - /* a ssert(err != -1); */ - if (err == -1) { - libdax_msgs_submit(libdax_messenger, - d->global_index, 0x0002010c, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "Failed to transfer command to drive", - errno, 0); - sg_close_drive(d); - d->released = 1; - d->busy = BURN_DRIVE_IDLE; - c->error = 1; - return -1; - } - - if (s.sb_len_wr) { - if (!c->retry) { - c->error = 1; - - /* A61106: rather than : return 1 */ - goto ex; - } - switch (scsi_error(d, s.sbp, s.sb_len_wr)) { - case RETRY: - done = 0; - break; - case FAIL: - done = 1; - c->error = 1; - break; - } - } else { - done = 1; - } - } while (!done); - - /* ts A61106 */ -ex:; - if (c->error) { - scsi_notify_error(d, c, s.sbp, s.sb_len_wr, 0); - } else if (s.host_status != Libburn_sg_host_oK || - s.driver_status != Libburn_sg_driver_oK) { - char msg[161]; - - sprintf(msg, - "SCSI command %2.2Xh indicates host or driver error:", - (unsigned int) c->opcode[0]); - sprintf(msg+strlen(msg), - " host_status= %xh , driver_status= %xh", - (unsigned int) s.host_status, - (unsigned int) s.driver_status); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x0002013b, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - } - -#ifdef Libburn_log_sg_commandS - sg_log_err(c, fp, &s, c->error != 0); -#endif /* Libburn_log_sg_commandS */ - - return 1; -} - - -/* ts A60922 */ -/** Tries to obtain SCSI address parameters. - @return 1 is success , 0 is failure -*/ -int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no, - int *target_no, int *lun_no) -{ - int fd, ret, l, open_mode = O_RDONLY; - struct my_scsi_idlun { - int x; - int host_unique_id; - }; - struct my_scsi_idlun idlun; - - - l = strlen(linux_ata_device_family) - 2; - if (l > 0 && strncmp(path, linux_ata_device_family, l) == 0 - && path[7] >= 'a' && path[7] <= 'z' && path[8] == 0) - return 0; /* on RIP 14 all hdx return SCSI adr 0,0,0,0 */ - - /* ts A70409 : DDLP-B */ - /* >>> obtain single lock on path */ - - if(burn_sg_open_o_nonblock) - open_mode |= O_NDELAY; - if(burn_sg_open_o_excl) { - /* O_EXCL | O_RDONLY does not work with /dev/sg* on - SuSE 9.0 (kernel 2.4) and SuSE 9.3 (kernel 2.6) */ - /* so skip it for now */; - } - fd = open(path, open_mode); - if(fd < 0) - return 0; - sg_fcntl_lock(&fd, path, F_RDLCK, 0); - if(fd < 0) - return 0; - -#ifdef SCSI_IOCTL_GET_BUS_NUMBER - /* Hearsay A61005 */ - if (ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, bus_no) == -1) - *bus_no = -1; -#endif - - /* http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/scsi_g_idlun.html */ - ret = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &idlun); - - sg_close_drive_fd(path, -1, &fd, 0); - if (ret == -1) - return(0); - *host_no= (idlun.x>>24)&255; - *channel_no= (idlun.x>>16)&255; - *target_no= (idlun.x)&255; - *lun_no= (idlun.x>>8)&255; -#ifdef SCSI_IOCTL_GET_BUS_NUMBER - if(*bus_no == -1) - *bus_no = 1000 * (*host_no + 1) + *channel_no; -#else - *bus_no= *host_no; -#endif - return 1; -} - - -/* ts A60922 ticket 33 : called from drive.c */ -/** Tells wether a text is a persistent address as listed by the enumeration - functions. -*/ -int sg_is_enumerable_adr(char *adr) -{ - char fname[4096]; - int ret = 0, first = 1; - burn_drive_enumerator_t idx; - - while (1) { - ret= sg_give_next_adr(&idx, fname, sizeof(fname), first); - if(ret <= 0) - break; - first = 0; - if (strcmp(adr, fname) == 0) { - sg_give_next_adr(&idx, fname, sizeof(fname), -1); - return 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; -} - diff --git a/libburn/sg.c b/libburn/sg.c deleted file mode 100644 index 79b78d9..0000000 --- a/libburn/sg.c +++ /dev/null @@ -1,17 +0,0 @@ - -/* sg.c - Switcher for operating system dependent transport level modules of libburn. - Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL -*/ - - -#ifdef __FreeBSD__ - -#include "sg-freebsd.c" - -#else - -#include "sg-linux.c" - -#endif - diff --git a/libburn/sg.h b/libburn/sg.h deleted file mode 100644 index f1de7a2..0000000 --- a/libburn/sg.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef __SG -#define __SG - - -#include "os.h" - - -/* see os.h for name of particular os-*.h where this is defined */ -BURN_OS_DEFINE_DRIVE_ENUMERATOR_T - - -struct burn_drive; -struct command; - - -/* ts A60922 ticket 33 */ -int sg_give_next_adr(burn_drive_enumerator_t *enm_context, - char adr[], int adr_size, int initialize); -int sg_is_enumerable_adr(char *adr); -int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no, - int *target_no, int *lun_no); - -int sg_grab(struct burn_drive *); -int sg_release(struct burn_drive *); -int sg_issue_command(struct burn_drive *, struct command *); - -/* ts A61115 : formerly sg_enumerate();ata_enumerate() */ -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 */ diff --git a/libburn/source.c b/libburn/source.c deleted file mode 100644 index 17ecee4..0000000 --- a/libburn/source.c +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#include <stdlib.h> -#include <string.h> -#include "libburn.h" -#include "source.h" -#include "structure.h" - -void burn_source_free(struct burn_source *src) -{ - if (--src->refcount < 1) { - if (src->free_data) - src->free_data(src); - free(src); - } -} - -enum burn_source_status burn_track_set_source(struct burn_track *t, - struct burn_source *s) -{ - s->refcount++; - t->source = s; - - /* ts A61031 */ - t->open_ended = (s->get_size(s) <= 0); - - return BURN_SOURCE_OK; -} - -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; -} - diff --git a/libburn/source.h b/libburn/source.h deleted file mode 100644 index 1f31527..0000000 --- a/libburn/source.h +++ /dev/null @@ -1,10 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef __SOURCE -#define __SOURCE - -struct burn_source *burn_source_new(void); - -int burn_source_cancel(struct burn_source *src); - -#endif /*__SOURCE*/ diff --git a/libburn/spc.c b/libburn/spc.c deleted file mode 100644 index 45e949e..0000000 --- a/libburn/spc.c +++ /dev/null @@ -1,997 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -/* scsi primary commands */ - -#include <unistd.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/ioctl.h> -#include <string.h> - -/* ts A61008 */ -/* #include <a ssert.h> */ - -#include <stdlib.h> - -#include "libburn.h" -#include "transport.h" -#include "spc.h" -#include "mmc.h" -#include "sbc.h" -#include "drive.h" -#include "debug.h" -#include "options.h" - -#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 */ -static unsigned char SPC_INQUIRY[] = { 0x12, 0, 0, 0, 36, 0 }; - -/*static char SPC_TEST[]={0,0,0,0,0,0};*/ -static unsigned char SPC_PREVENT[] = { 0x1e, 0, 0, 0, 1, 0 }; -static unsigned char SPC_ALLOW[] = { 0x1e, 0, 0, 0, 0, 0 }; -static unsigned char SPC_MODE_SENSE[] = { 0x5a, 0, 0, 0, 0, 0, 0, 16, 0, 0 }; -static unsigned char SPC_MODE_SELECT[] = - { 0x55, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static unsigned char SPC_REQUEST_SENSE[] = { 0x03, 0, 0, 0, 18, 0 }; -static unsigned char SPC_TEST_UNIT_READY[] = { 0x00, 0, 0, 0, 0, 0 }; - - -/* ts A70519 : An initializer for the abstract SCSI command structure */ -int scsi_init_command(struct command *c, unsigned char *opcode, int oplen) -{ - if (oplen > 16) - return 0; - memcpy(c->opcode, opcode, oplen); - c->oplen = oplen; - c->dir = NO_TRANSFER; - c->dxfer_len = -1; - memset(c->sense, 0, sizeof(c->sense)); - c->error = 0; - c->retry = 0; - c->page = NULL; - return 1; -} - - -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); - memcpy(c.opcode, SPC_TEST_UNIT_READY, sizeof(SPC_TEST_UNIT_READY)); - c.page = NULL; -*/ - c.retry = 0; - c.dir = NO_TRANSFER; - d->issue_command(d, &c); - if (c.error) { - *key= c.sense[2]; - *asc= c.sense[12]; - *ascq= c.sense[13]; - return (c.sense[2] & 0xF) == 0; - } - return 1; -} - -int spc_test_unit_ready(struct burn_drive *d) -{ - int key,asc,ascq; - - return spc_test_unit_ready_r(d, &key, &asc, &ascq); -} - - -/* 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 i, ret = 1, key = 0, asc = 0, ascq = 0; - char msg[160]; - - if (!(flag & 1)) - usleep(100000); - for(i = !(flag & 1); i < max_sec * 10; 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 */ - 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); - } - - 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) - 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; -} - - -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; -/* - c.oplen = sizeof(SPC_REQUEST_SENSE); - memcpy(c.opcode, SPC_REQUEST_SENSE, sizeof(SPC_REQUEST_SENSE)); -*/ - c.dxfer_len= c.opcode[4]; - c.retry = 0; - c.page = buf; - c.page->sectors = 0; - c.page->bytes = 0; - c.dir = FROM_DRIVE; - d->issue_command(d, &c); -} - -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]; -} - -void spc_inquiry(struct burn_drive *d) -{ - struct buffer buf; - 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)); - c.oplen = sizeof(SPC_INQUIRY); -*/ - c.dxfer_len= (c.opcode[3] << 8) | c.opcode[4]; - c.retry = 1; - c.page = &buf; - c.page->bytes = 0; - c.page->sectors = 0; - c.dir = FROM_DRIVE; - d->issue_command(d, &c); - id = (struct burn_scsi_inquiry_data *)d->idata; - memset(id->vendor, 0, 9); - memset(id->product, 0, 17); - memset(id->revision, 0, 5); - if (c.error) { - id->valid = -1; - return; - } - memcpy(id->vendor, c.page->data + 8, 8); - memcpy(id->product, c.page->data + 16, 16); - memcpy(id->revision, c.page->data + 32, 4); - id->valid = 1; - return; -} - -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)); - c.oplen = sizeof(SPC_PREVENT); - c.page = NULL; -*/ - c.retry = 1; - c.dir = NO_TRANSFER; - d->issue_command(d, &c); -} - -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)); - c.oplen = sizeof(SPC_ALLOW); - c.page = NULL; -*/ - c.retry = 1; - c.dir = NO_TRANSFER; - d->issue_command(d, &c); -} - -/* -ts A70518 : Do not call with *alloc_len < 8 -*/ -/** flag&1= do only inquire alloc_len */ -static int spc_sense_caps_al(struct burn_drive *d, int *alloc_len, int flag) -{ - struct buffer buf; - struct scsi_mode_data *m; - int size, page_length, num_write_speeds = 0, i, speed, ret; - int old_alloc_len, was_error = 0; - unsigned char *page; - struct command c; - struct burn_speed_descriptor *sd; - - /* ts A61225 : 1 = report about post-MMC-1 speed descriptors */ - static int speed_debug = 0; - - if (*alloc_len < 8) - return 0; - - memset(&buf, 0, sizeof(buf)); - scsi_init_command(&c, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE)); -/* - memcpy(c.opcode, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE)); - c.oplen = sizeof(SPC_MODE_SENSE); -*/ - c.dxfer_len = *alloc_len; - c.opcode[7] = (c.dxfer_len >> 8) & 0xff; - c.opcode[8] = c.dxfer_len & 0xff; - c.retry = 1; - c.opcode[2] = 0x2A; - c.page = &buf; - c.page->bytes = 0; - c.page->sectors = 0; - c.dir = FROM_DRIVE; - d->issue_command(d, &c); - if (c.error) { - memset(&buf, 0, sizeof(buf)); - d->mdata->valid = -1; - was_error = 1; - } - - size = c.page->data[0] * 256 + c.page->data[1]; - m = d->mdata; - page = c.page->data + 8; - - /* ts A61225 : - Although MODE SENSE indeed belongs to SPC, the returned code page - 2Ah is part of MMC-1 to MMC-3. In MMC-1 5.2.3.4. it has 22 bytes, - in MMC-3 6.3.11 there are at least 28 bytes plus a variable length - set of speed descriptors. In MMC-5 E.11 it is declared "legacy". - */ - page_length = page[1]; - old_alloc_len = *alloc_len; - *alloc_len = page_length + 8; - if (flag & 1) - return !was_error; - if (page_length + 8 > old_alloc_len) - page_length = old_alloc_len - 8; - if (page_length < 22) - return 0; - - m->valid = 0; - burn_mdata_free_subs(m); - - m->buffer_size = page[12] * 256 + page[13]; - m->dvdram_read = page[2] & 32; - m->dvdram_write = page[3] & 32; - m->dvdr_read = page[2] & 16; - m->dvdr_write = page[3] & 16; - m->dvdrom_read = page[2] & 8; - m->simulate = page[3] & 4; - m->cdrw_read = page[2] & 2; - m->cdrw_write = page[3] & 2; - m->cdr_read = page[2] & 1; - m->cdr_write = page[3] & 1; - - m->c2_pointers = page[5] & 16; - m->underrun_proof = page[4] & 128; - - /* ts A61021 : these fields are marked obsolete in MMC 3 */ - m->max_read_speed = page[8] * 256 + page[9]; - m->cur_read_speed = page[14] * 256 + page[15]; - - m->max_write_speed = page[18] * 256 + page[19]; - m->cur_write_speed = page[20] * 256 + page[21]; - - /* ts A61021 : New field to be set by atip (or following MMC-3 info) */ - m->min_write_speed = m->max_write_speed; - - /* ts A61225 : for ACh GET PERFORMANCE, Type 03h */ - m->min_end_lba = 0x7fffffff; - m->max_end_lba = 0; - - m->valid = 1; - - mmc_get_configuration(d); - - /* ts A61225 : end of MMC-1 , begin of MMC-3 */ - if (page_length < 32) /* no write speed descriptors ? */ - goto try_mmc_get_performance; - - m->cur_write_speed = page[28] * 256 + page[29]; - - if (speed_debug) - fprintf(stderr, "LIBBURN_DEBUG: cur_write_speed = %d\n", - m->cur_write_speed); - - num_write_speeds = page[30] * 256 + page[31]; - m->max_write_speed = m->min_write_speed = m->cur_write_speed; - - if (32 + 4 * num_write_speeds > page_length + 2) { - char msg[161]; - - sprintf(msg, "Malformed capabilities page 2Ah received (len=%d, #speeds=%d)", page_length, num_write_speeds); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x0002013c, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - return 0; - } - - for (i = 0; i < num_write_speeds; i++) { - speed = page[32 + 4*i + 2] * 256 + page[32 + 4*i + 3]; - - if (speed_debug) - fprintf(stderr, - "LIBBURN_DEBUG: write speed #%d = %d kB/s (rc %d)\n", - i, speed, page[32 + 4*i +1] & 7); - - /* ts A61226 */ - ret = burn_speed_descriptor_new(&(d->mdata->speed_descriptors), - NULL, d->mdata->speed_descriptors, 0); - if (ret > 0) { - sd = d->mdata->speed_descriptors; - sd->source = 1; - if (d->current_profile > 0) { - sd->profile_loaded = d->current_profile; - strcpy(sd->profile_name, - d->current_profile_text); - } - sd->wrc = (( page[32 + 4*i +1] & 7 ) == 1 ); - sd->write_speed = speed; - } - - if (speed > m->max_write_speed) - m->max_write_speed = speed; - if (speed < m->min_write_speed) - m->min_write_speed = speed; - } - - if (speed_debug) - fprintf(stderr, - "LIBBURN_DEBUG: 5Ah,2Ah min_write_speed = %d , max_write_speed = %d\n", - m->min_write_speed, m->max_write_speed); - -try_mmc_get_performance:; - ret = mmc_get_write_performance(d); - - if (ret > 0 && speed_debug) - fprintf(stderr, - "LIBBURN_DEBUG: ACh min_write_speed = %d , max_write_speed = %d\n", - m->min_write_speed, m->max_write_speed); - return !was_error; -} - - -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); -/* - fprintf(stderr,"LIBBURN_DEBUG: 5Ah alloc_len = %d , ret = %d\n", - alloc_len, ret); -*/ - if (alloc_len >= start_len && ret > 0) - /* second execution with announced length */ - spc_sense_caps_al(d, &alloc_len, 0); -} - - -void spc_sense_error_params(struct burn_drive *d) -{ - struct buffer buf; - struct scsi_mode_data *m; - int size, alloc_len = 12 ; - 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)); - c.oplen = sizeof(SPC_MODE_SENSE); -*/ - c.dxfer_len = alloc_len; - c.opcode[7] = (c.dxfer_len >> 8) & 0xff; - c.opcode[8] = c.dxfer_len & 0xff; - c.retry = 1; - c.opcode[2] = 0x01; - c.page = &buf; - c.page->bytes = 0; - c.page->sectors = 0; - c.dir = FROM_DRIVE; - d->issue_command(d, &c); - - size = c.page->data[0] * 256 + c.page->data[1]; - m = d->mdata; - page = c.page->data + 8; - d->params.retries = page[3]; - m->retry_page_length = page[1]; - m->retry_page_valid = 1; -} - -void spc_select_error_params(struct burn_drive *d, - const struct burn_read_opts *o) -{ - 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)); - c.oplen = sizeof(SPC_MODE_SELECT); -*/ - c.retry = 1; - c.opcode[8] = 8 + 2 + d->mdata->retry_page_length; - c.page = &buf; - c.page->bytes = 0; - c.page->sectors = 0; - - /* ts A61007 : moved up to only caller burn_disc_read() */ - /* a ssert(d->mdata->valid); */ - - memset(c.page->data, 0, 8 + 2 + d->mdata->retry_page_length); - c.page->bytes = 8 + 2 + d->mdata->retry_page_length; - c.page->data[8] = 1; - c.page->data[9] = d->mdata->retry_page_length; - if (o->transfer_damaged_blocks) - c.page->data[10] |= 32; - if (o->report_recovered_errors) - c.page->data[10] |= 4; - if (!o->hardware_error_recovery) - c.page->data[10] |= 1; -/*burn_print(1, "error parameter 0x%x\n", c->page->data[10]);*/ - c.page->data[11] = d->params.retries; - c.dir = TO_DRIVE; - d->issue_command(d, &c); -} - -void spc_sense_write_params(struct burn_drive *d) -{ - struct buffer buf; - struct scsi_mode_data *m; - int size, dummy, alloc_len = 10; - 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); */ - - scsi_init_command(&c, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE)); -/* - memcpy(c.opcode, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE)); - c.oplen = sizeof(SPC_MODE_SENSE); -*/ - c.dxfer_len = alloc_len; - c.opcode[7] = (c.dxfer_len >> 8) & 0xff; - c.opcode[8] = c.dxfer_len & 0xff; - c.retry = 1; - c.opcode[2] = 0x05; - c.page = &buf; - c.page->bytes = 0; - c.page->sectors = 0; - c.dir = FROM_DRIVE; - d->issue_command(d, &c); - - /* ts A71128 : do not interpret reply if error */ - 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; - 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->read_format_capacities(d, -1); - else if (d->status == BURN_DISC_BLANK || - (d->current_is_cd_profile && d->status == BURN_DISC_APPENDABLE)) { - d->get_nwa(d, -1, &dummy, &dummy); - } - /* others are hopefully up to date from mmc_read_disc_info() */ - -/* - fprintf(stderr, "LIBBURN_DEBUG: media_capacity_remaining = %.f\n", - (double) d->media_capacity_remaining); -*/ - -} - - -/* remark ts A61104 : -Although command MODE SELECT is SPC, the content of the -Write Parameters Mode Page (05h) is MMC (Table 108 in MMC-1). -Thus the filling of the mode page is done by mmc_compose_mode_page_5(). -*/ -void spc_select_write_params(struct burn_drive *d, - const struct burn_write_opts *o) -{ - 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); */ - - /* <<< A61030 - fprintf(stderr,"libburn_debug: write_type=%d multi=%d control=%d\n", - o->write_type,o->multi,o->control); - fprintf(stderr,"libburn_debug: block_type=%d spc_block_type=%d\n", - o->block_type,spc_block_type(o->block_type)); - */ - - scsi_init_command(&c, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT)); -/* - memcpy(c.opcode, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT)); - c.oplen = sizeof(SPC_MODE_SELECT); -*/ - c.retry = 1; - c.opcode[8] = 8 + 2 + d->mdata->write_page_length; - c.page = &buf; - c.page->bytes = 0; - c.page->sectors = 0; - - /* ts A61007 : moved up to burn_disc_write() */ - /* a ssert(d->mdata->valid); */ - - memset(c.page->data, 0, 8 + 2 + d->mdata->write_page_length); - c.page->bytes = 8 + 2 + d->mdata->write_page_length; - - burn_print(12, "using write page length %d (valid %d)\n", - d->mdata->write_page_length, d->mdata->write_page_valid); - - /* ts A61229 */ - if (mmc_compose_mode_page_5(d, o, c.page->data + 8) <= 0) - return; - - c.dir = TO_DRIVE; - d->issue_command(d, &c); -} - -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); -} - -/* -don't check totally stupid modes (raw/raw0) -some drives say they're ok, and they're not. -*/ - -void spc_probe_write_modes(struct burn_drive *d) -{ - struct buffer buf; - int try_write_type = 1; - int try_block_type = 0; - int key, asc, ascq, useable_write_type = -1, useable_block_type = -1; - 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, - try_block_type); - - /* ts A70213 */ - if (try_write_type == 4) { - /* Pseudo write type NONE . Set a useable write mode */ - if (useable_write_type == -1) - break; - try_write_type = useable_write_type; - try_block_type = useable_block_type; - last_try= 1; - } - scsi_init_command(&c, SPC_MODE_SELECT,sizeof(SPC_MODE_SELECT)); -/* - memcpy(c.opcode, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT)); - c.oplen = sizeof(SPC_MODE_SELECT); -*/ - c.retry = 1; - c.opcode[8] = 8 + 2 + 0x32; - c.page = &buf; - - memset(c.page->data, 0, 8 + 2 + 0x32); - c.page->bytes = 8 + 2 + 0x32; - - c.page->data[8] = 5; - c.page->data[9] = 0x32; - c.page->data[10] = try_write_type; - if (try_block_type > 4) - c.page->data[11] = 4; - else - c.page->data[11] = 0; - c.page->data[12] = try_block_type; - c.page->data[23] = 150; - c.dir = TO_DRIVE; - - d->silent_on_scsi_error = 1; - d->issue_command(d, &c); - d->silent_on_scsi_error = 0; - - if (last_try) - break; - - key = c.sense[2]; - asc = c.sense[12]; - ascq = c.sense[13]; - - if (key) - burn_print(7, "%d not supported\n", try_block_type); - else { - burn_print(7, "%d:%d SUPPORTED MODE!\n", - try_write_type, try_block_type); - if (try_write_type == 2) /* sao */ - d->block_types[try_write_type] = - BURN_BLOCK_SAO; - else - d->block_types[try_write_type] |= - 1 << try_block_type; - - /* ts A70213 */ - if ((useable_write_type < 0 && try_write_type > 0) || - (try_write_type == 1 && try_block_type == 8)) { - /* Packet is not supported yet. - Prefer TAO MODE_1. */ - useable_write_type = try_write_type; - useable_block_type = try_block_type; - } - } - switch (try_block_type) { - case 0: - case 1: - case 2: - try_block_type++; - break; - case 3: - try_block_type = 8; - break; - case 8: - case 9: - case 10: - case 11: - case 12: - try_block_type++; - break; - case 13: - try_block_type = 0; - try_write_type++; - break; - default: - return; - } - } -} - -/* ( ts A61229 : shouldn't this go to mmc.c too ?) */ - -/** @return -1 = error */ -int spc_block_type(enum burn_block_types b) -{ - switch (b) { - case BURN_BLOCK_SAO: - return 0; /* ignored bitz */ - case BURN_BLOCK_RAW0: - return 0; - case BURN_BLOCK_RAW16: - return 1; - case BURN_BLOCK_RAW96P: - return 2; - case BURN_BLOCK_RAW96R: - return 3; - case BURN_BLOCK_MODE1: - return 8; - case BURN_BLOCK_MODE2R: - return 9; - case BURN_BLOCK_MODE2_PATHETIC: - return 10; - case BURN_BLOCK_MODE2_LAME: - return 11; - case BURN_BLOCK_MODE2_OBSCURE: - return 12; - case BURN_BLOCK_MODE2_OK: - return 13; - default: - return -1; - } - /* ts A61007 : already prevented in burn_write_opts_set_write_type() */ - /* a ssert(0); */; -} - -/* ts A61021 : the spc specific part of sg.c:enumerate_common() -*/ -int spc_setup_drive(struct burn_drive *d) -{ - d->getcaps = spc_getcaps; - d->lock = spc_prevent; - d->unlock = spc_allow; - d->read_disc_info = spc_sense_write_params; - d->get_erase_progress = spc_get_erase_progress; - d->test_unit_ready = spc_test_unit_ready; - d->probe_write_modes = spc_probe_write_modes; - d->send_parameters = spc_select_error_params; - d->send_write_parameters = spc_select_write_params; - return 1; -} - -/* ts A61021 : the general SCSI specific part of sg.c:enumerate_common() - @param flag Bitfiled for control purposes - bit0= do not setup spc/sbc/mmc -*/ -int burn_scsi_setup_drive(struct burn_drive *d, int bus_no, int host_no, - int channel_no, int target_no, int lun_no, int flag) -{ - int ret; - - /* ts A60923 */ - d->bus_no = bus_no; - d->host = host_no; - d->id = target_no; - d->channel = channel_no; - d->lun = lun_no; - - /* ts A61106 */ - 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)); - - /* ts A61007 : obsolete Assert in drive_getcaps() */ - if(d->idata == NULL || d->mdata == NULL) { - libdax_msgs_submit(libdax_messenger, -1, 0x00020108, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "Could not allocate new drive object", 0, 0); - return -1; - } - d->idata->valid = 0; - d->mdata->valid = 0; - d->mdata->speed_descriptors = NULL; - if(!(flag & 1)) { - ret = spc_setup_drive(d); - if (ret<=0) - return ret; - ret = sbc_setup_drive(d); - if (ret<=0) - return ret; - ret = mmc_setup_drive(d); - if (ret<=0) - return ret; - } - return 1; -} - - -/* ts A61122 */ -enum response scsi_error_msg(struct burn_drive *d, unsigned char *sense, - int senselen, char msg[161], - int *key, int *asc, int *ascq) -{ - *key= *asc= *ascq= -1; - - if (senselen<=0 || senselen>2) - *key = sense[2]; - if (senselen<=0 || senselen>12) - *asc = sense[12]; - if (senselen<=0 || senselen>13) - *ascq = sense[13]; - - burn_print(12, "CONDITION: 0x%x 0x%x 0x%x on %s %s\n", - *key, *asc, *ascq, d->idata->vendor, d->idata->product); - - switch (*asc) { - case 0: - sprintf(msg, "(no error reported by SCSI transaction)"); - return RETRY; - - case 2: - sprintf(msg, "not ready"); - return RETRY; - case 4: - sprintf(msg, - "logical unit is in the process of becoming ready"); - return RETRY; - case 0x20: - if (*key == 5) - sprintf(msg, "bad opcode"); - return FAIL; - case 0x21: - sprintf(msg, "invalid address"); - return FAIL; - case 0x24: - if (*key == 5) - sprintf(msg, "invalid field in cdb"); - else - break; - return FAIL; - case 0x26: - if (*key == 5 ) - sprintf(msg, "invalid field in parameter list" ); - return FAIL; - case 0x28: - if (*key == 6) - sprintf(msg, "Medium may have changed"); - else - break; - return RETRY; - case 0x3A: - sprintf(msg, "Medium not present"); - d->status = BURN_DISC_EMPTY; - return FAIL; - } - sprintf(msg, - "Failure. See mmc3r10g.pdf: Sense Key %X ASC %2.2X ASCQ %2.2X", - *key, *asc, *ascq); - return FAIL; -} - - -/* ts A61115 moved from sg-*.c */ -/* ts A61122 made it frontend to scsi_error_msg() */ -enum response scsi_error(struct burn_drive *d, unsigned char *sense, - int senselen) -{ - int key, asc, ascq; - char msg[160]; - enum response resp; - - resp = scsi_error_msg(d, sense, senselen, msg, &key, &asc, &ascq); - if (asc == 0 || asc == 0x3A) - burn_print(12, "%s\n", msg); - else - burn_print(1, "%s\n", msg); - return resp; -} - - -/* ts A61030 - A61115 */ -/* @param flag bit0=do report conditions which are considered not an error */ -int scsi_notify_error(struct burn_drive *d, struct command *c, - unsigned char *sense, int senselen, int flag) -{ - int key= -1, asc= -1, ascq= -1, ret; - char msg[320],scsi_msg[160]; - - if (d->silent_on_scsi_error) - return 1; - - strcpy(scsi_msg, " \""); - scsi_error_msg(d, sense, senselen, scsi_msg + strlen(scsi_msg), - &key, &asc, &ascq); - strcat(scsi_msg, "\""); - - if(!(flag & 1)) { - /* SPC : TEST UNIT READY command */ - if (c->opcode[0] == 0) - return 1; - /* MMC : READ DISC INFORMATION command */ - if (c->opcode[0] == 0x51) - if (key == 0x2 && asc == 0x3A && - ascq>=0 && ascq <= 0x02) /* MEDIUM NOT PRESENT */ - return 1; - } - - 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) - sprintf(msg+strlen(msg), " asc=%2.2Xh", asc); - if (ascq>=0) - sprintf(msg+strlen(msg), " ascq=%2.2Xh", ascq); - ret = libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002010f, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, msg,0,0); - if (ret < 0) - return ret; - ret = libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002010f, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, - scsi_msg,0,0); - return ret; -} - diff --git a/libburn/spc.h b/libburn/spc.h deleted file mode 100644 index 81d2d46..0000000 --- a/libburn/spc.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef __SPC -#define __SPC - -#include "libburn.h" - -void spc_inquiry(struct burn_drive *); -void spc_prevent(struct burn_drive *); -void spc_allow(struct burn_drive *); -void spc_sense_caps(struct burn_drive *); -void spc_sense_error_params(struct burn_drive *); -void spc_select_error_params(struct burn_drive *, - const struct burn_read_opts *); -void spc_getcaps(struct burn_drive *d); -void spc_sense_write_params(struct burn_drive *); -void spc_select_write_params(struct burn_drive *, - const struct burn_write_opts *); -void spc_probe_write_modes(struct burn_drive *); -void spc_request_sense(struct burn_drive *d, struct buffer *buf); -int spc_block_type(enum burn_block_types b); -int spc_get_erase_progress(struct burn_drive *d); - -/* ts A70315 : test_unit_ready with result parameters */ -int spc_test_unit_ready_r(struct burn_drive *d, int *key, int *asc, int *ascq); - -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); - -/* ts A61021 : the spc specific part of sg.c:enumerate_common() -*/ -int spc_setup_drive(struct burn_drive *d); - -/* ts A61021 : the general SCSI specific part of sg.c:enumerate_common() - @param flag Bitfield for control purposes - bit0= do not setup spc/sbc/mmc -*/ -int burn_scsi_setup_drive(struct burn_drive *d, int bus_no, int host_no, - int channel_no, int target_no, int lun_no, int flag); - -/* ts A61115 moved from sg-*.h */ -enum response { RETRY, FAIL }; -enum response scsi_error(struct burn_drive *, unsigned char *, int); - -/* ts A61122 */ -enum response scsi_error_msg(struct burn_drive *d, unsigned char *sense, - int senselen, char msg[161], - int *key, int *asc, int *ascq); - -/* ts A61030 */ -/* @param flag bit0=do report conditions which are considered not an error */ -int scsi_notify_error(struct burn_drive *, struct command *c, - unsigned char *sense, int senselen, int flag); - -/* ts A70519 */ -int scsi_init_command(struct command *c, unsigned char *opcode, int oplen); - -#endif /*__SPC*/ diff --git a/libburn/structure.c b/libburn/structure.c deleted file mode 100644 index 40897b9..0000000 --- a/libburn/structure.c +++ /dev/null @@ -1,517 +0,0 @@ - -/* ts A61008 */ -/* #include <a ssert.h> */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "libburn.h" -#include "structure.h" -#include "write.h" -#include "debug.h" - -#include "libdax_msgs.h" -extern struct libdax_msgs *libdax_messenger; - - -/* ts A61008 : replaced Assert by if and return 0 */ -/* a ssert(!(pos > BURN_POS_END)); */ - -#define RESIZE(TO, NEW, pos) {\ - void *tmp;\ -\ - if (pos > BURN_POS_END)\ - return 0;\ - if (pos == BURN_POS_END)\ - pos = TO->NEW##s;\ - if (pos > TO->NEW##s)\ - return 0;\ -\ - tmp = realloc(TO->NEW, sizeof(struct NEW *) * (TO->NEW##s + 1));\ - if (!tmp)\ - return 0;\ - TO->NEW = tmp;\ - memmove(TO->NEW + pos + 1, TO->NEW + pos,\ - sizeof(struct NEW *) * (TO->NEW##s - pos));\ - TO->NEW##s++;\ -} - -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; - return d; -} - -void burn_disc_free(struct burn_disc *d) -{ - d->refcnt--; - if (d->refcnt == 0) { - /* dec refs on all elements */ - int i; - - for (i = 0; i < d->sessions; i++) - burn_session_free(d->session[i]); - free(d->session); - free(d); - } -} - -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; - s->hidefirst = 0; - return s; -} - -void burn_session_hide_first_track(struct burn_session *s, int onoff) -{ - s->hidefirst = onoff; -} - -void burn_session_free(struct burn_session *s) -{ - s->refcnt--; - if (s->refcnt == 0) { - /* dec refs on all elements */ - int i; - - for (i = 0; i < s->tracks; i++) - burn_track_free(s->track[i]); - free(s->track); - free(s); - } - -} - -int burn_disc_add_session(struct burn_disc *d, struct burn_session *s, - unsigned int pos) -{ - RESIZE(d, session, pos); - d->session[pos] = s; - s->refcnt++; - return 1; -} - -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; - t->offsetcount = 0; - t->tail = 0; - t->tailcount = 0; - t->mode = BURN_MODE1; - t->isrc.has_isrc = 0; - t->pad = 1; - - /* ts A70213 */ - t->fill_up_media = 0; - /* ts A70218 */ - t->default_size = 0; - - t->entry = NULL; - t->source = NULL; - t->eos = 0; - - /* ts A61101 */ - t->sourcecount = 0; - t->writecount = 0; - t->written_sectors = 0; - - /* ts A61031 */ - t->open_ended = 0; - t->track_data_done = 0; - - t->postgap = 0; - t->pregap1 = 0; - t->pregap2 = 0; - - /* ts A61024 */ - t->swap_source_bytes = 0; - return t; -} - -void burn_track_free(struct burn_track *t) -{ - t->refcnt--; - if (t->refcnt == 0) { - /* dec refs on all elements */ - if (t->source) - burn_source_free(t->source); - free(t); - } -} - -int burn_session_add_track(struct burn_session *s, struct burn_track *t, - unsigned int pos) -{ - RESIZE(s, track, pos); - s->track[pos] = t; - t->refcnt++; - return 1; -} - -int burn_session_remove_track(struct burn_session *s, struct burn_track *t) -{ - struct burn_track **tmp; - int i, pos = -1; - - /* ts A61008 */ - /* a ssert(s->track != NULL); */ - if (s->track == NULL) - return 0; - - burn_track_free(t); - - /* Find the position */ - for (i = 0; i < s->tracks; i++) { - if (t == s->track[i]) { - pos = i; - break; - } - } - - if (pos == -1) - return 0; - - /* Is it the last track? */ - if (pos != s->tracks - 1) { - memmove(&s->track[pos], &s->track[pos + 1], - sizeof(struct burn_track *) * (s->tracks - (pos + 1))); - } - - s->tracks--; - tmp = realloc(s->track, sizeof(struct burn_track *) * s->tracks); - if (tmp) - s->track = tmp; - return 1; -} - -void burn_structure_print_disc(struct burn_disc *d) -{ - int i; - - burn_print(12, "This disc has %d sessions\n", d->sessions); - for (i = 0; i < d->sessions; i++) { - burn_structure_print_session(d->session[i]); - } -} -void burn_structure_print_session(struct burn_session *s) -{ - int i; - - burn_print(12, " Session has %d tracks\n", s->tracks); - for (i = 0; i < s->tracks; i++) { - burn_structure_print_track(s->track[i]); - } -} -void burn_structure_print_track(struct burn_track *t) -{ - burn_print(12, "(%p) track size %d sectors\n", t, - burn_track_get_sectors(t)); -} - -void burn_track_define_data(struct burn_track *t, int offset, int tail, - int pad, int mode) -{ - int type_to_form(int mode, unsigned char *ctladr, int *form); - int burn_sector_length(int tracktype); - unsigned char ctladr; - int form = -1; /* unchanged form will be considered an error too */ - - type_to_form(mode, &ctladr, &form); - if (form == -1 || burn_sector_length(mode) <= 0) { - char msg[160]; - - sprintf(msg, "Attempt to set track mode to unusable value %d", - mode); - libdax_msgs_submit(libdax_messenger, -1, 0x00020115, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - return; - } - - t->offset = offset; - t->pad = pad; - t->mode = mode; - t->tail = tail; -} - - -/* ts A61024 */ -int burn_track_set_byte_swap(struct burn_track *t, int swap_source_bytes) -{ - if(swap_source_bytes!=0 && swap_source_bytes!=1) - return 0; - t->swap_source_bytes = swap_source_bytes; - return 1; -} - - -void burn_track_set_isrc(struct burn_track *t, char *country, char *owner, - unsigned char year, unsigned int serial) -{ - int i; - - for (i = 0; i < 2; ++i) { - - /* ts A61008 : This is always true */ - /* a ssert((country[i] >= '0' || country[i] < '9') && - (country[i] >= 'a' || country[i] < 'z') && - (country[i] >= 'A' || country[i] < 'Z')); */ - /* ts A61008 : now coordinated with sector.c: char_to_isrc() */ - if (! ((country[i] >= '0' && country[i] <= '9') || - (country[i] >= 'a' && country[i] <= 'z') || - (country[i] >= 'A' && country[i] <= 'Z') ) ) - goto is_not_allowed; - - t->isrc.country[i] = country[i]; - } - for (i = 0; i < 3; ++i) { - - /* ts A61008 : This is always true */ - /* a ssert((owner[i] >= '0' || owner[i] < '9') && - (owner[i] >= 'a' || owner[i] < 'z') && - (owner[i] >= 'A' || owner[i] < 'Z')); */ - /* ts A61008 : now coordinated with sector.c: char_to_isrc() */ - if (! ((owner[i] >= '0' && owner[i] <= '9') || - (owner[i] >= 'a' && owner[i] <= 'z') || - (owner[i] >= 'A' && owner[i] <= 'Z') ) ) - goto is_not_allowed; - - t->isrc.owner[i] = owner[i]; - } - - /* ts A61008 */ - /* a ssert(year <= 99); */ - if (year > 99) - goto is_not_allowed; - - t->isrc.year = year; - - /* ts A61008 */ - /* a ssert(serial <= 99999); */ - if (serial > 99999) - goto is_not_allowed; - - t->isrc.serial = serial; - - /* ts A61008 */ - t->isrc.has_isrc = 1; - return; -is_not_allowed:; - libdax_msgs_submit(libdax_messenger, -1, 0x00020114, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Attempt to set ISRC with bad data", 0, 0); - return; -} - -void burn_track_clear_isrc(struct burn_track *t) -{ - t->isrc.has_isrc = 0; -} - -int burn_track_get_sectors(struct burn_track *t) -{ - /* ts A70125 : was int */ - off_t size; - int sectors, seclen; - - seclen = burn_sector_length(t->mode); - size = t->offset + t->source->get_size(t->source) + t->tail; - sectors = size / seclen; - if (size % seclen) - sectors++; - burn_print(1, "%d sectors of %d length\n", sectors, seclen); - return sectors; -} - - -/* ts A70125 */ -int burn_track_set_sectors(struct burn_track *t, int sectors) -{ - off_t size, seclen; - int ret; - - seclen = burn_sector_length(t->mode); - size = seclen * (off_t) sectors - (off_t) t->offset - (off_t) t->tail; - if (size < 0) - return 0; - ret = t->source->set_size(t->source, size); - t->open_ended = (t->source->get_size(t->source) <= 0); - return ret; -} - - -/* ts A70218 , API since A70328 */ -int burn_track_set_size(struct burn_track *t, off_t size) -{ - if (t->source == NULL) - return 0; - if (t->source->set_size == NULL) - return 0; - t->open_ended = (size <= 0); - return t->source->set_size(t->source, size); -} - - -/* ts A70213 */ -int burn_track_set_fillup(struct burn_track *t, int fill_up_media) -{ - t->fill_up_media = fill_up_media; - if (fill_up_media) - t->open_ended = 0; - return 1; -} - - -/* ts A70213 */ -/** - @param flag bit0= force new size even if existing track size is larger -*/ -int burn_track_apply_fillup(struct burn_track *t, off_t max_size, int flag) -{ - int max_sectors, ret = 2; - char msg[160]; - - if (t->fill_up_media <= 0) - return 2; - max_sectors = max_size / 2048; - if (burn_track_get_sectors(t) < max_sectors || (flag & 1)) { - sprintf(msg, "Setting total track size to %ds (payload %ds)\n", - max_sectors, (int) (t->source->get_size(t->source)/2048)); - libdax_msgs_submit(libdax_messenger, -1, 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - msg, 0, 0); - ret = burn_track_set_sectors(t, max_sectors); - t->open_ended = 0; - } - return ret; -} - - -/* ts A61031 */ -int burn_track_is_open_ended(struct burn_track *t) -{ - return !!t->open_ended; -} - - -/* ts A70218 : API */ -int burn_track_set_default_size(struct burn_track *t, off_t size) -{ - t->default_size = size; - return 1; -} - - -/* ts A70218 */ -off_t burn_track_get_default_size(struct burn_track *t) -{ - return t->default_size; -} - - -/* ts A61101 : API function */ -int burn_track_get_counters(struct burn_track *t, - off_t *read_bytes, off_t *written_bytes) -{ -/* - fprintf(stderr, "libburn_experimental: sizeof(off_t)=%d\n", - sizeof(off_t)); -*/ - *read_bytes = t->sourcecount; - *written_bytes = t->writecount; - return 1; -} - -/* ts A61031 */ -int burn_track_is_data_done(struct burn_track *t) -{ - return !!t->track_data_done; -} - -int burn_track_get_shortage(struct burn_track *t) -{ - int size; - int seclen; - - seclen = burn_sector_length(t->mode); - size = t->offset + t->source->get_size(t->source) + t->tail; - if (size % seclen) - return seclen - size % seclen; - return 0; -} - -int burn_session_get_sectors(struct burn_session *s) -{ - int sectors = 0, i; - - for (i = 0; i < s->tracks; i++) - sectors += burn_track_get_sectors(s->track[i]); - return sectors; -} - -int burn_disc_get_sectors(struct burn_disc *d) -{ - int sectors = 0, i; - - for (i = 0; i < d->sessions; i++) - sectors += burn_session_get_sectors(d->session[i]); - return sectors; -} - -void burn_track_get_entry(struct burn_track *t, struct burn_toc_entry *entry) -{ - if (t->entry == NULL) - memset(entry, 0, sizeof(struct burn_toc_entry)); - else - memcpy(entry, t->entry, sizeof(struct burn_toc_entry)); -} - -void burn_session_get_leadout_entry(struct burn_session *s, - struct burn_toc_entry *entry) -{ - if (s->leadout_entry == NULL) - memset(entry, 0, sizeof(struct burn_toc_entry)); - else - memcpy(entry, s->leadout_entry, sizeof(struct burn_toc_entry)); -} - -struct burn_session **burn_disc_get_sessions(struct burn_disc *d, int *num) -{ - *num = d->sessions; - return d->session; -} - -struct burn_track **burn_session_get_tracks(struct burn_session *s, int *num) -{ - *num = s->tracks; - return s->track; -} - -int burn_track_get_mode(struct burn_track *track) -{ - return track->mode; -} - -int burn_session_get_hidefirst(struct burn_session *session) -{ - return session->hidefirst; -} diff --git a/libburn/structure.h b/libburn/structure.h deleted file mode 100644 index 89f25d5..0000000 --- a/libburn/structure.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef BURN__STRUCTURE_H -#define BURN__STRUCTURE_H - -struct isrc -{ - int has_isrc; - char country[2]; /* each must be 0-9, A-Z */ - char owner[3]; /* each must be 0-9, A-Z */ - unsigned char year; /* must be 0-99 */ - unsigned int serial; /* must be 0-99999 */ -}; - -struct burn_track -{ - int refcnt; - struct burn_toc_entry *entry; - unsigned char indices; - /* lba address of the index */ - unsigned int index[99]; - /** number of 0 bytes to write before data */ - int offset; - /** how much offset has been used */ - int offsetcount; - /** Number of zeros to write after data */ - int tail; - /** how much tail has been used */ - int tailcount; - /** 1 means Pad with zeros, 0 means start reading the next track */ - int pad; - - /* ts A70213 : wether to expand this track to full available media */ - int fill_up_media; - - /* ts A70218 : a track size to use if it is mandarory to have some */ - off_t default_size; - - /** Data source */ - struct burn_source *source; - /** End of Source flag */ - int eos; - - /* ts A61101 */ - off_t sourcecount; - off_t writecount; - off_t written_sectors; - - /* ts A61031 */ - /** Source is of undefined length */ - int open_ended; - /** End of open ended track flag : offset+payload+tail are delivered */ - int track_data_done; - - /** The audio/data mode for the entry. Derived from control and - possibly from reading the track's first sector. */ - int mode; - /** The track contains interval one of a pregap */ - int pregap1; - /** The track contains interval two of a pregap */ - int pregap2; - /** The track contains a postgap */ - int postgap; - struct isrc isrc; - - /* ts A61024 */ - /** Byte swapping on source data stream : 0=none , 1=pairwise */ - int swap_source_bytes; -}; - -struct burn_session -{ - unsigned char firsttrack; - unsigned char lasttrack; - int hidefirst; - unsigned char start_m; - unsigned char start_s; - unsigned char start_f; - struct burn_toc_entry *leadout_entry; - - int tracks; - struct burn_track **track; - int refcnt; -}; - -struct burn_disc -{ - int sessions; - struct burn_session **session; - int refcnt; -}; - -int burn_track_get_shortage(struct burn_track *t); - - -/* ts A61031 : might go to libburn.h */ -int burn_track_is_open_ended(struct burn_track *t); -int burn_track_is_data_done(struct burn_track *t); - -/* ts A70125 : sets overall sectors of a track: offset+payload+padding */ -int burn_track_set_sectors(struct burn_track *t, int sectors); - -/* ts A70218 : sets the payload size alone */ -int burn_track_set_size(struct burn_track *t, off_t size); - -/* ts A70213 */ -int burn_track_set_fillup(struct burn_track *t, int fill_up_media); -int burn_track_apply_fillup(struct burn_track *t, off_t max_size, int flag); - -/* ts A70218 */ -off_t burn_track_get_default_size(struct burn_track *t); - - -#endif /* BURN__STRUCTURE_H */ diff --git a/libburn/toc.c b/libburn/toc.c deleted file mode 100644 index 7a9bbbc..0000000 --- a/libburn/toc.c +++ /dev/null @@ -1,141 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -/* ts A61008 */ -/* #include <a ssert.h> */ - -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include "toc.h" -#include "transport.h" -#include "libburn.h" -#include "sector.h" -#include "options.h" - -#if 0 -static void write_clonecd2(volatile struct toc *toc, int f); - -static void write_clonecd2(volatile struct toc *toc, int f) -{ - int i; - - /* header */ - dprintf(f, "[CloneCD]\r\n"); - dprintf(f, "Version=2\r\n"); - dprintf(f, "\r\n"); - - /* disc data */ - dprintf(f, "[Disc]\r\n"); - - dprintf(f, "TocEntries=%d\r\n", toc->toc_entries); - dprintf(f, "Sessions=%d\r\n", toc->sessions); - dprintf(f, "DataTracksScrambled=%d\r\n", toc->datatracksscrambled); - dprintf(f, "CDTextLength=%d\r\n", toc->cdtextlength); - dprintf(f, "\r\n"); - - /* session data */ - for (i = 0; i < toc->sessions; ++i) { - dprintf(f, "[Session %d]\r\n", i + 1); - - { - int m; - - switch (toc->session[i].track[0]->mode) { - case BURN_MODE_RAW_DATA: - case BURN_MODE_AUDIO: - m = 0; - break; - case BURN_MODE0: - m = 1; - break; - case BURN_MODE1: - case BURN_MODE2_FORMLESS: - case BURN_MODE2_FORM1: - case BURN_MODE2_FORM2: - case BURN_MODE_UNINITIALIZED: - - /* ts A61008 : do this softly without Assert */ - - a ssert(0); /* unhandled! find out ccd's - value for these modes! */ - } - dprintf(f, "PreGapMode=%d\r\n", m); - } - dprintf(f, "\r\n"); - } - - for (i = 0; i < toc->toc_entries; ++i) { - dprintf(f, "[Entry %d]\r\n", i); - - dprintf(f, "Session=%d\r\n", toc->toc_entry[i].session); - dprintf(f, "Point=0x%02x\r\n", toc->toc_entry[i].point); - dprintf(f, "ADR=0x%02x\r\n", toc->toc_entry[i].adr); - dprintf(f, "Control=0x%02x\r\n", toc->toc_entry[i].control); - dprintf(f, "TrackNo=%d\r\n", toc->toc_entry[i].tno); - dprintf(f, "AMin=%d\r\n", toc->toc_entry[i].min); - dprintf(f, "ASec=%d\r\n", toc->toc_entry[i].sec); - dprintf(f, "AFrame=%d\r\n", toc->toc_entry[i].frame); - dprintf(f, "ALBA=%d\r\n", - burn_msf_to_lba(toc->toc_entry[i].min, - toc->toc_entry[i].sec, - toc->toc_entry[i].frame)); - dprintf(f, "Zero=%d\r\n", toc->toc_entry[i].zero); - dprintf(f, "PMin=%d\r\n", toc->toc_entry[i].pmin); - dprintf(f, "PSec=%d\r\n", toc->toc_entry[i].psec); - dprintf(f, "PFrame=%d\r\n", toc->toc_entry[i].pframe); - dprintf(f, "PLBA=%d\r\n", - burn_msf_to_lba(toc->toc_entry[i].pmin, - toc->toc_entry[i].psec, - toc->toc_entry[i].pframe)); - dprintf(f, "\r\n"); - } -} -#endif - -void toc_find_modes(struct burn_drive *d) -{ - struct burn_read_opts o; - int lba; - int i, j; - struct buffer mem; - struct burn_toc_entry *e; - - /* ts A61008 : to be prevented on the higher levels */ - /* a ssert(d->busy); */ - - mem.bytes = 0; - mem.sectors = 1; - o.raw = 1; - o.c2errors = 0; - o.subcodes_audio = 1; - o.subcodes_data = 1; - o.hardware_error_recovery = 1; - o.report_recovered_errors = 0; - o.transfer_damaged_blocks = 1; - o.hardware_error_retries = 1; - - for (i = 0; i < d->disc->sessions; i++) - for (j = 0; j < d->disc->session[i]->tracks; j++) { - struct burn_track *t = d->disc->session[i]->track[j]; - - e = t->entry; - if (!e) - lba = 0; - else - lba = burn_msf_to_lba(e->pmin, e->psec, - e->pframe); -/* XXX | in the subcodes if appropriate! */ - if (e && !(e->control & 4)) { - t->mode = BURN_AUDIO; - } else { - - t->mode = BURN_MODE1; -/* ts A70519 : this does not work with Linux 2.4 USB because one cannot - predict the exact dxfer_size without knowing the sector type. - mem.sectors = 1; - d->read_sectors(d, lba, mem.sectors, &o, &mem); - t->mode = sector_identify(mem.data); -*/ - } - } -} diff --git a/libburn/toc.h b/libburn/toc.h deleted file mode 100644 index 1d804e7..0000000 --- a/libburn/toc.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef __TOC_H -#define __TOC_H - -struct command; - -#include "libburn.h" -#include "structure.h" - -/* return if a given entry refers to a track position */ -#define TOC_ENTRY_IS_TRACK(drive, entrynum) \ - ((drive)->toc_entry[entrynum].point < 100) - -/* return if a given entry is in audio or data format */ -#define TOC_ENTRY_IS_AUDIO(drive, entrynum) \ - (~(drive)->toc_entry[entrynum].control & 4) - -/* return the point value for a given entry number */ -#define TOC_POINT(drive, entrynum) ((drive)->toc_entry[entrynum].point) - -/* return the track struct for a given entry number */ -#define TOC_TRACK(drive, entrynum) \ - ((drive)->track[TOC_POINT(drive, entrynum) - 1]) - -/* return the lba of a toc entry */ -#define TOC_ENTRY_PLBA(drive, entrynum) \ - burn_msf_to_lba((drive)->toc_entry[(entrynum)].pmin, \ - (drive)->toc_entry[(entrynum)].psec, \ - (drive)->toc_entry[(entrynum)].pframe) - -/* flags for the q subchannel control field */ -#define TOC_CONTROL_AUDIO (0) -#define TOC_CONTROL_DATA (1 << 2) -#define TOC_CONTROL_AUDIO_TWO_CHANNELS (0) -#define TOC_CONTROL_AUDIO_FOUR_CHANNELS (1 << 3) -#define TOC_CONTROL_AUDIO_PRE_EMPHASIS (1 << 0) -#define TOC_CONTROL_DATA_RECORDED_UNINTERRUPTED (0) -#define TOC_CONTROL_DATA_RECORDED_INCREMENT (1 << 0) -#define TOC_CONTROL_COPY_PROHIBITED (0) -#define TOC_CONTROL_COPY_PERMITTED (1 << 1) - -/** read a sector from each track on disc to determine modes - @param d The drive. -*/ -void toc_find_modes(struct burn_drive *d); - -#endif /*__TOC_H*/ diff --git a/libburn/transport.h b/libburn/transport.h deleted file mode 100644 index 22c2000..0000000 --- a/libburn/transport.h +++ /dev/null @@ -1,361 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef __TRANSPORT -#define __TRANSPORT - -#include "libburn.h" -#include "os.h" - -#include <pthread.h> -/* sg data structures */ -#include <sys/types.h> - - -/* see os.h for name of particular os-*.h where this is defined */ -#define BUFFER_SIZE BURN_OS_TRANSPORT_BUFFER_SIZE - - -enum transfer_direction -{ TO_DRIVE, FROM_DRIVE, NO_TRANSFER }; - -/* end of sg data structures */ - -/* generic 'drive' data structures */ - -struct cue_sheet -{ - int count; - unsigned char *data; -}; - -struct params -{ - int speed; - int retries; -}; - -struct buffer -{ - /* ts A61219: - Added 4096 bytes reserve against possible buffer overflows. - (Changed in sector.c buffer flush test from >= to > BUFFER_SIZE . - This can at most cause a 1 sector overlap. Sometimes an offset - of 16 byte is applied to the output data (in some RAW mode). ) */ - unsigned char data[BUFFER_SIZE + 4096]; - int sectors; - int bytes; -}; - -struct command -{ - unsigned char opcode[16]; - int oplen; - int dir; - int dxfer_len; - unsigned char sense[128]; - int error; - int retry; - struct buffer *page; -}; - -struct burn_scsi_inquiry_data -{ - char vendor[9]; - char product[17]; - char revision[5]; - int valid; -}; - - -struct scsi_mode_data -{ - int buffer_size; - int dvdram_read; - int dvdram_write; - int dvdr_read; - int dvdr_write; - int dvdrom_read; - int cdrw_read; - int cdrw_write; - int cdr_read; - int cdr_write; - int simulate; - int max_read_speed; - int max_write_speed; - - /* ts A61021 */ - int min_write_speed; - - /* ts A61225 : Results from ACh GET PERFORMANCE, Type 03h - Speed values go into *_*_speed */ - int min_end_lba; - int max_end_lba; - struct burn_speed_descriptor *speed_descriptors; - - int cur_read_speed; - int cur_write_speed; - int retry_page_length; - int retry_page_valid; - int write_page_length; - int write_page_valid; - int c2_pointers; - int valid; - int underrun_proof; -}; - - -/* ts A70112 : represents a single Formattable Capacity Descriptor as of - mmc5r03c.pdf 6.24.3.3 . There can at most be 32 of them. */ -struct burn_format_descr { - /* format type: e.g 0x00 is "Full", 0x15 is "Quick" */ - int type; - - /* the size in bytes derived from Number of Blocks */ - off_t size; - - /* the Type Dependent Parameter (usually the write alignment size) */ - unsigned int 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; - int channel; - int lun; - char *devname; - - /* ts A70302: mmc5r03c.pdf 5.3.2 Physical Interface Standard */ - int phys_if_std; /* 1=SCSI, 2=ATAPI, 3,4,6=FireWire, 7=SATA, 8=USB */ - char phys_if_name[80]; /* MMC-5 5.3.2 table 91 , e.g. "SCSI Family" */ - - /* see os.h for name of particular os-*.h where this is defined */ - BURN_OS_TRANSPORT_DRIVE_ELEMENTS - - - /* ts A60904 : ticket 62, contribution by elmom */ - /** - Tells the index in scanned burn_drive_info array. - -1 if fallen victim to burn_drive_info_forget() - */ - int global_index; - - pthread_mutex_t access_lock; - - enum burn_disc_status status; - int erasable; - - /* ts A61201 from 46h GET CONFIGURATION */ - int current_profile; - char current_profile_text[80]; - int current_is_cd_profile; - int current_is_supported_profile; - - /* ts A70128 : MMC-to-MMC feature info from 46h for DVD-RW. - Quite internal. Regard as opaque :) - */ - /* 1 = incremental recording available, 0 = not available */ - int current_has_feat21h; - - /* Link Size item number 0 from feature 0021h descriptor */ - int current_feat21h_link_size; - - /* 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. - */ - int current_feat2fh_byte4; - - /* ts A70114 : whether 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*/ - - /* 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 */ - int best_format_type; - off_t best_format_size; - - /* The complete list of format descriptors as read with 23h */ - int num_format_descr; - struct burn_format_descr format_descriptors[32]; - - - volatile int released; - - /* 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 */ - int start_lba; - int end_lba; - - - /* ts A70131 : from 51h READ DISC INFORMATION Number of Sessions (-1)*/ - int complete_sessions; - /* ts A70129 : - from 51h READ DISC INFORMATION Last Track Number in Last Session */ - int last_track_no; - /* ts A70212 : 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. - (e.g. by d->send_write_parameters() ; d->get_nwa()). - */ - off_t media_capacity_remaining; - /* ts A70215 : if > 0 : first lba on media that is too high for write*/ - int media_lba_limit; - - - int toc_temp; - struct burn_disc *disc; /* disc structure */ - int block_types[4]; - struct buffer *buffer; - struct burn_progress progress; - - /* ts A70711 : keeping an eye on the drive buffer */ - off_t pessimistic_buffer_free; - 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; - - 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 *); - - /* ts A61021 */ - int (*drive_is_open) (struct burn_drive *); - - int (*issue_command) (struct burn_drive *, struct command *); - -/* lower level functions */ - void (*erase) (struct burn_drive *, int); - void (*getcaps) (struct burn_drive *); - - /* ts A61021 */ - void (*read_atip) (struct burn_drive *); - - int (*write) (struct burn_drive *, int, struct buffer *); - void (*read_toc) (struct burn_drive *); - void (*lock) (struct burn_drive *); - void (*unlock) (struct burn_drive *); - void (*eject) (struct burn_drive *); - void (*load) (struct burn_drive *); - int (*start_unit) (struct burn_drive *); - void (*read_disc_info) (struct burn_drive *); - void (*read_sectors) (struct burn_drive *, - int start, - int len, - const struct burn_read_opts *, struct buffer *); - void (*perform_opc) (struct burn_drive *); - void (*set_speed) (struct burn_drive *, int, int); - void (*send_parameters) (struct burn_drive *, - const struct burn_read_opts *); - void (*send_write_parameters) (struct burn_drive *, - const struct burn_write_opts *); - void (*send_cue_sheet) (struct burn_drive *, struct cue_sheet *); - - /* ts A70205 : Announce size of a DVD-R[W] DAO session. */ - int (*reserve_track) (struct burn_drive *d, off_t size); - - void (*sync_cache) (struct burn_drive *); - int (*get_erase_progress) (struct burn_drive *); - int (*get_nwa) (struct burn_drive *, int trackno, int *lba, int *nwa); - - /* ts A70131 : obtain (possibly fake) TOC number and start lba of - first track in last complete session */ - int (*read_multi_session_c1)(struct burn_drive *d, - int *trackno, int *start); - - /* ts A61009 : removed d in favor of o->drive */ - /* void (*close_disc) (struct burn_drive * d, - struct burn_write_opts * o); - void (*close_session) (struct burn_drive * d, - struct burn_write_opts * o); - */ - void (*close_disc) (struct burn_write_opts * o); - void (*close_session) ( struct burn_write_opts * o); - - /* ts A61029 */ - void (*close_track_session) ( struct burn_drive *d, - int session, int track); - - int (*test_unit_ready) (struct burn_drive * d); - void (*probe_write_modes) (struct burn_drive * d); - struct params params; - struct burn_scsi_inquiry_data *idata; - struct scsi_mode_data *mdata; - int toc_entries; - struct burn_toc_entry *toc_entry; - - /* ts A61023 : get size and free space of drive buffer */ - int (*read_buffer_capacity) (struct burn_drive *d); - - /* ts A61220 : format media (e.g. DVD+RW) */ - int (*format_unit) (struct burn_drive *d, off_t size, int flag); - - /* ts A70108 */ - /* 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 */ diff --git a/libburn/util.c b/libburn/util.c deleted file mode 100644 index c50821d..0000000 --- a/libburn/util.c +++ /dev/null @@ -1,60 +0,0 @@ -#include <string.h> - -/* ts A61008 */ -/* #include <a ssert.h> */ - -#include <stdlib.h> -#include "../version.h" -#include "util.h" -#include "libburn.h" - -char *burn_strdup(char *s) -{ - char *ret; - int l; - - /* ts A61008 */ - /* a ssert(s); */ - if (s == NULL) - return NULL; - - l = strlen(s) + 1; - ret = malloc(l); - memcpy(ret, s, l); - - return ret; -} - -char *burn_strndup(char *s, int n) -{ - char *ret; - int l; - - /* ts A61008 */ - /* a ssert(s); */ - /* a ssert(n > 0); */ - if (s == NULL || n <= 0) - return NULL; - - l = strlen(s); - ret = malloc(l < n ? l : n); - - memcpy(ret, s, l < n - 1 ? l : n - 1); - ret[n - 1] = '\0'; - - return ret; -} - -void burn_version(int *major, int *minor, int *micro) -{ -/* ts A80408 : switched from configure.ac versioning to libburn.h versioning */ -#ifdef burn_header_version_major - *major = burn_header_version_major; - *minor = burn_header_version_minor; - *micro = burn_header_version_micro; -#else - *major = BURN_MAJOR_VERSION; - *minor = BURN_MINOR_VERSION; - *micro = BURN_MICRO_VERSION; -#endif -} diff --git a/libburn/util.h b/libburn/util.h deleted file mode 100644 index 4e74895..0000000 --- a/libburn/util.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __UTIL -#define __UTIL - -char *burn_strdup(char *s); - -char *burn_strndup(char *s, int n); - -#endif diff --git a/libburn/write.c b/libburn/write.c deleted file mode 100644 index 9790fea..0000000 --- a/libburn/write.c +++ /dev/null @@ -1,2334 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#include <unistd.h> -#include <signal.h> - -/* ts A61009 */ -/* #include <a ssert.h> */ - - -/* ts A61106 : Deliberate defect provocation macros - DO NOT DEFINE THESE IF YOU WANT SUCCESSFUL TAO ! -#define Libburn_experimental_no_close_tracK 1 -#define Libburn_experimental_no_close_sessioN 1 -*/ - -/* ts A61114 : Highly experimental : try to achieve SAO on appendables - THIS DOES NOT WORK YET ! -#define Libburn_sao_can_appenD 1 -*/ - -#include <sys/types.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <stdlib.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/stat.h> -#include <sys/time.h> - -#include "error.h" -#include "sector.h" -#include "libburn.h" -#include "drive.h" -#include "transport.h" -#include "crc.h" -#include "debug.h" -#include "init.h" -#include "lec.h" -#include "toc.h" -#include "util.h" -#include "sg.h" -#include "write.h" -#include "options.h" -#include "structure.h" -#include "source.h" - -#include "libdax_msgs.h" -extern struct libdax_msgs *libdax_messenger; - - -/* The maximum output size to be used with CD media. This is also curbed - by BURN_OS_TRANSPORT_BUFFER_SIZE. The smaller number gets into effect. -*/ -#define Libburn_cd_obS (32 * 1024) - -/* The size to be used with DVD media. -*/ -#define Libburn_dvd_obS (32 * 1024) - -/* The size to be used with BD-RE media in normal, not streamed mode. -*/ -#define Libburn_bd_re_obS (32 * 1024) - -/* The size to be used with BD-RE media in streamed mode. -*/ -#define Libburn_bd_re_streamed_obS (64 * 1024) - - -static int type_to_ctrl(int mode) -{ - int ctrl = 0; - - int data = BURN_MODE2 | BURN_MODE1 | BURN_MODE0; - - if (mode & data) { - ctrl |= 4; - } else if (mode & BURN_AUDIO) { - if (mode & BURN_4CH) - ctrl |= 8; - if (mode & BURN_PREEMPHASIS) - ctrl |= 1; - } else - /* ts A61008 */ - /* a ssert(0); */ - return -1; - - if (mode & BURN_COPY) - ctrl |= 2; - - return ctrl; -} - -/* only the ctrl nibble is set here (not adr) */ -/* ts A61009 : removed "static" , reacted on type_to_ctrl() == -1 - preserved ignorance towards unknown modes (for now) */ -void type_to_form(int mode, unsigned char *ctladr, int *form) -{ - int ret; - - ret = type_to_ctrl(mode) << 4; - if (ret == -1) { - *ctladr = 0xff; - *form = -1; - return; - } - *ctladr = ret; - - if (mode & BURN_AUDIO) - *form = 0; - if (mode & BURN_MODE0) { - - /* ts A61009 */ - /* a ssert(0); */ - *form = -1; - return; - } - - if (mode & BURN_MODE1) - *form = 0x10; - if (mode & BURN_MODE2) { - - /* ts A61009 */ - /* a ssert(0); */ /* XXX someone's gonna want this sometime */ - *form = -1; - return; - } - - if (mode & BURN_MODE_RAW) - *form = 0; - if (mode & BURN_SUBCODE_P16) /* must be expanded to R96 */ - *form |= 0x40; - if (mode & BURN_SUBCODE_P96) - *form |= 0xC0; - if (mode & BURN_SUBCODE_R96) - *form |= 0x40; -} - - -/* ts A71002 : outsourced from burn_write_flush() : no sync cache here */ -int burn_write_flush_buffer(struct burn_write_opts *o,struct burn_track *track) -{ - struct burn_drive *d = o->drive; - - if (d->buffer->bytes && !d->cancel) { - int err; - err = d->write(d, d->nwa, d->buffer); - if (err == BE_CANCELLED) - return 0; - /* A61101 */ - if(track != NULL) { - track->writecount += d->buffer->bytes; - track->written_sectors += d->buffer->sectors; - } - /* ts A61119 */ - d->progress.buffered_bytes += d->buffer->bytes; - - d->nwa += d->buffer->sectors; - d->buffer->bytes = 0; - d->buffer->sectors = 0; - } - return 1; -} - - -int burn_write_flush(struct burn_write_opts *o, struct burn_track *track) -{ - int ret; - struct burn_drive *d = o->drive; - - ret = burn_write_flush_buffer(o, track); - if (ret <= 0) - return ret; - d->sync_cache(d); - return 1; -} - - -/* ts A71002 : outsourced from burn_write_close_track() */ -int burn_write_track_minsize(struct burn_write_opts *o, struct burn_session *s, - int tnum) -{ - char msg[81]; - struct burn_drive *d; - struct burn_track *t; - int todo, step, cancelled, seclen; - - d = o->drive; - t = s->track[tnum]; - - /* ts A61103 : pad up track to minimum size of 600 sectors */ - if (t->written_sectors < 300) { - todo = 300 - t->written_sectors; - sprintf(msg,"Padding up track to minimum size (+ %d sectors)", - todo); - libdax_msgs_submit(libdax_messenger, o->drive->global_index, - 0x0002011a, - LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH, msg,0,0); - step = BUFFER_SIZE / 4096; /* shall fit any sector size */ - if (step <= 0) - step = 1; - seclen = burn_sector_length(t->mode); - if (seclen <= 0) - seclen = 2048; - memset(d->buffer, 0, sizeof(struct buffer)); - cancelled = d->cancel; - for (; todo > 0; todo -= step) { - if (step > todo) - step = todo; - d->buffer->bytes = step*seclen; - d->buffer->sectors = step; - d->cancel = 0; - d->write(d, d->nwa, d->buffer); - d->nwa += d->buffer->sectors; - t->writecount += d->buffer->bytes; - t->written_sectors += d->buffer->sectors; - d->progress.buffered_bytes += d->buffer->bytes; - } - d->cancel = cancelled; - } - return 1; -} - - -/* ts A61030 */ -int burn_write_close_track(struct burn_write_opts *o, struct burn_session *s, - int tnum) -{ - char msg[81]; - struct burn_drive *d; - struct burn_track *t; - - /* ts A61106 */ -#ifdef Libburn_experimental_no_close_tracK - return 1; -#endif - - d = o->drive; - t = s->track[tnum]; - - d->busy = BURN_DRIVE_CLOSING_TRACK; - - sprintf(msg, "Closing track %2.2d", tnum+1); - libdax_msgs_submit(libdax_messenger, o->drive->global_index,0x00020119, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, msg,0,0); - - /* MMC-1 mentions track number 0xFF for "the incomplete track", - MMC-3 does not. I tried both. 0xFF was in effect when other - bugs finally gave up and made way for readable tracks. */ - /* ts A70129 - Probably the right value for appendables is d->last_track_no - */ - d->close_track_session(o->drive, 0, 0xff); - - d->busy = BURN_DRIVE_WRITING; - - return 1; -} - - - -/* ts A61030 */ -int burn_write_close_session(struct burn_write_opts *o, struct burn_session *s) -{ - - /* ts A61106 */ -#ifdef Libburn_experimental_no_close_sessioN - return 1; -#endif - - libdax_msgs_submit(libdax_messenger, o->drive->global_index,0x00020119, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, - "Closing session", 0, 0); - - /* ts A61102 */ - o->drive->busy = BURN_DRIVE_CLOSING_SESSION; - - o->drive->close_track_session(o->drive, 1, 0); - - /* ts A61102 */ - o->drive->busy = BURN_DRIVE_WRITING; - - return 1; -} - - -/* ts A60819: - This is unused since about Feb 2006, icculus.org/burn CVS. - The compiler complains. We shall please our compiler. -*/ -#ifdef Libburn_write_with_function_print_cuE - -static void print_cue(struct cue_sheet *sheet) -{ - int i; - unsigned char *unit; - - printf("\n"); - printf("ctladr|trno|indx|form|scms| msf\n"); - printf("------+----+----+----+----+--------\n"); - for (i = 0; i < sheet->count; i++) { - unit = sheet->data + 8 * i; - printf(" %1X %1X | %02X | %02X | %02X | %02X |", - (unit[0] & 0xf0) >> 4, unit[0] & 0xf, unit[1], unit[2], - unit[3], unit[4]); - printf("%02X:%02X:%02X\n", unit[5], unit[6], unit[7]); - } -} - -#endif /* Libburn_write_with_print_cuE */ - - -/* ts A61009 : changed type from void to int */ -/** @return 1 = success , <=0 failure */ -static int add_cue(struct cue_sheet *sheet, unsigned char ctladr, - unsigned char tno, unsigned char indx, - unsigned char form, unsigned char scms, int lba) -{ - unsigned char *unit; - unsigned char *ptr; - int m, s, f; - - burn_lba_to_msf(lba, &m, &s, &f); - - sheet->count++; - ptr = realloc(sheet->data, sheet->count * 8); - - /* ts A61009 */ - /* a ssert(ptr); */ - if (ptr == NULL) { - libdax_msgs_submit(libdax_messenger, -1, 0x00020111, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "Could not allocate new auxiliary object (cue_sheet->data)", - 0, 0); - return -1; - } - - sheet->data = ptr; - unit = sheet->data + (sheet->count - 1) * 8; - unit[0] = ctladr; - unit[1] = tno; - unit[2] = indx; - unit[3] = form; - unit[4] = scms; - unit[5] = m; - unit[6] = s; - unit[7] = f; - return 1; -} - -/* ts A61114: added parameter nwa */ -struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o, - struct burn_session *session, - int nwa) -{ - int i, m, s, f, form, pform, runtime = -150, ret, track_length; - unsigned char ctladr; - struct burn_drive *d; - struct burn_toc_entry *e; - struct cue_sheet *sheet; - struct burn_track **tar = session->track; - int ntr = session->tracks; - int rem = 0; - - d = o->drive; - -#ifdef Libburn_sao_can_appenD - if (d->status == BURN_DISC_APPENDABLE) - runtime = nwa-150; -#endif - - sheet = malloc(sizeof(struct cue_sheet)); - - /* ts A61009 : react on failures of malloc(), add_cue_sheet() - type_to_form() */ - if (sheet == NULL) { - libdax_msgs_submit(libdax_messenger, -1, 0x00020111, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "Could not allocate new auxiliary object (cue_sheet)", - 0, 0); - return NULL; - } - - sheet->data = NULL; - sheet->count = 0; - type_to_form(tar[0]->mode, &ctladr, &form); - if (form == -1) { - libdax_msgs_submit(libdax_messenger, -1, 0x00020116, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "Track mode has unusable value", 0, 0); - goto failed; - } - ret = add_cue(sheet, ctladr | 1, 0, 0, 1, 0, runtime); - if (ret <= 0) - goto failed; - ret = add_cue(sheet, ctladr | 1, 1, 0, form, 0, runtime); - if (ret <= 0) - goto failed; - runtime += 150; - - burn_print(1, "toc for %d tracks:\n", ntr); - d->toc_entries = ntr + 3; - - /* ts A61009 */ - /* a ssert(d->toc_entry == NULL); */ - if (d->toc_entry != NULL) { - - /* ts A61109 : this happens with appendable CDs - >>> Open question: is the existing TOC needed ? */ - - /* ts A61109 : for non-SAO, this sheet is thrown away later */ - free((char *) d->toc_entry); - - /* - libdax_msgs_submit(libdax_messenger, - d->global_index, 0x00020117, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "toc_entry of drive is already in use", 0, 0); - goto failed; - */ - } - - d->toc_entry = calloc(d->toc_entries, sizeof(struct burn_toc_entry)); - e = d->toc_entry; - e[0].point = 0xA0; - if (tar[0]->mode & BURN_AUDIO) - e[0].control = TOC_CONTROL_AUDIO; - else - e[0].control = TOC_CONTROL_DATA; - e[0].pmin = 1; - e[0].psec = o->format; - e[0].adr = 1; - e[1].point = 0xA1; - e[1].pmin = ntr; - e[1].adr = 1; - if (tar[ntr - 1]->mode & BURN_AUDIO) - e[1].control = TOC_CONTROL_AUDIO; - else - e[1].control = TOC_CONTROL_DATA; - e[2].point = 0xA2; - e[2].control = e[1].control; - e[2].adr = 1; - - /* ts A70121 : The pause before the first track is not a Pre-gap. - To count it as part 2 of a Pre-gap is a dirty hack. It also seems - to have caused confusion in dealing with part 1 of an eventual - real Pre-gap. mmc5r03c.pdf 6.33.3.2, 6.33.3.18 . - */ - tar[0]->pregap2 = 1; - - pform = form; - for (i = 0; i < ntr; i++) { - type_to_form(tar[i]->mode, &ctladr, &form); - - - /* ts A70121 : This seems to be thw wrong test. Correct would - be to compare tar[]->mode or bit2 of ctladr. - */ - - if (pform != form) { - - ret = add_cue(sheet, ctladr | 1, i + 1, 0, form, 0, - runtime); - if (ret <= 0) - goto failed; - - runtime += 150; -/* XXX fix pregap interval 1 for data tracks */ -/* ts A60813 silence righteous compiler warning about C++ style comments - This is possibly not a comment but rather a trace of Derek Foreman - experiments. Thus not to be beautified - but to be preserved rectified. -/ / if (!(form & BURN_AUDIO)) -/ / tar[i]->pregap1 = 1; -*/ -/* ts A70121 : it is unclear why (form & BURN_AUDIO) should prevent pregap1. - I believe, correct would be: - runtime += 75; - tar[i]->pregap1 = 1; - - The test for pform != form is wrong anyway. - - Next one has to care for Post-gap: table 555 in mmc5r03c.pdf does not - show any although 6.33.3.19 would prescribe some. - - Nobody seems to have ever tested this situation, up to now. - It is banned for now in burn_disc_write(). - Warning have been placed in libburn.h . -*/ - - tar[i]->pregap2 = 1; - } -/* XXX HERE IS WHERE WE DO INDICES IN THE CUE SHEET */ -/* XXX and we should make sure the gaps conform to ecma-130... */ - tar[i]->entry = &e[3 + i]; - e[3 + i].point = i + 1; - burn_lba_to_msf(runtime, &m, &s, &f); - e[3 + i].pmin = m; - e[3 + i].psec = s; - e[3 + i].pframe = f; - e[3 + i].adr = 1; - e[3 + i].control = type_to_ctrl(tar[i]->mode); - burn_print(1, "track %d control %d\n", tar[i]->mode, - e[3 + i].control); - - ret = add_cue(sheet, ctladr | 1, i + 1, 1, form, 0, runtime); - if (ret <= 0) - goto failed; - - /* ts A70125 : - Still not understanding the sense behind linking tracks, - i decided to at least enforce the MMC specs' minimum - track length. - */ - track_length = burn_track_get_sectors(tar[i]); - if (track_length < 300 && !burn_track_is_open_ended(tar[i])) { - track_length = 300; - if (!tar[i]->pad) - tar[i]->pad = 1; - burn_track_set_sectors(tar[i], track_length); - } - runtime += track_length; - -/* if we're padding, we'll clear any current shortage. - if we're not, we'll slip toc entries by a sector every time our - shortage is more than a sector -XXX this is untested :) -*/ - if (!tar[i]->pad) { - rem += burn_track_get_shortage(tar[i]); - - /* ts A61101 : I doubt that linking would yield a - desireable effect. With TAO it is - counterproductive in any way. - */ - if (o->write_type == BURN_WRITE_TAO) - tar[i]->source->next = NULL; - else - - if (i +1 != ntr) - tar[i]->source->next = tar[i+1]->source; - } else if (rem) { - rem = 0; - runtime++; - } - if (rem > burn_sector_length(tar[i]->mode)) { - rem -= burn_sector_length(tar[i]->mode); - runtime--; - } - pform = form; - } - burn_lba_to_msf(runtime, &m, &s, &f); - e[2].pmin = m; - e[2].psec = s; - e[2].pframe = f; - burn_print(1, "run time is %d (%d:%d:%d)\n", runtime, m, s, f); - for (i = 0; i < d->toc_entries; i++) - burn_print(1, "point %d (%02d:%02d:%02d)\n", - d->toc_entry[i].point, d->toc_entry[i].pmin, - d->toc_entry[i].psec, d->toc_entry[i].pframe); - ret = add_cue(sheet, ctladr | 1, 0xAA, 1, 1, 0, runtime); - if (ret <= 0) - goto failed; - return sheet; - -failed:; - if (sheet != NULL) - free((char *) sheet); - return NULL; -} - -int burn_sector_length(int tracktype) -{ - if (tracktype & BURN_AUDIO) - return 2352; - if (tracktype & BURN_MODE_RAW) - return 2352; - if (tracktype & BURN_MODE1) - return 2048; - /* ts A61009 */ - /* a ssert(0); */ - return -1; -} - -int burn_subcode_length(int tracktype) -{ - if (tracktype & BURN_SUBCODE_P16) - return 16; - if ((tracktype & BURN_SUBCODE_P96) || (tracktype & BURN_SUBCODE_R96)) - return 96; - return 0; -} - -int burn_write_leadin(struct burn_write_opts *o, - struct burn_session *s, int first) -{ - struct burn_drive *d = o->drive; - int count; - - d->busy = BURN_DRIVE_WRITING_LEADIN; - - burn_print(5, first ? " first leadin\n" : " leadin\n"); - - if (first) - count = 0 - d->alba - 150; - else - count = 4500; - - d->progress.start_sector = d->alba; - d->progress.sectors = count; - d->progress.sector = 0; - - while (count != 0) { - if (!sector_toc(o, s->track[0]->mode)) - return 0; - count--; - d->progress.sector++; - } - d->busy = BURN_DRIVE_WRITING; - return 1; -} - -int burn_write_leadout(struct burn_write_opts *o, - int first, unsigned char control, int mode) -{ - struct burn_drive *d = o->drive; - int count; - - d->busy = BURN_DRIVE_WRITING_LEADOUT; - - d->rlba = -150; - burn_print(5, first ? " first leadout\n" : " leadout\n"); - if (first) - count = 6750; - else - count = 2250; - d->progress.start_sector = d->alba; - d->progress.sectors = count; - d->progress.sector = 0; - - while (count != 0) { - if (!sector_lout(o, control, mode)) - return 0; - count--; - d->progress.sector++; - } - d->busy = BURN_DRIVE_WRITING; - return 1; -} - -int burn_write_session(struct burn_write_opts *o, struct burn_session *s) -{ - struct burn_drive *d = o->drive; - struct burn_track *prev = NULL, *next = NULL; - int i, ret; - - d->rlba = 0; - burn_print(1, " writing a session\n"); - for (i = 0; i < s->tracks; i++) { - if (i > 0) - prev = s->track[i - 1]; - if (i + 1 < s->tracks) - next = s->track[i + 1]; - else - next = NULL; - - if (!burn_write_track(o, s, i)) - { ret = 0; goto ex; } - } - - /* ts A61103 */ - ret = 1; -ex:; - if (o->write_type == BURN_WRITE_TAO) - burn_write_close_session(o, s); - return ret; -} - - -/* ts A61218 : outsourced from burn_write_track() */ -int burn_disc_init_track_status(struct burn_write_opts *o, - struct burn_session *s, int tnum, int sectors) -{ - struct burn_drive *d = o->drive; - - /* Update progress */ - d->progress.start_sector = d->nwa; - d->progress.sectors = sectors; - d->progress.sector = 0; - - /* ts A60831: added tnum-line, extended print message on proposal - by bonfire-app@wanadoo.fr in http://libburn.pykix.org/ticket/58 */ - d->progress.track = tnum; - - /* ts A61102 */ - d->busy = BURN_DRIVE_WRITING; - - return 1; -} - - -int burn_write_track(struct burn_write_opts *o, struct burn_session *s, - int tnum) -{ - struct burn_track *t = s->track[tnum]; - struct burn_drive *d = o->drive; - int i, tmp = 0, open_ended = 0, ret= 0, nwa, lba; - int sectors; - char msg[80]; - - d->rlba = -150; - -/* XXX for tao, we don't want the pregaps but still want post? */ - if (o->write_type != BURN_WRITE_TAO) { - - /* ts A61102 */ - d->busy = BURN_DRIVE_WRITING_PREGAP; - - if (t->pregap1) - d->rlba += 75; - if (t->pregap2) - d->rlba += 150; - - if (t->pregap1) { - - struct burn_track *pt; - /* ts A70121 : Removed pseudo suicidal initializer - = s->track[tnum - 1]; - */ - - if (tnum == 0) { - - /* ts A70121 : This is not possible because - track 1 cannot have a pregap at all. - MMC-5 6.33.3.2 precribes a mandatory pause - prior to any track 1. Pre-gap is prescribed - for mode changes like audio-to-data. - To set burn_track.pregap1 for track 1 is - kindof a dirty hack. - */ - - printf("first track should not have a pregap1\n"); - pt = t; - } else - pt = s->track[tnum - 1]; /* ts A70121 */ - for (i = 0; i < 75; i++) - if (!sector_pregap(o, t->entry->point, - pt->entry->control, pt->mode)) - { ret = 0; goto ex; } - } - if (t->pregap2) - for (i = 0; i < 150; i++) - if (!sector_pregap(o, t->entry->point, - t->entry->control, t->mode)) - { ret = 0; goto ex; } - } else { - o->control = t->entry->control; - d->send_write_parameters(d, o); - - /* ts A61103 */ - ret = d->get_nwa(d, -1, &lba, &nwa); - - /* ts A70213: CD-TAO: eventually expand size of track to max */ - burn_track_apply_fillup(t, d->media_capacity_remaining, 0); - - /* <<< */ - sprintf(msg, - "TAO pre-track %2.2d : get_nwa(%d)=%d, d=%d , demand=%.f , cap=%.f\n", - tnum+1, nwa, ret, d->nwa, (double) burn_track_get_sectors(t) * 2048.0, - (double) d->media_capacity_remaining); - libdax_msgs_submit(libdax_messenger, d->global_index, 0x000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - msg, 0, 0); - if (nwa > d->nwa) - d->nwa = nwa; - - } - -/* user data */ - - sectors = burn_track_get_sectors(t); - open_ended = burn_track_is_open_ended(t); - - burn_disc_init_track_status(o, s, tnum, sectors); - - burn_print(12, "track %d is %d sectors long\n", tnum, sectors); - - /* ts A61030 : this cannot happen. tnum is always < s->tracks */ - if (tnum == s->tracks) - tmp = sectors > 150 ? 150 : sectors; - - for (i = 0; open_ended || i < sectors - tmp; i++) { - - /* ts A61023 : http://libburn.pykix.org/ticket/14 - From time to time inquire drive buffer */ - if ((i%64)==0) - d->read_buffer_capacity(d); - - if (!sector_data(o, t, 0)) - { ret = 0; goto ex; } - - /* ts A61031 */ - if (open_ended) { - d->progress.sectors = sectors = i; - if (burn_track_is_data_done(t)) - break; - } - - /* update current progress */ - d->progress.sector++; - } - for (; i < sectors; i++) { - - /* ts A61030: program execution never gets to this point */ - fprintf(stderr,"LIBBURN_DEBUG: TNUM=%d TRACKS=%d TMP=%d\n", - tnum, s->tracks, tmp); - - burn_print(1, "last track, leadout prep\n"); - - /* ts A61023 */ - if ((i%64)==0) - d->read_buffer_capacity(d); - - if (!sector_data(o, t, 1)) - { ret = 0; goto ex; } - - /* update progress */ - d->progress.sector++; - } - - if (t->postgap) - for (i = 0; i < 150; i++) - if (!sector_postgap(o, t->entry->point, t->entry->control, - t->mode)) - { ret = 0; goto ex; } - i = t->offset; - if (o->write_type == BURN_WRITE_SAO) { - if (d->buffer->bytes) { - int err; - err = d->write(d, d->nwa, d->buffer); - if (err == BE_CANCELLED) - { ret = 0; goto ex; } - - /* A61101 : probably this is not all payload data */ - /* A61108 : but audio count is short without this */ - t->writecount += d->buffer->bytes; - t->written_sectors += d->buffer->sectors; - d->progress.buffered_bytes += d->buffer->bytes; - - d->nwa += d->buffer->sectors; - d->buffer->bytes = 0; - d->buffer->sectors = 0; - } - } - - /* ts A61103 */ - ret = 1; -ex:; - if (d->cancel) - burn_source_cancel(t->source); - if (o->write_type == BURN_WRITE_TAO) { - - /* ts A71002 */ - if (!burn_write_flush_buffer(o, t)) - ret = 0; - - /* Ensure that at least 600 kB get written */ - burn_write_track_minsize(o, s, tnum); - d->sync_cache(d); - - /* ts A61030 */ - if (burn_write_close_track(o, s, tnum) <= 0) - ret = 0; - } - return ret; -} - -/* ts A61009 */ -/* @param flag bit1 = do not libdax_msgs_submit() */ -int burn_disc_write_is_ok(struct burn_write_opts *o, struct burn_disc *disc, - int flag) -{ - int i, t; - char msg[80]; - - for (i = 0; i < disc->sessions; i++) - for (t = 0; t < disc->session[i]->tracks; t++) - if (!sector_headers_is_ok( - o, disc->session[i]->track[t]->mode)) - goto bad_track_mode_found; - return 1; -bad_track_mode_found:; - sprintf(msg, "Unsuitable track mode 0x%x in track %d of session %d", - disc->session[i]->track[t]->mode, i+1, t+1); - if (!(flag & 2)) - libdax_msgs_submit(libdax_messenger, -1, 0x0002010a, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - return 0; -} - - -/* ts A61218 : outsourced from burn_disc_write_sync() */ -int burn_disc_init_write_status(struct burn_write_opts *o, - struct burn_disc *disc) -{ - struct burn_drive *d = o->drive; - struct burn_track *t = NULL; - int sx, tx; - - d->cancel = 0; - - /* init progress before showing the state */ - d->progress.session = 0; - d->progress.sessions = disc->sessions; - d->progress.track = 0; - d->progress.tracks = disc->session[0]->tracks; - /* TODO: handle indices */ - d->progress.index = 0; - d->progress.indices = disc->session[0]->track[0]->indices; - /* TODO: handle multissession discs */ - /* XXX: sectors are only set during write track */ - d->progress.start_sector = 0; - d->progress.sectors = 0; - d->progress.sector = 0; - d->progress.track = 0; - - /* ts A61023 */ - d->progress.buffer_capacity = 0; - d->progress.buffer_available = 0; - d->progress.buffered_bytes = 0; - d->progress.buffer_min_fill = 0xffffffff; - - /* ts A70711 */ - d->pessimistic_buffer_free = 0; - d->pbf_altered = 0; - d->pessimistic_writes = 0; - d->waited_writes = 0; - d->waited_tries = 0; - d->waited_usec = 0; - - /* Set eventual media fill up for last track only */ - for (sx = 0; sx < disc->sessions; sx++) - for (tx = 0 ; tx < disc->session[sx]->tracks; tx++) { - t = disc->session[sx]->track[tx]; - burn_track_set_fillup(t, 0); - } - if (o->fill_up_media && t != NULL) - burn_track_set_fillup(t, 1); - - d->busy = BURN_DRIVE_WRITING; - - return 1; -} - - -/* ts A70219 : API */ -int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc, - char reasons[BURN_REASONS_LEN], int silent) -{ - enum burn_write_types wt; - struct burn_drive *d = o->drive; - char msg[160], *reason_pt; - int no_media = 0; - - reason_pt= reasons; - reasons[0] = 0; - - if (d->drive_role == 0) { - sprintf(reasons, - "DRIVE: is a virtual placeholder (null-drive)"); - no_media = 1; - goto ex; - } - - /* check write mode against write job */ - wt = burn_write_opts_auto_write_type(o, disc, reasons, 1); - if (wt == BURN_WRITE_NONE) { - if (strncmp(reasons, "MEDIA: ", 7)==0) - no_media = 1; - goto ex; - } - - sprintf(reasons, "%s: ", d->current_profile_text); - reason_pt= reasons + strlen(reasons); - if (d->status == BURN_DISC_UNSUITABLE) - goto unsuitable_profile; - if (d->drive_role == 2 || - d->current_profile == 0x1a || d->current_profile == 0x12 || - d->current_profile == 0x43) { - /* DVD+RW , DVD-RAM , BD-RE, emulated drive on stdio file */ - if (o->start_byte >= 0 && (o->start_byte % 2048)) - strcat(reasons, - "write start address not properly aligned to 2048, "); - } else if (d->current_profile == 0x09 || d->current_profile == 0x0a) { - /* CD-R , CD-RW */ - if (!burn_disc_write_is_ok(o, disc, (!!silent) << 1)) - strcat(reasons, "unsuitable track mode found, "); - if (o->start_byte >= 0) - strcat(reasons, "write start address not supported, "); - } else if (d->current_profile == 0x13) { - /* DVD-RW Restricted Overwrite */ - if (o->start_byte >= 0 && (o->start_byte % 32768)) - strcat(reasons, - "write start address not properly aligned to 32k, "); - } else if (d->drive_role == 3 || - d->current_profile == 0x11 || d->current_profile == 0x14 || - d->current_profile == 0x15 || - d->current_profile == 0x1b || d->current_profile == 0x2b ) { - /* DVD-R* Sequential , DVD+R[/DL] , sequential stdio "drive" */ - if (o->start_byte >= 0) - strcat(reasons, "write start address not supported, "); - } else { -unsuitable_profile:; - sprintf(msg, "Unsuitable media detected. Profile %4.4Xh %s", - d->current_profile, d->current_profile_text); - if (!silent) - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x0002011e, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - strcat(reasons, "no suitable media profile detected, "); - return 0; - } -ex:; - if (reason_pt[0]) { - if (no_media) { - if (!silent) - libdax_msgs_submit(libdax_messenger, - d->global_index, 0x0002013a, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "No suitable media detected", 0, 0); - return -1; - } - if (!silent) - libdax_msgs_submit(libdax_messenger, - d->global_index, 0x00020139, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Write job parameters are unsuitable", 0, 0); - return 0; - } - return 1; -} - - -/* ts A70129 : learned much from dvd+rw-tools-7.0/growisofs_mmc.cpp */ -int burn_disc_open_track_dvd_minus_r(struct burn_write_opts *o, - struct burn_session *s, int tnum) -{ - struct burn_drive *d = o->drive; - char msg[160]; - int ret, lba, nwa; - off_t size; - - d->send_write_parameters(d, o); - ret = d->get_nwa(d, -1, &lba, &nwa); - sprintf(msg, - "DVD pre-track %2.2d : get_nwa(%d), ret= %d , d->nwa= %d", - tnum+1, nwa, ret, d->nwa); - libdax_msgs_submit(libdax_messenger, d->global_index, 0x000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, msg,0,0); - if (nwa > d->nwa) - d->nwa = nwa; - /* ts A70214 : eventually adjust already expanded size of track */ - burn_track_apply_fillup(s->track[tnum], d->media_capacity_remaining,1); - - if (o->write_type == BURN_WRITE_SAO) { /* DAO */ - /* Round track size up to 32 KiB and reserve track */ - size = ((off_t) burn_track_get_sectors(s->track[tnum])) - * (off_t) 2048; - size = (size + (off_t) 0x7fff) & ~((off_t) 0x7fff); - ret = d->reserve_track(d, size); - if (ret <= 0) { - sprintf(msg, "Cannot reserve track of %.f bytes", - (double) size); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020138, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - return 0; - } - } - return 1; -} - - -/* ts A70226 */ -int burn_disc_open_track_dvd_plus_r(struct burn_write_opts *o, - struct burn_session *s, int tnum) -{ - struct burn_drive *d = o->drive; - char msg[160]; - int ret, lba, nwa; - off_t size; - - ret = d->get_nwa(d, -1, &lba, &nwa); - sprintf(msg, - "DVD+R pre-track %2.2d : get_nwa(%d), ret= %d , d->nwa= %d", - tnum+1, nwa, ret, d->nwa); - libdax_msgs_submit(libdax_messenger, d->global_index, 0x000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, msg,0,0); - if (nwa > d->nwa) - d->nwa = nwa; - /* ts A70214 : eventually adjust already expanded size of track */ - burn_track_apply_fillup(s->track[tnum], d->media_capacity_remaining,1); - - if (o->write_type == BURN_WRITE_SAO && - ! burn_track_is_open_ended(s->track[tnum])) { - /* Round track size up to 32 KiB and reserve track */ - size = ((off_t) burn_track_get_sectors(s->track[tnum])) - * (off_t) 2048; - size = (size + (off_t) 0x7fff) & ~((off_t) 0x7fff); - ret = d->reserve_track(d, size); - if (ret <= 0) { - sprintf(msg, "Cannot reserve track of %.f bytes", - (double) size); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020138, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - return 0; - } - } - return 1; -} - - -/* ts A70129 */ -int burn_disc_close_track_dvd_minus_r(struct burn_write_opts *o, - struct burn_session *s, int tnum) -{ - struct burn_drive *d = o->drive; - char msg[80]; - - /* only with Incremental writing */ - if (o->write_type != BURN_WRITE_TAO) - return 2; - - sprintf(msg, "Closing track %2.2d (absolute track number %d)", - tnum + 1, d->last_track_no); - libdax_msgs_submit(libdax_messenger, o->drive->global_index,0x00020119, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, msg,0,0); - - d->busy = BURN_DRIVE_CLOSING_SESSION; - /* Ignoring tnum here and hoping that d->last_track_no is correct */ - d->close_track_session(d, 0, d->last_track_no); /* CLOSE TRACK, 001b */ - d->busy = BURN_DRIVE_WRITING; - d->last_track_no++; - return 1; -} - - -/* ts A70229 */ -int burn_disc_finalize_dvd_plus_r(struct burn_write_opts *o) -{ - struct burn_drive *d = o->drive; - - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - "Finalizing DVD+R ...", 0, 0); - - /* CLOSE SESSION, 101b, Finalize with minimal radius */ - d->close_track_session(d, 2, 1); /* (2<<1)|1 = 5 */ - - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - "... finalizing DVD+R done ", 0, 0); - - return 1; -} - - -/* ts A70226 */ -int burn_disc_close_track_dvd_plus_r(struct burn_write_opts *o, - struct burn_session *s, int tnum, int is_last_track) -{ - struct burn_drive *d = o->drive; - char msg[80]; - - sprintf(msg, - "Closing track %2.2d (absolute track and session number %d)", - tnum + 1, d->last_track_no); - libdax_msgs_submit(libdax_messenger, o->drive->global_index,0x00020119, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, msg,0,0); - - d->busy = BURN_DRIVE_CLOSING_SESSION; - d->close_track_session(d, 0, d->last_track_no); /* CLOSE TRACK, 001b */ - - /* Each session becomes a single logical track. So to distinguish them, - it is mandatory to close the session together with each track. */ - - if (is_last_track && !o->multi) - burn_disc_finalize_dvd_plus_r(o); - else - d->close_track_session(d, 1, 0); /* CLOSE SESSION, 010b */ - d->busy = BURN_DRIVE_WRITING; - d->last_track_no++; - return 1; -} - - -/* ts A61218 - A70129 */ -int burn_dvd_write_track(struct burn_write_opts *o, - struct burn_session *s, int tnum, int is_last_track) -{ - struct burn_track *t = s->track[tnum]; - struct burn_drive *d = o->drive; - struct buffer *out = d->buffer; - int sectors; - int i, open_ended = 0, ret= 0, is_flushed = 0; - - /* ts A70213 : eventually expand size of track to max */ - burn_track_apply_fillup(t, d->media_capacity_remaining, 0); - - if (d->current_profile == 0x11 || d->current_profile == 0x14 || - d->current_profile == 0x15) { - /* DVD-R, DVD-RW Sequential, DVD-R/DL Sequential */ - ret = burn_disc_open_track_dvd_minus_r(o, s, tnum); - if (ret <= 0) - goto ex; - } else if (d->current_profile == 0x1b || d->current_profile == 0x2b) { - /* DVD+R , DVD+R/DL */ - ret = burn_disc_open_track_dvd_plus_r(o, s, tnum); - if (ret <= 0) - goto ex; - } - - sectors = burn_track_get_sectors(t); - open_ended = burn_track_is_open_ended(t); - /* <<< */ - { - char msg[160]; - - sprintf(msg, - "DVD pre-track %2.2d : demand=%.f%s, cap=%.f\n", - tnum+1, (double) sectors * 2048.0, - (open_ended ? " (open ended)" : ""), - (double) d->media_capacity_remaining); - libdax_msgs_submit(libdax_messenger, d->global_index, 0x000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - msg, 0, 0); - } - - - /* (offset padding is done within sector_data()) */ - - burn_disc_init_track_status(o, s, tnum, sectors); - for (i = 0; open_ended || i < sectors; i++) { - - /* From time to time inquire drive buffer */ - if ((i%256)==0) - d->read_buffer_capacity(d); - - /* transact a (CD sized) sector */ - if (!sector_data(o, t, 0)) - { ret = 0; goto ex; } - - if (open_ended) { - d->progress.sectors = sectors = i; - if (burn_track_is_data_done(t)) - break; - } - - /* update current progress */ - d->progress.sector++; - } - - /* (tail padding is done in sector_data()) */ - - /* Pad up buffer to next full o->obs (usually 32 kB) */ - if (o->obs_pad && out->bytes > 0 && out->bytes < o->obs) { - memset(out->data + out->bytes, 0, o->obs - out->bytes); - out->sectors += (o->obs - out->bytes) / 2048; - out->bytes = o->obs; - } - ret = burn_write_flush(o, t); - if (ret <= 0) - goto ex; - is_flushed = 1; - - /* Eventually finalize track */ - if (d->current_profile == 0x11 || d->current_profile == 0x14 || - d->current_profile == 0x15) { - /* DVD-R, DVD-RW Sequential, DVD-R/DL Sequential */ - ret = burn_disc_close_track_dvd_minus_r(o, s, tnum); - if (ret <= 0) - goto ex; - } else if (d->current_profile == 0x1b || d->current_profile == 0x2b) { - /* DVD+R , DVD+R/DL */ - ret = burn_disc_close_track_dvd_plus_r(o, s, tnum, - is_last_track); - if (ret <= 0) - goto ex; - } - ret = 1; -ex:; - if (d->cancel) - burn_source_cancel(t->source); - if (!is_flushed) - d->sync_cache(d); /* burn_write_flush() was not called */ - return ret; -} - - -/* ts A61219 */ -int burn_disc_close_session_dvd_plus_rw(struct burn_write_opts *o, - struct burn_session *s) -{ - struct burn_drive *d = o->drive; - - d->busy = BURN_DRIVE_CLOSING_SESSION; - /* This seems to be a quick end : "if (!dvd_compat)" */ - /* >>> Stop de-icing (ongoing background format) quickly - by mmc_close() (but with opcode[2]=0). - Wait for unit to get ready. - return 1; - */ - /* Else: end eventual background format in a "DVD-RO" compatible way */ - d->close_track_session(d, 1, 0); /* same as CLOSE SESSION for CD */ - d->busy = BURN_DRIVE_WRITING; - return 1; -} - - -/* ts A61228 */ -int burn_disc_close_session_dvd_minus_rw(struct burn_write_opts *o, - struct burn_session *s) -{ - struct burn_drive *d = o->drive; - - d->busy = BURN_DRIVE_CLOSING_SESSION; - if (d->current_profile == 0x13) { - d->close_track_session(d, 1, 0); /* CLOSE SESSION, 010b */ - - /* ??? under what circumstances to use close functiom 011b - "Finalize disc" ? */ - - } - d->busy = BURN_DRIVE_WRITING; - return 1; -} - - -/* ts A70129 : for profile 0x11 DVD-R, 0x14 DVD-RW Seq, 0x15 DVD-R/DL Seq */ -int burn_disc_close_session_dvd_minus_r(struct burn_write_opts *o, - struct burn_session *s) -{ - struct burn_drive *d = o->drive; - - /* only for Incremental writing */ - if (o->write_type != BURN_WRITE_TAO) - return 2; - -#ifdef Libburn_dvd_r_dl_multi_no_close_sessioN - if (d->current_profile == 0x15 && o->multi) - return 2; -#endif - - libdax_msgs_submit(libdax_messenger, o->drive->global_index,0x00020119, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, - "Closing session", 0, 0); - - d->busy = BURN_DRIVE_CLOSING_SESSION; - d->close_track_session(d, 1, 0); /* CLOSE SESSION, 010b */ - d->busy = BURN_DRIVE_WRITING; - return 1; -} - - -/* ts A61218 */ -int burn_dvd_write_session(struct burn_write_opts *o, - struct burn_session *s, int is_last_session) -{ - int i,ret; - struct burn_drive *d = o->drive; - - /* >>> open_session ? */ - - for (i = 0; i < s->tracks; i++) { - ret = burn_dvd_write_track(o, s, i, - is_last_session && i == (s->tracks - 1)); - if (ret <= 0) - break; - } - if (d->current_profile == 0x11 || d->current_profile == 0x14 || - d->current_profile == 0x15) { - /* DVD-R , DVD-RW Sequential, DVD-R/DL Sequential */ - ret = burn_disc_close_session_dvd_minus_r(o, s); - if (ret <= 0) - return 0; - } else if (d->current_profile == 0x12 || d->current_profile == 0x43) { - /* DVD-RAM , BD-RE */ - /* ??? any finalization needed ? */; - } else if (d->current_profile == 0x13) { - /* DVD-RW restricted overwrite */ - if (d->needs_close_session) { - ret = burn_disc_close_session_dvd_minus_rw(o, s); - if (ret <= 0) - return 0; - } - } else if (d->current_profile == 0x1a) { - /* DVD+RW */ - if (d->needs_close_session) { - ret = burn_disc_close_session_dvd_plus_rw(o, s); - if (ret <= 0) - return 0; - } - } else if (d->current_profile == 0x1b || d->current_profile == 0x2b) { - /* DVD+R , DVD+R/DL do each track as an own session */; - } - return 1; -} - - -/* ts A61218 : learned much from dvd+rw-tools-7.0/growisofs_mmc.cpp */ -int burn_disc_setup_dvd_plus_rw(struct burn_write_opts *o, - struct burn_disc *disc) -{ - struct burn_drive *d = o->drive; - int ret; - char msg[160]; - - if (d->bg_format_status==0 || d->bg_format_status==1) { - d->busy = BURN_DRIVE_FORMATTING; - /* start or re-start dvd_plus_rw formatting */ - ret = d->format_unit(d, (off_t) 0, 0); - if (ret <= 0) - return 0; - d->busy = BURN_DRIVE_WRITING; - d->needs_close_session = 1; - } - d->nwa = 0; - if (o->start_byte >= 0) { - d->nwa = o->start_byte / 2048; - - sprintf(msg, "Write start address is %d * 2048", d->nwa); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020127, - LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - } - - /* >>> perform OPC if needed */; - - /* >>> ? what else ? */; - - return 1; -} - - -/* ts A61228 : learned much from dvd+rw-tools-7.0/growisofs_mmc.cpp */ -int burn_disc_setup_dvd_minus_rw(struct burn_write_opts *o, - struct burn_disc *disc) -{ - struct burn_drive *d = o->drive; - char msg[160]; - int ret; - - d->nwa = 0; - if (o->start_byte >= 0) { - d->nwa = o->start_byte / 32768; /* align to 32 kB */ - - sprintf(msg, "Write start address is %d * 32768", d->nwa); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020127, - LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - - d->nwa *= 16; /* convert to 2048 block units */ - } - - - /* ??? mmc5r03c.pdf 7.5.2 : - "For DVD-RW media ... If a medium is in Restricted overwrite - mode, this mode page shall not be used." - - But growisofs composes a page 5 and sends it. - mmc5r03c.pdf 5.3.16 , table 127 specifies that mode page 5 - shall be supported with feature 0026h Restricted Overwrite. - 5.3.22 describes a feature 002Ch Rigid Restrictive Overwrite - which seems to apply to DVD-RW and does not mention page 5. - - 5.4.14 finally states that profile 0013h includes feature - 002Ch rather than 0026h. - - d->send_write_parameters(d, o); - */ - - d->busy = BURN_DRIVE_FORMATTING; - - /* "quick grow" to at least byte equivalent of d->nwa */ - ret = d->format_unit(d, (off_t) d->nwa * (off_t) 2048, - (d->nwa > 0) << 3); - if (ret <= 0) - return 0; - - d->busy = BURN_DRIVE_WRITING; - - /* >>> perform OPC if needed */; - - return 1; -} - - -/* ts A70129 : for DVD-R[W] Sequential Recoding */ -int burn_disc_setup_dvd_minus_r(struct burn_write_opts *o, - struct burn_disc *disc) -{ - struct burn_drive *d = o->drive; - - /* most setup is in burn_disc_setup_track_dvd_minus_r() */; - - d->nwa = 0; - return 1; -} - - -/* ts A70226 : for DVD+R , DVD+R/DL */ -int burn_disc_setup_dvd_plus_r(struct burn_write_opts *o, - struct burn_disc *disc) -{ - struct burn_drive *d = o->drive; - - /* most setup is in burn_disc_setup_track_dvd_plus_r() */; - - d->nwa = 0; - return 1; -} - - -/* ts A61218 - A70415 */ -int burn_dvd_write_sync(struct burn_write_opts *o, - struct burn_disc *disc) -{ - int i, ret, o_end; - off_t default_size = 0; - struct burn_drive *d = o->drive; - struct burn_track *t; - char msg[160]; - - d->needs_close_session = 0; - - /* buffer flush trigger for sector.c:get_sector() */ - o->obs = Libburn_dvd_obS; - - if (d->current_profile == 0x1a || d->current_profile == 0x12 || - d->current_profile == 0x43) { - /* DVD+RW , DVD-RAM , BD-RE */ - ret = 1; - if (d->current_profile == 0x1a) - ret = burn_disc_setup_dvd_plus_rw(o, disc); - if (ret <= 0) { - sprintf(msg, - "Write preparation setup failed for DVD+RW"); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020121, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - goto early_failure; - } - o->obs_pad = 0; /* no filling-up of track's last 32k buffer */ - if (d->current_profile == 0x43) /* BD-RE */ - o->obs = Libburn_bd_re_obS; - if (d->do_stream_recording) { - o->obs_pad = 1; - if (d->current_profile == 0x43) /* BD-RE */ - o->obs = Libburn_bd_re_streamed_obS; - } - - } else if (d->current_profile == 0x13) { - /* DVD-RW Restricted Overwrite */ - ret = burn_disc_setup_dvd_minus_rw(o, disc); - if (ret <= 0) { - sprintf(msg, - "Write preparation setup failed for DVD-RW"); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020121, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - goto early_failure; - } - - /* _Rigid_ Restricted Overwrite demands this */ - o->obs_pad = 1; /* fill-up track's last 32k buffer */ - - } else if (d->current_profile == 0x11 || d->current_profile == 0x14 || - d->current_profile == 0x15) { - /* DVD-R , DVD-RW Sequential , DVD-R/DL Sequential */ - t = disc->session[0]->track[0]; - o_end = ( burn_track_is_open_ended(t) && !o->fill_up_media ); - default_size = burn_track_get_default_size(t); - if (o->write_type == BURN_WRITE_SAO && o_end) { - sprintf(msg, "Activated track default size %.f", - (double) default_size); - libdax_msgs_submit(libdax_messenger, - d->global_index, 0x0002012e, - LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - burn_track_set_size(t, default_size); - } - ret = burn_disc_setup_dvd_minus_r(o, disc); - if (ret <= 0) { - sprintf(msg, - "Write preparation setup failed for DVD-R[W]"); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020121, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - goto early_failure; - } - /* ??? padding needed ??? cowardly doing it for now */ - o->obs_pad = 1; /* fill-up track's last 32k buffer */ - - } else if (d->current_profile == 0x1b || d->current_profile == 0x2b) { - /* DVD+R , DVD+R/DL */ - t = disc->session[0]->track[0]; - o_end = ( burn_track_is_open_ended(t) && !o->fill_up_media ); - default_size = burn_track_get_default_size(t); - if (o->write_type == BURN_WRITE_SAO && o_end) { - sprintf(msg, "Activated track default size %.f", - (double) default_size); - libdax_msgs_submit(libdax_messenger, - d->global_index, 0x0002012e, - LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - burn_track_set_size(t, default_size); - } - ret = burn_disc_setup_dvd_plus_r(o, disc); - if (ret <= 0) { - sprintf(msg, - "Write preparation setup failed for DVD+R"); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020121, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - goto early_failure; - } - /* ??? padding needed ??? cowardly doing it for now */ - o->obs_pad = 1; /* fill-up track's last 32k buffer */ - } - - sprintf(msg, "dvd/bd Profile= %2.2Xh , obs= %d , obs_pad= %d", - d->current_profile, o->obs, o->obs_pad); - libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, msg, 0, 0); - - for (i = 0; i < disc->sessions; i++) { - /* update progress */ - d->progress.session = i; - d->progress.tracks = disc->session[i]->tracks; - - ret = burn_dvd_write_session(o, disc->session[i], - i == (disc->sessions - 1)); - if (ret <= 0) - goto ex; - - /* XXX: currently signs an end of session */ - d->progress.sector = 0; - d->progress.start_sector = 0; - d->progress.sectors = 0; - } - ret = 1; -ex:; - - /* >>> eventual emergency finalization measures */ - - /* update media state records */ - burn_drive_mark_unready(d); - burn_drive_inquire_media(d); - - d->busy = BURN_DRIVE_IDLE; - return ret; -early_failure:; - return 0; -} - - -/* ts A70904 */ -int burn_stdio_open_write(struct burn_drive *d, off_t start_byte, - int sector_size, int flag) -{ - -/* <<< We need _LARGEFILE64_SOURCE defined by the build system. -*/ -#ifndef O_LARGEFILE -#define O_LARGEFILE 0 -#endif - - int fd = -1; - int mode = O_RDWR | O_CREAT | O_LARGEFILE; - char msg[160]; - - if (d->devname[0] == 0) /* null drives should not come here */ - return -1; - fd = burn_drive__fd_from_special_adr(d->devname); - if (fd >= 0) - fd = dup(fd); /* check validity and make closeable */ - else - fd = open(d->devname, mode, S_IRUSR | S_IWUSR); - if (fd == -1) { - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020005, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Failed to open device (a pseudo-drive)", errno, 0); - d->cancel = 1; - return -1; - } - if (start_byte < 0) - start_byte = 0; - if (d->drive_role == 2) - if (lseek(fd, start_byte, SEEK_SET)==-1) { - sprintf(msg, "Cannot address start byte %.f", - (double) start_byte); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020147, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - msg, errno, 0); - close(fd); - d->cancel = 1; - fd = -1; - } - d->nwa = start_byte / sector_size; - return fd; -} - - -/* ts A70904 */ -int burn_stdio_read_source(struct burn_source *source, char *buf, int bufsize, - struct burn_write_opts *o, int flag) -{ - int count= 0, todo; - - for(todo = bufsize; todo > 0; todo -= count) { - if(source->read!=NULL) - count = source->read(source, - (unsigned char *) (buf + (bufsize - todo)), todo); - else - count = source->read_xt(source, - (unsigned char *) (buf + (bufsize - todo)), todo); - if (count <= 0) - break; - } - return (bufsize - todo); -} - - -/* ts A70904 */ -int burn_stdio_write(int fd, char *buf, int count, struct burn_drive *d, - int flag) -{ - if (write(fd, buf, count) != count) { - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020148, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Cannot write desired amount of data", errno, 0); - d->cancel = 1; - return 0; - } - return count; -} - - -/* ts A70910 : to be used as burn_drive.write(), emulating mmc_write() */ -int burn_stdio_mmc_write(struct burn_drive *d, int start, struct buffer *buf) -{ - int ret; - off_t start_byte; - - if (d->cancel) - return BE_CANCELLED; - if (d->stdio_fd < 0) { - - /* >>> program error */; - - d->cancel = 1; - return BE_CANCELLED; - } - if (start != d->nwa) { - char msg[80]; - - start_byte = ((off_t) start) * - (off_t) (buf->bytes / buf->sectors); - if (lseek(d->stdio_fd, start_byte, SEEK_SET)==-1) { - sprintf(msg, "Cannot address start byte %.f", - (double) start_byte); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020147, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - msg, errno, 0); - d->cancel = 1; - return BE_CANCELLED; - } - d->nwa = start; - } - ret = burn_stdio_write(d->stdio_fd,(char *)buf->data, buf->bytes, d,0); - if (ret <= 0) - return BE_CANCELLED; - d->nwa += buf->sectors; - return 0; -} - - -/* ts A70910 : to be used as burn_drive.write(), - emulating mmc_write() with simulated writing. */ -int burn_stdio_mmc_dummy_write(struct burn_drive *d, int start, - struct buffer *buf) -{ - if (d->cancel) - return BE_CANCELLED; - d->nwa = start + buf->sectors; - return 0; -} - - -/* ts A70911 */ -/* Flush stdio system buffer to physical device. - @param flag bit0= do not report debug message (intermediate sync) -*/ -int burn_stdio_sync_cache(int fd, struct burn_drive *d, int flag) -{ - if (fd < 0) { - - /* >>> program error */; - - d->cancel = 1; - return 0; - } - d->needs_sync_cache = 0; - if (!(flag & 1)) - libdax_msgs_submit(libdax_messenger, -1, 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - "syncing cache (stdio fsync)", 0, 0); - if (fsync(fd) != 0) { - if (errno == EINVAL) /* E.g. /dev/null cannot fsync */ - return 1; - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020148, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Cannot write desired amount of data", errno, 0); - d->cancel = 1; - return 0; - } - return 1; -} - - -/* ts A70911 : to be used as burn_drive.sync_cache(), - emulating mmc_sync_cache() */ -void burn_stdio_mmc_sync_cache(struct burn_drive *d) -{ - burn_stdio_sync_cache(d->stdio_fd, d, 0); -} - - -/* ts A70912 */ -/* Enforces eventual nominal write speed. - @param flag bit0= initialize *prev_time */ -int burn_stdio_slowdown(struct burn_drive *d, struct timeval *prev_time, - int amount, int flag) -{ - struct timeval tnow; - struct timezone dummy_tz; - double to_wait; - - if (flag & 1) { - gettimeofday(prev_time, &dummy_tz); - return 1; - } - if(d->nominal_write_speed <= 0) - return 2; - gettimeofday(&tnow, &dummy_tz); - to_wait = ( ((double) amount) / (double) d->nominal_write_speed ) - - (double) ( tnow.tv_sec - prev_time->tv_sec ) - - (double) ( tnow.tv_usec - prev_time->tv_usec ) / 1.0e6 - - 0.001; /* best would be 1 / kernel granularity HZ */ - if (to_wait >= 0.0001) { - usleep((int) (to_wait * 1000000.0)); - } - gettimeofday(prev_time, &dummy_tz); - return 1; -} - - -/* ts A70904 */ -int burn_stdio_write_track(struct burn_write_opts *o, struct burn_session *s, - int tnum, int flag) -{ - int open_ended, bufsize, ret, sectors, fd; - struct burn_track *t = s->track[tnum]; - struct burn_drive *d = o->drive; - char buf[16*2048]; - int i, prev_sync_sector = 0; - struct buffer *out = d->buffer; - struct timeval prev_time; - - bufsize = sizeof(buf); - fd = d->stdio_fd; - - sectors = burn_track_get_sectors(t); - burn_disc_init_track_status(o, s, tnum, sectors); - open_ended = burn_track_is_open_ended(t); - - /* attach stdio emulators for mmc_*() functions */ - if (o->simulate) - d->write = burn_stdio_mmc_dummy_write; - else - d->write = burn_stdio_mmc_write; - d->sync_cache = burn_stdio_mmc_sync_cache; - - burn_stdio_slowdown(d, &prev_time, 0, 1); /* initialize */ - for (i = 0; open_ended || i < sectors; i++) { - /* transact a (CD sized) sector */ - if (!sector_data(o, t, 0)) - {ret= 0; goto ex;} - if (open_ended) { - d->progress.sectors = sectors = d->progress.sector; - if (burn_track_is_data_done(t)) - break; - } - d->progress.sector++; - /* Flush to disk after each full MB */ - if (d->progress.sector - prev_sync_sector >= 512) { - prev_sync_sector = d->progress.sector; - if (!o->simulate) - burn_stdio_sync_cache(d->stdio_fd, d, 1); - burn_stdio_slowdown(d, &prev_time, 512 * 2, 0); - } - } - - /* Pad up buffer to next full o->obs (usually 32 kB) */ - if (o->obs_pad && out->bytes > 0 && out->bytes < o->obs) { - memset(out->data + out->bytes, 0, o->obs - out->bytes); - out->sectors += (o->obs - out->bytes) / 2048; - out->bytes = o->obs; - } - ret = burn_write_flush(o, t); - ret= 1; -ex:; - if (d->cancel) - burn_source_cancel(t->source); - return ret; -} - - -/* ts A70904 */ -int burn_stdio_write_sync(struct burn_write_opts *o, - struct burn_disc *disc) -{ - int ret; - struct burn_drive *d = o->drive; - - d->needs_close_session = 0; - o->obs_pad = 0; /* no filling-up of track's last 32k buffer */ - o->obs = 32*1024; /* buffer size */ - - if (disc->sessions != 1) - {ret= 0 ; goto ex;} - if (disc->session[0]->tracks != 1) - {ret= 0 ; goto ex;} - - /* update progress */ - d->progress.session = 0; - d->progress.tracks = 1; - - /* >>> adjust sector size (2048) to eventual audio or even raw */ - /* open target file */ - if (d->stdio_fd >= 0) - close(d->stdio_fd); - d->stdio_fd = burn_stdio_open_write(d, o->start_byte, 2048, 0); - if (d->stdio_fd == -1) - {ret = 0; goto ex;} - - ret = burn_stdio_write_track(o, disc->session[0], 0, 0); - if (ret <= 0) - goto ex; - - /* XXX: currently signs an end of session */ - d->progress.sector = 0; - d->progress.start_sector = 0; - d->progress.sectors = 0; - ret = 1; -ex:; - if (d->stdio_fd >= 0) - close(d->stdio_fd); - d->stdio_fd = -1; - - /* update media state records */ - burn_drive_mark_unready(d); - - d->busy = BURN_DRIVE_IDLE; - return ret; -} - - -void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc) -{ - struct cue_sheet *sheet; - struct burn_drive *d = o->drive; - struct buffer buf; - struct burn_track *lt, *t; - int first = 1, i, ret, lba, nwa = 0; - off_t default_size; - char msg[80]; - -/* ts A60924 : libburn/message.c gets obsoleted - burn_message_clear_queue(); -*/ - - /* ts A61224 */ - burn_disc_init_write_status(o, disc); /* must be done very early */ - - /* ts A80412 */ - d->do_stream_recording = o->do_stream_recording; - - d->buffer = &buf; - memset(d->buffer, 0, sizeof(struct buffer)); - d->rlba = -150; - d->toc_temp = 9; - - /* ts A70904 */ - if (d->drive_role != 1) { - ret = burn_stdio_write_sync(o, disc); - if (ret <= 0) - goto fail_wo_sync; - goto ex; - } - /* ts A61218 */ - if (! d->current_is_cd_profile) { - ret = burn_dvd_write_sync(o, disc); - if (ret <= 0) - goto fail_wo_sync; - goto ex; - } - - /* ts A70521 : Linux 2.4 USB audio fails with 64 kiB */ - /* ts A80414 : might need 64 kiB for BD-RE streaming */ - /* buffer flush trigger for sector.c:get_sector() */ - o->obs = Libburn_cd_obS; - - sprintf(msg, "cd Profile= %2.2Xh , obs= %d , obs_pad= %d", - d->current_profile, o->obs, o->obs_pad); - libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, msg, 0, 0); - - /* ts A70218 */ - if (o->write_type == BURN_WRITE_SAO) { - for (i = 0 ; i < disc->session[0]->tracks; i++) { - t = disc->session[0]->track[i]; - if (burn_track_is_open_ended(t)) { - default_size = burn_track_get_default_size(t); - sprintf(msg, - "Activated track default size %.f", - (double) default_size); - libdax_msgs_submit(libdax_messenger, - d->global_index, 0x0002012e, - LIBDAX_MSGS_SEV_NOTE, - LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0); - burn_track_set_size(t, default_size); - } - } - } - - burn_print(1, "sync write of %d CD sessions\n", disc->sessions); - -/* Apparently some drives require this command to be sent, and a few drives -return crap. so we send the command, then ignore the result. -*/ - /* ts A61107 : moved up send_write_parameters because LG GSA-4082B - seems to dislike get_nwa() in advance */ - d->alba = d->start_lba; /* ts A61114: this looks senseless */ - d->nwa = d->alba; - if (o->write_type == BURN_WRITE_TAO) { - nwa = 0; /* get_nwa() will be called in burn_track() */ - } else { - - d->send_write_parameters(d, o); - - ret = d->get_nwa(d, -1, &lba, &nwa); - sprintf(msg, - "SAO|RAW: Inquired nwa: %d , ret= %d , cap=%.f\n", - nwa, ret, (double) d->media_capacity_remaining); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - msg,0, 0); - - /* >>> ts A70212 : CD-DAO/SAO : eventually expand size of last track to maximum */; - - } - - for (i = 0; i < disc->sessions; i++) { - /* update progress */ - d->progress.session = i; - d->progress.tracks = disc->session[i]->tracks; - - /* ts A61114: added parameter nwa */ - sheet = burn_create_toc_entries(o, disc->session[i], nwa); - - /* ts A61009 */ - if (sheet == NULL) - goto fail; - -/* print_cue(sheet);*/ - if (o->write_type == BURN_WRITE_SAO) - d->send_cue_sheet(d, sheet); - free(sheet); - - if (o->write_type == BURN_WRITE_RAW) { - if (!burn_write_leadin(o, disc->session[i], first)) - goto fail; - } else { - if (first) { - - /* ts A61030 : 0 made the burner take data. */ - /* ts A61103 : Meanwhile d->nwa is updated in - burn_write_track() */ - if(o->write_type == BURN_WRITE_TAO) { - d->nwa= d->alba = 0; - } else { - -#ifdef Libburn_sao_can_appenD - /* ts A61114: address for d->write() */ - if (d->status == BURN_DISC_APPENDABLE - && o->write_type == BURN_WRITE_SAO) { - d->nwa = d->alba = nwa-150; - - sprintf(msg, - "SAO appendable d->nwa= %d\n", d->nwa); - libdax_msgs_submit( - libdax_messenger, d->global_index, 0x000002, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, - msg, 0, 0); - - } else { - d->nwa = -150; - d->alba = -150; - } -#else - d->nwa = -150; - d->alba = -150; -#endif /* ! Libburn_sao_can_appenD */ - - - } - - } else { - d->nwa += 4500; - d->alba += 4500; - } - } - if (!burn_write_session(o, disc->session[i])) - goto fail; - - lt = disc->session[i]->track[disc->session[i]->tracks - 1]; - if (o->write_type == BURN_WRITE_RAW) { - if (!burn_write_leadout(o, first, lt->entry->control, - lt->mode)) - goto fail; - } else { - - /* ts A61030 */ - if (o->write_type != BURN_WRITE_TAO) - - if (!burn_write_flush(o, NULL)) - goto fail; - - d->nwa += first ? 6750 : 2250; - d->alba += first ? 6750 : 2250; - } - if (first) - first = 0; - - /* XXX: currently signs an end of session */ - d->progress.sector = 0; - d->progress.start_sector = 0; - d->progress.sectors = 0; - } - - /* ts A61030: extended skipping of flush to TAO: session is closed */ - if (o->write_type != BURN_WRITE_SAO && o->write_type != BURN_WRITE_TAO) - if (!burn_write_flush(o, NULL)) - goto fail; - - sleep(1); - - /* ts A61125 : update media state records */ - burn_drive_mark_unready(d); - burn_drive_inquire_media(d); - - burn_print(1, "done\n"); - d->busy = BURN_DRIVE_IDLE; - - /* ts A61012 : This return was traditionally missing. I suspect this - to have caused Cdrskin_eject() failures */ - goto ex; - -fail: - d->sync_cache(d); -fail_wo_sync:; - usleep(500001); /* ts A61222: to avoid a warning from remove_worker()*/ - burn_print(1, "done - failed\n"); - libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002010b, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "Burn run failed", 0, 0); - d->cancel = 1; - d->busy = BURN_DRIVE_IDLE; -ex:; - d->do_stream_recording = 0; - return; -} - -/* ts A70811 : API function */ -int burn_random_access_write(struct burn_drive *d, off_t byte_address, - char *data, off_t data_count, int flag) -{ - int alignment = 0, start, upto, chunksize, err, fd = -1, ret; - char msg[81], *rpt; - struct buffer buf; - - 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 write", 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; - } - - if(d->drive_role == 2) - alignment = 2 * 1024; - if (d->current_profile == 0x12) /* DVD-RAM */ - alignment = 2 * 1024; - if (d->current_profile == 0x13) /* DVD-RW restricted overwrite */ - alignment = 32 * 1024; - if (d->current_profile == 0x1a) /* DVD+RW */ - alignment = 2 * 1024; - if (d->current_profile == 0x43) /* BD-RE */ - alignment = 2 * 1024; - if (alignment == 0) { - sprintf(msg, "Write start address not supported"); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020125, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Write start address not supported", 0, 0); - return 0; - } - if ((byte_address % alignment) != 0) { - sprintf(msg, - "Write start address not properly aligned (%d bytes)", - alignment); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020126, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - return 0; - } - if ((data_count % alignment) != 0) { - sprintf(msg, - "Write data count not properly aligned (%ld bytes)", - (long) alignment); - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020141, - 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, 0x00020140, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "Drive is busy on attempt to write random access",0,0); - return 0; - } - if(d->drive_role != 1) { - fd = burn_stdio_open_write(d, byte_address, 2048, 0); - if (fd == -1) - return 0; - } - d->busy = BURN_DRIVE_WRITING_SYNC; - d->buffer = &buf; - - start = byte_address / 2048; - upto = start + data_count / 2048; - rpt = data; - for (; start < upto; start += 16) { - chunksize = upto - start; - if (chunksize > 16) - chunksize = 16; - d->buffer->bytes = chunksize * 2048; - memcpy(d->buffer->data, rpt, d->buffer->bytes); - rpt += d->buffer->bytes; - d->buffer->sectors = chunksize; - d->nwa = start; - if(d->drive_role == 1) { - err = d->write(d, d->nwa, d->buffer); - } else { - ret = burn_stdio_write(fd, (char *) d->buffer->data, - d->buffer->bytes, d, 0); - err = 0; - if (ret <= 0) - err = BE_CANCELLED; - } - if (err == BE_CANCELLED) { - d->busy = BURN_DRIVE_IDLE; - if(fd >= 0) - close(fd); - return (-(start * 2048 - byte_address)); - } - } - - if(d->drive_role == 1) - d->needs_sync_cache = 1; - if(flag & 1) { - if(d->drive_role == 1) - d->sync_cache(d); - else - burn_stdio_sync_cache(fd, d, 0); - d->needs_sync_cache = 0; - } - - if(fd >= 0) - close(fd); - d->buffer = NULL; - d->busy = BURN_DRIVE_IDLE; - return 1; -} - diff --git a/libburn/write.h b/libburn/write.h deleted file mode 100644 index d5b1b32..0000000 --- a/libburn/write.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#ifndef BURN__WRITE_H -#define BURN__WRITE_H - -struct cue_sheet; -struct burn_session; -struct burn_write_opts; -struct burn_disc; - -struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o, - struct burn_session *session, - int nwa); -int burn_sector_length(int trackmode); -int burn_subcode_length(int trackmode); - -/* ts A61009 */ -int burn_disc_write_is_ok(struct burn_write_opts *o, struct burn_disc *disc, - int flag); - -void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc); -int burn_write_leadin(struct burn_write_opts *o, - struct burn_session *s, int first); -int burn_write_leadout(struct burn_write_opts *o, - int first, unsigned char control, int mode); -int burn_write_session(struct burn_write_opts *o, struct burn_session *s); -int burn_write_track(struct burn_write_opts *o, struct burn_session *s, - int tnum); -int burn_write_flush(struct burn_write_opts *o, struct burn_track *track); - -/* ts A61030 : necessary for TAO */ -int burn_write_close_track(struct burn_write_opts *o, struct burn_session *s, - int tnum); -int burn_write_close_session(struct burn_write_opts *o,struct burn_session *s); - - - -/* mmc5r03c.pdf 6.3.3.3.3: DVD-R DL: Close Function 010b: Close Session - "When the recording mode is Incremental Recording, - the disc is single session." - Enable this macro to get away from growisofs which uses Close Session - but also states "// DVD-R DL Seq has no notion of multi-session". - - #define Libburn_dvd_r_dl_multi_no_close_sessioN 1 - -*/ - -#endif /* BURN__WRITE_H */ diff --git a/libcevap/cgen.c b/libcevap/cgen.c deleted file mode 100644 index 81718f7..0000000 --- a/libcevap/cgen.c +++ /dev/null @@ -1,1503 +0,0 @@ - -#include <sys/time.h> -#include <sys/types.h> -#include <unistd.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <sys/stat.h> - - -#include "smem.h" - -char *Sfile_fgets(); -int Sregex_string(); -int Sregex_trimline(); - - -#include "ctyp.h" - -#include "cgen.h" - - - -/* ----------------------------- CgeN ------------------------- */ - -int Cgen_new(cgen,flag) -struct CgeN **cgen; -int flag; -{ - int ret; - struct CgeN *c; - - *cgen= c= TSOB_FELD(struct CgeN,1); - if(c==NULL) { - fprintf(stderr,"+++ Cannot create cgen object : %s\n",strerror(errno)); - return(-1); - } - c->classname= NULL; - c->structname= NULL; - c->functname= NULL; - c->is_managed_list= 0; - c->is_bossless_list= 0; - c->gen_for_stic= 1; - c->make_ansi= 0; - c->make_lowercase= 0; - c->global_include_file[0]= 0; - c->global_include_fp= NULL; - c->elements= NULL; - c->last_element= NULL; - c->may_overwrite= 0; - c->fp= NULL; - c->filename[0]= 0; - c->ptt_fp= NULL; - c->ptt_filename[0]= 0; - c->msg[0]= 0; - return(1); -} - - -int Cgen_destroy(cgen,flag) -struct CgeN **cgen; -int flag; -{ - struct CgeN *c; - struct CtyP *ct,*next_ct; - - c= *cgen; - if(c==NULL) - return(0); - - if(c->fp!=NULL) - fclose(c->fp); - if(c->ptt_fp!=NULL) - fclose(c->ptt_fp); - Sregex_string(&(c->classname),NULL,0); - Sregex_string(&(c->structname),NULL,0); - Sregex_string(&(c->functname),NULL,0); - for(ct= c->elements; ct!=NULL; ct= next_ct) { - next_ct= ct->next; - Ctyp_destroy(&ct,0); - } - - free((char *) c); - *cgen= NULL; - return(1); -} - - -int Cgen_make_names(cgen,flag) -struct CgeN *cgen; -int flag; -{ - int l; - - if(Sregex_string(&(cgen->structname),cgen->classname,0)<=0) - return(-1); - if(Sregex_string(&(cgen->functname),cgen->classname,0)<=0) - return(-1); - if(!cgen->make_lowercase) { - cgen->structname[0]= toupper(cgen->structname[0]); - l= strlen(cgen->structname); - cgen->structname[l-1]= toupper(cgen->structname[l-1]); - cgen->functname[0]= toupper(cgen->functname[0]); - } - return(1); -} - - -int Cgen_read_fp(cgen,fp,flag) -struct CgeN *cgen; -FILE *fp; -int flag; -/* - bit0= return 0 if eof at classname -*/ -{ - char line[4096],*cpt,*bpt; - int ret; - - line[0]= 0; - while(1) { - printf("[-list] classname ?\n"); - if(Sfile_fgets(line,sizeof(line)-1,fp)==NULL) { - if(!(flag&1)) - return(2); -no_name:; - sprintf(cgen->msg,"No classname given."); - return(0); - } - printf("%s\n",line); - if(strcmp(line,"@@@")==0) - return(2); - - if(line[0]==0 || line[0]=='#') { - - /* >>> record class comments */; - - } else - break; - } - cpt= line; - while(cpt[0]=='-') { - /* look for management specifiers: - -l* listable by prev-next chain - */ - if(cpt[1]=='l' || cpt[1]=='L') { - cgen->is_managed_list= 1; - } else if(cpt[1]=='b' || cpt[1]=='B') { - cgen->is_bossless_list= 1; - } - while(*cpt!=0 && !isspace(*cpt)) cpt++; - while(*cpt!=0 && isspace(*cpt)) cpt++; - if(*cpt==0) - goto no_name; - } - if(Sregex_string(&(cgen->classname),cpt,0)<=0) - return(-1); - ret= Cgen_make_names(cgen,0); - if(ret<=0) - return(ret); - - while(1) { - ret= Ctyp_read_fp(&(cgen->last_element),fp,cgen->msg, - !!cgen->make_lowercase); - if(ret<=0) - return(ret); - if(ret==2) - break; - if(cgen->elements==NULL) - cgen->elements= cgen->last_element; - } - if(cgen->is_managed_list) { - sprintf(line,"-c struct %s *prev",cgen->structname); - ret= Ctyp_new_from_line(&(cgen->last_element),cgen->last_element, - line,cgen->msg,0); - if(ret<=0) - return(ret); - if(cgen->elements==NULL) - cgen->elements= cgen->last_element; - sprintf(line,"-c struct %s *next",cgen->structname); - ret= Ctyp_new_from_line(&(cgen->last_element),cgen->last_element, - line,cgen->msg,0); - if(ret<=0) - return(ret); - } - return(1); -} - - -int Cgen_open_wfile(cgen,flag) -struct CgeN *cgen; -int flag; -/* - bit0-3: modes - 0= open cgen->fp - 1= open cgen->ptt_fp - 2= open cgen->global_include_fp -*/ -{ - struct stat stbuf; - int ret, mode; - char *name, fmode[4]; - FILE *fp; - - mode= flag&15; - strcpy(fmode,"w"); - if(mode==0) { - name= cgen->filename; - fp= cgen->fp; - cgen->fp= NULL; - } else if(mode==1) { - name= cgen->ptt_filename; - fp= cgen->ptt_fp; - cgen->ptt_fp= NULL; - } else if(mode==2) { - strcpy(fmode,"a"); - name= cgen->global_include_file; - fp= cgen->global_include_fp; - cgen->global_include_fp= NULL; - } else { - fprintf(stderr,"+++ Cgen_open_wfile : program error : unknown mode %d\n", - mode); - ret= -1; goto ex; - } - if(fmode[0]=='w' && stat(name,&stbuf)!=-1 && !cgen->may_overwrite) { - sprintf(cgen->msg,"File '%s' already existing.",name); - ret= 0; goto ex; - } - if(fp!=NULL) - {fclose(fp); fp= NULL;} - fp= fopen(name,fmode); - if(fp==NULL) { - sprintf(cgen->msg,"Cannot open file '%s' in %s-mode. %s", - name,fmode,strerror(errno)); - ret= 0; goto ex; - } - ret= 1; -ex:; - if(mode==0) - cgen->fp= fp; - else if(mode==1) - cgen->ptt_fp= fp; - else if(mode==2) - cgen->global_include_fp= fp; - return(ret); -} - - -int Cgen_write_datestr(cgen,flag) -struct CgeN *cgen; -int flag; -/* - bit0= operate on ptt (= ANSI prototype) file rather than on internal header -*/ -{ - time_t t0; - char timetext[81]; - FILE *fp; - - if(flag&1) - fp= cgen->ptt_fp; - else - fp= cgen->fp; - t0= time(0); - strftime(timetext,sizeof(timetext),"%a, %d %b %Y %H:%M:%S GMT", - gmtime(&t0)); - fprintf(fp,"/* ( derived from stub generated by CgeN on %s ) */\n", - timetext); - return(1); -} - - -int Cgen_write_h(cgen,flag) -struct CgeN *cgen; -int flag; -{ - int ret,i,pointer_level; - FILE *fp= NULL; - struct CtyP *ct; - char pvt[16],macro_name[4096],*cpt; - - if(cgen->make_ansi) { - sprintf(cgen->filename,"%s_private.h",cgen->classname); - strcpy(pvt,"_private"); - } else { - sprintf(cgen->filename,"%s.h",cgen->classname); - strcpy(pvt,""); - } - - ret= Cgen_open_wfile(cgen,0); - if(ret<=0) - goto ex; - sprintf(macro_name,"%s%s_includeD",cgen->functname,pvt); - macro_name[0]= toupper(macro_name[0]); - fp= cgen->fp; - - /* >>> print class comments */; - - fprintf(fp,"\n"); - fprintf(fp,"#ifndef %s\n",macro_name); - fprintf(fp,"#define %s\n",macro_name); - fprintf(fp,"\n"); - if(strlen(cgen->global_include_file)!=0) { - fprintf(fp,"#include \"%s\"\n",cgen->global_include_file); - fprintf(fp,"\n\n"); - } - if(cgen->make_ansi) - fprintf(fp,"/* For function prototypes see file %s.h */\n",cgen->classname); - fprintf(fp,"\n\n"); - fprintf(fp,"struct %s {\n",cgen->structname); - fprintf(fp,"\n"); - ct= cgen->elements; - for(ct= cgen->elements;ct!=NULL;ct= ct->next) { - - if(ct->is_comment) { - if(ct->name[0]==0) { - fprintf(fp,"\n"); - continue; - } - fprintf(fp," /* "); - for(cpt= ct->name; *cpt!=0; cpt++) { - fprintf(fp,"%c",*cpt); - if(cpt[0]=='*' && cpt[1]=='/') - fprintf(fp," "); - } - fprintf(fp," */\n"); - continue; - } - - if(ct->is_volatile) - fprintf(fp," volatile"); - if(Ctyp_is_struct(ct,0)) - fprintf(fp," struct"); - else if(ct->is_unsigned) - fprintf(fp," unsigned"); - fprintf(fp," %s ",ct->dtype); - pointer_level= Ctyp_get_pointer_level(ct,0); - for(i=0;i<pointer_level;i++) - fprintf(fp,"*"); - fprintf(fp,"%s",ct->name); - if(ct->array_size>0) - fprintf(fp,"[%lu]",ct->array_size); - fprintf(fp,";\n"); - } - fprintf(fp,"\n"); - fprintf(fp,"};\n"); - fprintf(fp,"\n"); - fprintf(fp,"\n"); - fprintf(fp,"#endif /* %s */\n",macro_name); - fprintf(fp,"\n"); - Cgen_write_datestr(cgen,0); - - /* Eventually write start of ANSI prototype include file */ - if(!cgen->make_ansi) - goto after_ansi_h; - sprintf(cgen->ptt_filename,"%s.h",cgen->classname); - ret= Cgen_open_wfile(cgen,1); - if(ret<=0) - goto ex; - sprintf(macro_name,"%s_includeD",cgen->functname); - macro_name[0]= toupper(macro_name[0]); - fp= cgen->ptt_fp; - - /* >>> print class comments */; - - fprintf(fp,"\n"); - fprintf(fp,"#ifndef %s\n",macro_name); - fprintf(fp,"#define %s\n",macro_name); - fprintf(fp,"\n\n"); - if(strlen(cgen->global_include_file)!=0) { - fprintf(fp,"#include \"%s\"\n",cgen->global_include_file); - } else { - fprintf(fp,"struct %s;\n",cgen->structname); - } - fprintf(fp,"\n\n"); - fprintf(fp,"/* For inner details see file %s_private.h */\n",cgen->classname); - fprintf(fp,"\n\n"); - -after_ansi_h:; - if(strlen(cgen->global_include_file)==0) - goto after_global_include; - ret= Cgen_open_wfile(cgen,2); - if(ret<=0) - goto ex; - fprintf(cgen->global_include_fp,"struct %s;\n",cgen->structname); - -after_global_include:; - ret= 1; -ex:; - if(cgen->fp!=NULL) - {fclose(cgen->fp); cgen->fp= NULL;} - /* ( note: cgen->ptt_fp stays open ) */ - if(cgen->global_include_fp!=NULL) - {fclose(cgen->global_include_fp); cgen->global_include_fp= NULL;} - return(ret); -} - - -int Cgen_write_to_ptt(cgen,ptt,flag) -struct CgeN *cgen; -char *ptt; -int flag; -{ - if(cgen->ptt_fp==NULL) - return(-1); - fprintf(cgen->ptt_fp,"%s;\n",ptt); - return(1); -} - - -int Cgen_finish_public_h(cgen,flag) -struct CgeN *cgen; -int flag; -{ - char macro_name[4096]; - - if(cgen->ptt_fp==NULL) - return(-1); - fprintf(cgen->ptt_fp,"\n"); - fprintf(cgen->ptt_fp,"\n"); - sprintf(macro_name,"%s_includeD",cgen->functname); - macro_name[0]= toupper(macro_name[0]); - fprintf(cgen->ptt_fp,"#endif /* %s */\n",macro_name); - fprintf(cgen->ptt_fp,"\n"); - Cgen_write_datestr(cgen,1); - if(cgen->ptt_fp!=NULL) - {fclose(cgen->ptt_fp); cgen->ptt_fp= NULL;} - return(1); -} - - -int Cgen_write_c_head(cgen,flag) -struct CgeN *cgen; -int flag; -{ - int ret,is_pointer,is_struct,array_size; - FILE *fp= NULL; - struct CtyP *ct,*hct; - char *dtype= NULL,*name= NULL; - - fp= cgen->fp; - fprintf(fp,"\n"); - fprintf(fp,"/*\n"); - fprintf(fp," cc -g -c %s.c\n",cgen->classname); - fprintf(fp,"*/\n"); - Cgen_write_datestr(cgen,0); - fprintf(fp,"\n"); - fprintf(fp,"#include <sys/types.h>\n"); - fprintf(fp,"#include <stdlib.h>\n"); - fprintf(fp,"#include <stdio.h>\n"); - fprintf(fp,"#include <string.h>\n"); - fprintf(fp,"#include <errno.h>\n"); - fprintf(fp,"\n"); - fprintf(fp,"#include \"%s.h\"\n",cgen->classname); - if(cgen->make_ansi) { - fprintf(fp,"#include \"%s_private.h\"\n",cgen->classname); - } - fprintf(fp,"\n"); - for(ct= cgen->elements; ct!=NULL; ct= ct->next) { - if(ct->is_comment) - continue; - Ctyp_get_dtype(ct,&dtype,0); - Ctyp_get_type_mod(ct,&is_pointer,&is_struct,&array_size,0); -/* - fprintf(stderr,"DEBUG: %s %s\n",(is_struct?"struct ":""),dtype); -*/ - /* already included ? */ - if(strcmp(dtype,cgen->structname)==0) - continue; - for(hct= cgen->elements; hct!=NULL && hct!=ct; hct= hct->next) { - if(hct->is_comment) - continue; - if(hct->dtype!=NULL) - if(strcmp(hct->dtype,dtype)==0) - break; - } - if(hct!=ct && hct!=NULL) - continue; - - if(is_struct && (isupper(dtype[0]) && isupper(dtype[strlen(dtype)-1]))) { - dtype[0]= tolower(dtype[0]); - dtype[strlen(dtype)-1]= tolower(dtype[strlen(dtype)-1]); - fprintf(fp,"#include \"%s.h\"\n",dtype); - } - } - fprintf(fp,"\n"); - if(cgen->gen_for_stic==1) { - fprintf(fp,"#include \"../s_tools/smem.h\"\n"); - fprintf(fp,"#include \"../s_tools/sfile.h\"\n"); - fprintf(fp,"#include \"../s_tools/sregex.h\"\n"); - fprintf(fp,"\n"); - } else if(cgen->gen_for_stic==2) { - fprintf(fp,"#include \"smem.h\"\n"); - fprintf(fp,"\n"); - } - fprintf(fp,"\n"); - fprintf(fp,"/* -------------------------- %s ----------------------- */\n", - cgen->structname); - fprintf(fp,"\n"); - - if(dtype!=NULL) - Sregex_string(&dtype,NULL,0); - if(name!=NULL) - Sregex_string(&name,NULL,0); - return(1); -} - - -int Cgen_write_c_new(cgen,flag) -struct CgeN *cgen; -int flag; -{ - int ret,pointer_level,management,boss_parm= 0; - unsigned long array_size; - FILE *fp= NULL; - struct CtyP *ct; - char ptt[4096]; - - fp= cgen->fp; - - if(!cgen->is_bossless_list) { - if(cgen->elements!=NULL) - if(strcmp(cgen->elements->name,"boss")==0 && cgen->elements->is_struct && - cgen->elements->is_pointer==1 && cgen->elements->no_initializer==0) - boss_parm= 1; - if(cgen->is_managed_list && boss_parm==0) - fprintf(stderr, - "+++ Warning: -l %s without -v struct ... *boss as first attribute\n", - cgen->classname); - } - fprintf(fp,"\n"); - if(cgen->make_ansi) { - sprintf(ptt,"int %s_new(struct %s **objpt, ", - cgen->functname,cgen->structname); - if(boss_parm) - sprintf(ptt+strlen(ptt),"struct %s *boss, ",cgen->elements->dtype); - sprintf(ptt+strlen(ptt),"int flag)"); - fprintf(fp,"%s\n",ptt); - ret= Cgen_write_to_ptt(cgen, ptt, 0); - if(ret<=0) - return(ret); - } else { - fprintf(fp,"int %s_new(objpt,\n",cgen->functname); - if(boss_parm) - fprintf(fp,"boss,"); - fprintf(fp,"flag)\n"); - fprintf(fp,"struct %s **objpt;\n",cgen->structname); - if(boss_parm) - fprintf(fp,"struct %s *boss;",cgen->elements->dtype); - fprintf(fp,"int flag;\n"); - } - fprintf(fp,"{\n"); - fprintf(fp," struct %s *o;\n",cgen->structname); - - /* Is an array index i needed ? */ - for(ct= cgen->elements; ct!=NULL; ct= ct->next) { - if(ct->is_comment || ct->no_initializer) - continue; - if(ct->array_size>0) - if(strcmp(ct->dtype,"char")!=0) { - fprintf(fp," int i;\n"); - break; - } - } - - fprintf(fp,"\n"); - if(cgen->gen_for_stic) - fprintf(fp," *objpt= o= TSOB_FELD(struct %s,1);\n",cgen->structname); - else - fprintf(fp," *objpt= o= (struct %s *) malloc(sizeof(struct %s));\n", - cgen->structname, cgen->structname); - fprintf(fp," if(o==NULL)\n"); - fprintf(fp," return(-1);\n"); - fprintf(fp,"\n"); - for(ct= cgen->elements; ct!=NULL; ct= ct->next) { - if(ct->is_comment || ct->no_initializer) - continue; - array_size= Ctyp_get_array_size(ct,0); - pointer_level= Ctyp_get_pointer_level(ct,0); - if(ct==cgen->elements && boss_parm) { - fprintf(fp," o->boss= boss;\n"); - } else if(array_size>0) { - if(strcmp(ct->dtype,"char")==0) { - fprintf(fp," o->%s[0]= 0;\n;",ct->name); - } else if(pointer_level>0) { - fprintf(fp," for(i=0;i<%lu;i++)\n",array_size); - fprintf(fp," o->%s[i]= NULL;\n",ct->name); - } else { - fprintf(fp," for(i=0;i<%lu;i++)\n",array_size); - fprintf(fp," o->%s[i]= 0;\n",ct->name); - } - } else if(pointer_level>0) { - fprintf(fp," o->%s= NULL;\n",ct->name); - } else - fprintf(fp," o->%s= 0;\n",ct->name); - } - fprintf(fp,"\n"); - fprintf(fp," return(1);\n"); - fprintf(fp,"/*\n"); - fprintf(fp,"failed:;\n"); - fprintf(fp," %s_destroy(objpt,0);\n",cgen->functname); - fprintf(fp," return(-1);\n"); - fprintf(fp,"*/\n"); - fprintf(fp,"}\n"); - fprintf(fp,"\n"); - for(ct= cgen->elements; ct!=NULL; ct= ct->next) { - if(ct->is_comment) - continue; - management= Ctyp_get_management(ct,0); - if(management==4) { - if(ct->next==NULL) { -no_last_pt:; - sprintf(cgen->msg, - "Lonely -l found. A -v of same type must follow.\nName is : %s", - ct->name); - return(0); - } - if(strcmp(ct->next->dtype,ct->dtype)!=0 - || ct->next->is_pointer!=ct->is_pointer) - goto no_last_pt; - ct->next->with_getter= ct->next->with_setter= 0; - ret= Cgen_write_c_new_type(cgen,ct,ct->next,0); - if(ret<=0) - return(ret); - } - } - return(1); -} - - -int Cgen_write_c_new_type(cgen,ct_first,ct_last,flag) -struct CgeN *cgen; -struct CtyP *ct_first,*ct_last; -int flag; -{ - int ret,l,management,pointer_level,i; - FILE *fp= NULL; - char funct[4096],classname[4096],*npt,ptt[4096]; - - strcpy(funct,ct_first->dtype); - strcpy(classname,funct); - l= strlen(funct); - if(l>0) { - if(cgen->make_lowercase) - funct[0]= tolower(funct[0]); - else - funct[0]= toupper(funct[0]); - funct[l-1]= tolower(funct[l-1]); - classname[0]= tolower(funct[0]); - classname[l-1]= funct[l-1]; - } - fp= cgen->fp; - fprintf(fp,"\n"); - if(cgen->make_ansi) { - sprintf(ptt, "int %s_new_%s(struct %s *o, int flag)", - cgen->functname,ct_first->name,cgen->structname); - fprintf(fp,"%s\n",ptt); - if(ct_first->with_setter) { - ret= Cgen_write_to_ptt(cgen, ptt, 0); - if(ret<=0) - return(ret); - } - } else { - fprintf(fp,"int %s_new_%s(o,flag)\n",cgen->functname,ct_first->name); - fprintf(fp,"struct %s *o;\n",cgen->structname); - fprintf(fp,"int flag;\n"); - } - fprintf(fp,"{\n"); - fprintf(fp," int ret;\n"); - fprintf(fp," struct %s *c= NULL;\n",ct_first->dtype); - fprintf(fp,"\n"); - if(ct_first->bossless_list) - fprintf(fp," ret= %s_new(&c,0);\n",funct); - else - fprintf(fp," ret= %s_new(&c,o,0);\n",funct); - fprintf(fp," if(ret<=0)\n"); - fprintf(fp," return(ret);\n"); - fprintf(fp," %s_link(c,o->%s,0);\n",funct,ct_last->name); - fprintf(fp," o->%s= c;\n",ct_last->name); - fprintf(fp," if(o->%s==NULL)\n",ct_first->name); - fprintf(fp," o->%s= c;\n",ct_first->name); - fprintf(fp," return(1);\n"); - fprintf(fp,"}\n"); - fprintf(fp,"\n"); - ret= 1; -ex:; - return(ret); -} - - -int Cgen_write_c_destroy(cgen,flag) -struct CgeN *cgen; -int flag; -{ - int ret,l,management,pointer_level,i; - FILE *fp= NULL; - struct CtyP *ct,*next; - char funct[4096],*npt,ptt[4096]; - - fp= cgen->fp; - fprintf(fp,"\n"); - if(cgen->make_ansi) { - sprintf(ptt, "int %s_destroy(struct %s **objpt, int flag)", - cgen->functname,cgen->structname); - fprintf(fp,"%s\n",ptt); - ret= Cgen_write_to_ptt(cgen, ptt, 0); - if(ret<=0) - return(ret); - } else { - fprintf(fp,"int %s_destroy(objpt,flag)\n",cgen->functname); - fprintf(fp,"struct %s **objpt;\n",cgen->structname); - fprintf(fp,"int flag;\n"); - } - fprintf(fp,"{\n"); - fprintf(fp," struct %s *o;\n",cgen->structname); - fprintf(fp,"\n"); - fprintf(fp," o= *objpt;\n"); - fprintf(fp," if(o==NULL)\n"); - fprintf(fp," return(0);\n"); - fprintf(fp,"\n"); - for(ct= cgen->elements; ct!=NULL; ct= ct->next) { - if(ct->is_comment) - continue; - management= Ctyp_get_management(ct,0); - if(management==1 || management==4) { - strcpy(funct,ct->dtype); - l= strlen(funct); - if(l>0) { - if(cgen->make_lowercase) - funct[0]= tolower(funct[0]); - else - funct[0]= toupper(funct[0]); - funct[l-1]= tolower(funct[l-1]); - } - if(strcmp(ct->dtype,"char")==0) { - if(cgen->gen_for_stic==1) - fprintf(fp," Sregex_string("); - else if(cgen->gen_for_stic==2) - fprintf(fp," Smem_freE((char *) "); - else - fprintf(fp," free("); - } else if(strcmp(ct->dtype,"LstrinG")==0 || management==4) - fprintf(fp," %s_destroy_all(",funct); - else - fprintf(fp," %s_destroy(",funct); - - pointer_level= Ctyp_get_pointer_level(ct,0)-2; - for(i=0; i>pointer_level; i--) - fprintf(fp,"&"); - for(i=0; i<pointer_level; i++) - fprintf(fp,"*"); - fprintf(fp,"(o->%s)",ct->name); - if(strcmp(ct->dtype,"char")==0) { - if(cgen->gen_for_stic==1) - fprintf(fp,",NULL,0);\n"); - else - fprintf(fp,");\n"); - } else - fprintf(fp,",0);\n"); - } else if(management==2) { - next= ct->next; - if(next==NULL) { -broken_chain:; - sprintf(cgen->msg, - "Lonely -c found. They have to appear in pairs.\nName is : %s", - ct->name); - ret= 0; goto ex; - } - if(next->management!=3) - goto broken_chain; - fprintf(fp," if(o->%s!=NULL)\n",ct->name); - fprintf(fp," o->%s->%s= o->%s;\n",ct->name,next->name,next->name); - fprintf(fp," if(o->%s!=NULL)\n",next->name); - fprintf(fp," o->%s->%s= o->%s;\n",next->name,ct->name,ct->name); - ct= next; - } - } - fprintf(fp,"\n"); - if(cgen->gen_for_stic) - fprintf(fp," Smem_freE((char *) o);\n"); - else - fprintf(fp," free((char *) o);\n"); - fprintf(fp," *objpt= NULL;\n"); - fprintf(fp," return(1);\n"); - fprintf(fp,"}\n"); - fprintf(fp,"\n"); - if(cgen->is_managed_list){ - ret= Cgen_write_c_destroy_all(cgen,0); - if(ret<=0) - goto ex; - } - ret= 1; -ex:; - return(ret); -} - - -int Cgen_write_c_destroy_all(cgen,flag) -struct CgeN *cgen; -int flag; -{ - int ret,l,management,pointer_level,i; - FILE *fp= NULL; - struct CtyP *ct; - char ptt[4096]; - - fp= cgen->fp; - fprintf(fp,"\n"); - if(cgen->make_ansi) { - sprintf(ptt, "int %s_destroy_all(struct %s **objpt, int flag)", - cgen->functname, cgen->structname); - fprintf(fp,"%s\n",ptt); - ret= Cgen_write_to_ptt(cgen, ptt, 0); - if(ret<=0) - return(ret); - } else { - fprintf(fp,"int %s_destroy_all(objpt,flag)\n",cgen->functname); - fprintf(fp,"struct %s **objpt;\n",cgen->structname); - fprintf(fp,"int flag;\n"); - } - fprintf(fp,"{\n"); - fprintf(fp," struct %s *o,*n;\n",cgen->structname); - fprintf(fp,"\n"); - fprintf(fp," o= *objpt;\n"); - fprintf(fp," if(o==NULL)\n"); - fprintf(fp," return(0);\n"); - fprintf(fp," for(;o->prev!=NULL;o= o->prev);\n"); - fprintf(fp," for(;o!=NULL;o= n) {\n"); - fprintf(fp," n= o->next;\n"); - fprintf(fp," %s_destroy(&o,0);\n",cgen->functname); - fprintf(fp," }\n"); - fprintf(fp," *objpt= NULL;\n"); - fprintf(fp," return(1);\n"); - fprintf(fp,"}\n"); - fprintf(fp,"\n"); - ret= 1; -ex:; - return(ret); -} - - -int Cgen_write_c_access(cgen,flag) -struct CgeN *cgen; -int flag; -{ - int ret,l,mgt,pointer_level,i; - FILE *fp= NULL; - struct CtyP *ct; - char funct[4096],*npt,ptt[4096]; - - fp= cgen->fp; - for(ct= cgen->elements; ct!=NULL; ct= ct->next) { - if(ct->is_comment) - continue; - pointer_level= Ctyp_get_pointer_level(ct,0); - if(Ctyp_get_with_getter(ct,0)<=0) - goto after_getter; - fprintf(fp,"\n"); - if(cgen->make_ansi) { - sprintf(ptt, "int %s_get_%s(struct %s *o, ", - cgen->functname,ct->name,cgen->structname); - if(Ctyp_is_struct(ct,0)) - strcat(ptt,"struct "); - strcat(ptt,ct->dtype); - strcat(ptt," "); - for(i=0; i<pointer_level+1; i++) - strcat(ptt,"*"); - if(Ctyp_get_array_size(ct,0)>0) - strcat(ptt,"*"); - strcat(ptt,"pt"); - if(ct->management==4) - strcat(ptt,", int idx"); - strcat(ptt,", int flag)"); - fprintf(fp,"%s\n",ptt); - ret= Cgen_write_to_ptt(cgen, ptt, 0); - if(ret<=0) - return(ret); - } else { - fprintf(fp,"int %s_get_%s(o,pt",cgen->functname,ct->name); - if(ct->management==4) - fprintf(fp,",idx"); - fprintf(fp,",flag)\n"); - fprintf(fp,"struct %s *o;\n",cgen->structname); - if(Ctyp_is_struct(ct,0)) - fprintf(fp,"struct "); - fprintf(fp,"%s ",ct->dtype); - for(i=0; i<pointer_level+1; i++) - fprintf(fp,"*"); - if(Ctyp_get_array_size(ct,0)>0) - fprintf(fp,"*"); - fprintf(fp,"pt;\n"); - if(ct->management==4) - fprintf(fp,"int idx;\n"); - fprintf(fp,"int flag;\n"); - } - if(ct->management==4) - fprintf(fp,"/* Note: idx==-1 fetches the last item of the list */\n"); - fprintf(fp,"{\n"); - if(ct->management==4) { - strcpy(funct,ct->dtype); - l= strlen(funct); - if(cgen->make_lowercase) - funct[0]= tolower(funct[0]); - if(l>1) - funct[l-1]= tolower(funct[l-1]); - fprintf(fp," if(idx==-1) {\n"); - fprintf(fp," *pt= o->%s;\n",ct->next->name); - fprintf(fp," return(*pt!=NULL);\n"); - fprintf(fp," }\n"); - fprintf(fp," return(%s_by_idx(o->%s,(flag&1?1:idx),pt,flag&1));\n", - funct,ct->name); - } else { - fprintf(fp," *pt= o->%s;\n",ct->name); - fprintf(fp," return(1);\n"); - } - fprintf(fp,"}\n"); - fprintf(fp,"\n"); -after_getter:; - - if(Ctyp_get_with_setter(ct,0)<=0) - goto after_setter; - - /* <<< provisory : develop a setter for arrays */ - if(Ctyp_get_array_size(ct,0)>0) - goto after_setter; - - mgt= Ctyp_get_management(ct,0); - if(mgt==0 || - (mgt==1 && pointer_level==1)) { - /* -value or -managed pointers */ - /* was: -value or -managed char * */ - /* (mgt==1 && strcmp(ct->dtype,"char")==0 && pointer_level==1)) { */ - - fprintf(fp,"\n"); - if(cgen->make_ansi) { - sprintf(ptt, "int %s_set_%s(struct %s *o, ", - cgen->functname,ct->name,cgen->structname); - if(Ctyp_is_struct(ct,0)) - strcat(ptt,"struct "); - strcat(ptt,ct->dtype); - strcat(ptt," "); - for(i=0; i<pointer_level; i++) - strcat(ptt,"*"); - strcat(ptt,"value, int flag)"); - fprintf(fp,"%s\n",ptt); - ret= Cgen_write_to_ptt(cgen, ptt, 0); - if(ret<=0) - return(ret); - } else { - fprintf(fp,"int %s_set_%s(o,value,flag)\n",cgen->functname,ct->name); - fprintf(fp,"struct %s *o;\n",cgen->structname); - if(Ctyp_is_struct(ct,0)) - fprintf(fp,"struct "); - fprintf(fp,"%s ",ct->dtype); - for(i=0; i<pointer_level; i++) - fprintf(fp,"*"); - fprintf(fp,"value;\n"); - fprintf(fp,"int flag;\n"); - } - fprintf(fp,"{\n"); - if(mgt==1 && strcmp(ct->dtype,"char")==0) { - if(cgen->gen_for_stic==1) { - fprintf(fp," if(Sregex_string(&(o->%s),value,0)<=0)\n",ct->name); - fprintf(fp," return(-1);\n"); - } else if(cgen->gen_for_stic==2) { - fprintf(fp," if(Smem_clone_string(&(o->%s),value)<=0)\n",ct->name); - fprintf(fp," return(-1);\n"); - } else { - fprintf(fp," char *cpt;\n"); - fprintf(fp,"\n"); - fprintf(fp," cpt= malloc(strlen(value)+1);\n"); - fprintf(fp," if(cpt==NULL)\n"); - fprintf(fp," return(-1);\n"); - fprintf(fp," o->%s= cpt;\n",ct->name); - fprintf(fp," \n"); - } - } else { - fprintf(fp," o->%s= value;\n",ct->name); - } - fprintf(fp," return(1);\n"); - fprintf(fp,"}\n"); - fprintf(fp,"\n"); - } - -after_setter:; - } - - if(cgen->is_managed_list) { - fprintf(fp,"\n"); - if(cgen->make_ansi) { - sprintf(ptt,"int %s_link(struct %s *o, struct %s *link, int flag)", - cgen->functname,cgen->structname,cgen->structname); - fprintf(fp,"%s\n",ptt); -/* if(cgen->readonly) */ - { - ret= Cgen_write_to_ptt(cgen, ptt, 0); - if(ret<=0) - return(ret); - } - } else { - fprintf(fp,"int %s_link(o,link,flag)\n",cgen->functname); - fprintf(fp,"struct %s *o;\n",cgen->structname); - fprintf(fp,"struct %s *link;\n",cgen->structname); - fprintf(fp,"int flag;\n"); - } - fprintf(fp,"/*\n"); - fprintf(fp," bit0= insert as link->prev rather than as link->next\n"); - fprintf(fp,"*/\n"); - fprintf(fp,"{\n"); - fprintf(fp," if(o->prev!=NULL)\n"); - fprintf(fp," o->prev->next= o->next;\n"); - fprintf(fp," if(o->next!=NULL)\n"); - fprintf(fp," o->next->prev= o->prev;\n"); - fprintf(fp," o->prev= o->next= NULL;\n"); - fprintf(fp," if(link==NULL)\n"); - fprintf(fp," return(1);\n"); - fprintf(fp," if(flag&1) {\n"); - fprintf(fp," o->next= link;\n"); - fprintf(fp," o->prev= link->prev;\n"); - fprintf(fp," if(o->prev!=NULL)\n"); - fprintf(fp," o->prev->next= o;\n"); - fprintf(fp," link->prev= o;\n"); - fprintf(fp," } else {\n"); - fprintf(fp," o->prev= link;\n"); - fprintf(fp," o->next= link->next;\n"); - fprintf(fp," if(o->next!=NULL)\n"); - fprintf(fp," o->next->prev= o;\n"); - fprintf(fp," link->next= o;\n"); - fprintf(fp," }\n"); - fprintf(fp," return(1);\n"); - fprintf(fp,"}\n"); - fprintf(fp,"\n"); - - fprintf(fp,"\n"); - if(cgen->make_ansi) { - sprintf(ptt,"int %s_count(struct %s *o, int flag)", - cgen->functname,cgen->structname); - fprintf(fp,"%s\n",ptt); - ret= Cgen_write_to_ptt(cgen, ptt, 0); - if(ret<=0) - return(ret); - } else { - fprintf(fp,"int %s_count(o,flag)\n",cgen->functname); - fprintf(fp,"struct %s *o;\n",cgen->structname); - fprintf(fp,"int flag;\n"); - } - fprintf(fp,"/* flag: bit1= count from start of list */\n"); - fprintf(fp,"{\n"); - fprintf(fp," int counter= 0;\n"); - fprintf(fp,"\n"); - fprintf(fp," if(flag&2)\n"); - fprintf(fp," for(;o->prev!=NULL;o= o->prev);\n"); - fprintf(fp," for(;o!=NULL;o= o->next)\n"); - fprintf(fp," counter++;\n"); - fprintf(fp," return(counter);\n"); - fprintf(fp,"}\n"); - fprintf(fp,"\n"); - - fprintf(fp,"\n"); - if(cgen->make_ansi) { - sprintf(ptt, - "int %s_by_idx(struct %s *o, int idx, struct %s **pt, int flag)", - cgen->functname,cgen->structname,cgen->structname); - fprintf(fp,"%s\n",ptt); - ret= Cgen_write_to_ptt(cgen, ptt, 0); - if(ret<=0) - return(ret); - } else { - fprintf(fp,"int %s_count(o,idx,pt,flag)\n",cgen->functname); - fprintf(fp,"struct %s *o;\n",cgen->structname); - fprintf(fp,"int idx;\n"); - fprintf(fp,"struct %s **pt;\n",cgen->structname); - fprintf(fp,"int flag;\n"); - } - fprintf(fp, - "/* flag: bit0= fetch first (idx<0) or last (idx>0) item in list\n"); - fprintf(fp, - " bit1= address from start of list */\n"); - fprintf(fp,"{\n"); - fprintf(fp," int i,abs_idx;\n"); - fprintf(fp," struct %s *npt;\n",cgen->structname); - fprintf(fp,"\n"); - fprintf(fp," if(flag&2)\n"); - fprintf(fp," for(;o->prev!=NULL;o= o->prev);\n"); - fprintf(fp," abs_idx= (idx>0?idx:-idx);\n"); - fprintf(fp," *pt= o;\n"); - fprintf(fp," for(i= 0;(i<abs_idx || (flag&1)) && *pt!=NULL;i++) {\n"); - fprintf(fp," if(idx>0)\n"); - fprintf(fp," npt= o->next;\n"); - fprintf(fp," else\n"); - fprintf(fp," npt= o->prev;\n"); - fprintf(fp," if(npt==NULL && (flag&1))\n"); - fprintf(fp," break;\n"); - fprintf(fp," *pt= npt;\n"); - fprintf(fp," }\n"); - fprintf(fp," return(*pt!=NULL);\n"); - fprintf(fp,"}\n"); - fprintf(fp,"\n"); - } - - return(1); -} - - -int Cgen_write_c_method_include(cgen,flag) -struct CgeN *cgen; -int flag; -{ - FILE *fp= NULL; - char filename[4096],line[4096]; - struct stat stbuf; - time_t t0; - - sprintf(filename,"%s.c.methods",cgen->classname); - if(stat(filename,&stbuf)!=-1) - goto write_include; - fp= fopen(filename,"w"); - if(fp==NULL) { - sprintf(cgen->msg,"Cannot open file '%s' in %s-mode. %s", - filename,"w",strerror(errno)); - return(0); - } - fprintf(fp,"\n"); - fprintf(fp,"/* File %s */\n",filename); - fprintf(fp,"/* Manually provided C code for class %s */\n", - cgen->classname); - fprintf(fp,"/* This file gets copied to the end of %s.c */\n", - cgen->classname); - fprintf(fp,"\n"); - fclose(fp); fp= NULL; - -write_include:; - fp= fopen(filename,"r"); - if(fp==NULL) { - sprintf(cgen->msg,"Cannot open file '%s' in %s-mode. %s", - filename,"r",strerror(errno)); - return(0); - } - fprintf(cgen->fp,"\n"); - fprintf(cgen->fp, -"/* -------------- end of automatically regenerated code -------------- */\n"); - fprintf(cgen->fp,"\n"); - while(1) { - if(Sfile_fgets(line,sizeof(line)-1,fp)==NULL) - break; - fprintf(cgen->fp,"%s\n",line); - } - fclose(fp); fp= NULL; - return(1); -} - -int Cgen_write_c(cgen,flag) -struct CgeN *cgen; -int flag; -/* - bit0= also write access functions *_set_* *_get_* [*_link_*] -*/ -{ - int ret; - - sprintf(cgen->filename,"%s.c",cgen->classname); - ret= Cgen_open_wfile(cgen,0); - if(ret<=0) - goto ex; - ret= Cgen_write_c_head(cgen,0); - if(ret<=0) - goto ex; - ret= Cgen_write_c_new(cgen,0); - if(ret<=0) - goto ex; - ret= Cgen_write_c_destroy(cgen,0); - if(ret<=0) - goto ex; - if(flag&1) { - ret= Cgen_write_c_access(cgen,0); - if(ret<=0) - goto ex; - } - ret= Cgen_write_c_method_include(cgen,0); - if(ret<=0) - goto ex; - - if(cgen->make_ansi) { /* public .h file collected ANSI prototypes */ - ret= Cgen_finish_public_h(cgen,0); - if(ret<=0) - goto ex; - } - - ret= 1; -ex:; - if(cgen->fp!=NULL) - {fclose(cgen->fp); cgen->fp= NULL;} - return(ret); -} - - -int Cgen__write_global_include(global_include_file,flag) -char *global_include_file; -int flag; -/* - bit0= write footer rather than header - bit1= allow overwriting of existing file -*/ -{ - FILE *fp= NULL; - int ret; - char fmode[4],timetext[81],macro_name[4096],*cpt; - time_t t0; - struct stat stbuf; - - strcpy(macro_name,global_include_file); - for(cpt= macro_name; *cpt!=0; cpt++) { - if(*cpt>='A' && *cpt<='Z') - *cpt= tolower(*cpt); - else if((*cpt>='a' && *cpt<='z') || (*cpt>='0' && *cpt<='9') || *cpt=='_') - ; - else - *cpt= '_'; - } - macro_name[0]= toupper(macro_name[0]); - strcat(macro_name,"_includeD"); - - strcpy(fmode,"w"); - if(flag&1) { - strcpy(fmode,"a"); - } else { - if(stat(global_include_file,&stbuf)!=-1 && !(flag&2)) { - fprintf(stderr,"+++ File '%s' already existing.",global_include_file); - ret= 0; goto ex; - } - } - fp= fopen(global_include_file,fmode); - if(fp==NULL) { - fprintf(stderr,"+++ Cannot open file '%s' in %s-mode. %s", - global_include_file,fmode,strerror(errno)); - ret= 0; goto ex; - } - if(flag&1) { - fprintf(fp,"\n"); - fprintf(fp,"#endif /* %s */\n\n",macro_name); - t0= time(0); - strftime(timetext,sizeof(timetext),"%a, %d %b %Y %H:%M:%S GMT", - gmtime(&t0)); - fprintf(fp,"/* ( derived from stub generated by CgeN on %s ) */\n", - timetext); - - } else { - fprintf(fp,"\n"); - fprintf(fp,"#ifndef %s\n",macro_name); - fprintf(fp,"#define %s\n",macro_name); - fprintf(fp,"\n"); - } - -ex:; - if(fp!=NULL) - fclose(fp); - return(ret); -} - - -/* ---------------- Sfile and Sregex Emancipation copies ---------------- */ - - -char *Sfile_fgets(line,maxl,fp) -char *line; -int maxl; -FILE *fp; -{ -int l; -char *ret; - ret= fgets(line,maxl,fp); - if(ret==NULL) - return(NULL); - l= strlen(line); - if(l>0) if(line[l-1]=='\r') line[--l]= 0; - if(l>0) if(line[l-1]=='\n') line[--l]= 0; - if(l>0) if(line[l-1]=='\r') line[--l]= 0; - return(ret); -} - - -int Sregex_string_cut(handle,text,len,flag) -char **handle; -char *text; -int len; -int flag; -/* - bit0= append (text!=NULL) - bit1= prepend (text!=NULL) -*/ -{ - int l=0; - char *old_handle; - - if((flag&(1|2))&&*handle!=NULL) - l+= strlen(*handle); - old_handle= *handle; - if(text!=NULL) { - l+= len; - *handle= TSOB_FELD(char,l+1); - if(*handle==NULL) { - *handle= old_handle; - return(0); - } - if((flag&2) && old_handle!=NULL) { - strncpy(*handle,text,len); - strcpy((*handle)+len,old_handle); - } else { - if((flag&1) && old_handle!=NULL) - strcpy(*handle,old_handle); - else - (*handle)[0]= 0; - if(len>0) - strncat(*handle,text,len); - } - } else { - *handle= NULL; - } - if(old_handle!=NULL) - Smem_freE(old_handle); - return(1); -} - - -int Sregex_string(handle,text,flag) -char **handle; -char *text; -int flag; -/* - bit0= append (text!=NULL) - bit1= prepend (text!=NULL) -*/ -{ - int ret,l=0; - - if(text!=NULL) - l= strlen(text); - -/* #define Sregex_looking_for_contenT 1 */ -#ifdef Sregex_looking_for_contenT - /* a debugging point if a certain text content has to be caught */ - if(text!=NULL) - if(strcmp(text,"clear")==0) - ret= 0; -#endif - - ret= Sregex_string_cut(handle,text,l,flag&(1|2)); - return(ret); -} - - -int Sregex_trimline(line,flag) -/* - removes line endings as well as leading and trailing blanks -*/ -char *line; -int flag; -/* - bit0= do not remove line end (protects trailing blanks if line end is present) - bit1= do not remove leading blanks - bit2= do not remove trailing blanks - bit3= remove surrounding quotation marks (after removing line end) -*/ -{ - char *cpt,*wpt; - int l; - - if(!(flag&1)){ - l= strlen(line); - if(l>0) if(line[l-1]=='\r') line[--l]= 0; - if(l>0) if(line[l-1]=='\n') line[--l]= 0; - if(l>0) if(line[l-1]=='\r') line[--l]= 0; - } - if(flag&3){ - l= strlen(line); - if(l>1) if(line[0]==34 && line[l-1]==34) { - wpt= line; - cpt= wpt+1; - while(*cpt!=0) - *(wpt++)= *(cpt++); - line[l-2]= 0; - } - } - if(!(flag&2)){ - wpt= cpt= line; - while(*(cpt)!=0) { - if(!isspace(*cpt)) - break; - cpt++; - } - while(*(cpt)!=0) - *(wpt++)= *(cpt++); - *wpt= 0; - } - if(!(flag&4)){ - l= strlen(line); - if(l<=0) - return(1); - cpt= line+l; - while(cpt-->=line){ - if(!isspace(*cpt)) - break; - *(cpt)= 0; - } - } - return(1); -} - - -/* -------------------------------------------------------------- */ - - -main(argc,argv) -int argc; -char **argv; -{ - struct CgeN *cgen= NULL; - int ret, msg_printed= 0,first=1,gen_for_stic= 1, make_ansi= 0, i; - int make_lowercase= 0, may_overwrite= 0; - char global_include_file[4096]; - - global_include_file[0]= 0; - - for(i= 1; i<argc; i++) { - if(strcmp(argv[i],"-no_stic")==0) - gen_for_stic= 0; - else if(strcmp(argv[i],"-smem_local")==0) - gen_for_stic= 2; - else if(strcmp(argv[i],"-ansi")==0) - make_ansi= 1; - else if(strcmp(argv[i],"-global_include")==0) { - if(i+1>=argc) - strcpy(global_include_file,"global_include.h"); - else { - i++; - strcpy(global_include_file,argv[i]); - } - } else if(strcmp(argv[i],"-lowercase")==0) { - make_lowercase= 1; - } else if(strcmp(argv[i],"-overwrite")==0) { - may_overwrite= 1; - } else { - fprintf(stderr,"+++ %s: Unrecognized option: %s\n",argv[0],argv[i]); - {ret= 0; goto ex;} - } - } - - if(strlen(global_include_file)>0) { - /* begin */ - ret= Cgen__write_global_include(global_include_file,(!!may_overwrite)<<1); - if(ret<=0) - goto ex; - } - while(!feof(stdin)) { - ret= Cgen_new(&cgen,0); - if(ret<=0) - goto ex; - - /* <<< can be done neater */ - cgen->gen_for_stic= gen_for_stic; - cgen->make_ansi= make_ansi; - strcpy(cgen->global_include_file,global_include_file); - cgen->make_lowercase= make_lowercase; - cgen->may_overwrite= may_overwrite; - - ret= Cgen_read_fp(cgen,stdin,first); - if(ret<=0) - goto ex; - if(ret==2) - break; - first= 0; - ret= Cgen_write_h(cgen,0); - if(ret<=0) - goto ex; - ret= Cgen_write_c(cgen,1); - if(ret<=0) - goto ex; - } - if(strlen(global_include_file)>0) { - /* finalize */ - ret= Cgen__write_global_include(global_include_file,1); - if(ret<=0) - goto ex; - } - ret= 1; -ex: - if(cgen!=NULL) - if(cgen->msg[0]!=0) { - fprintf(stderr,"+++ %s\n",cgen->msg); - msg_printed= 1; - } - if(ret<=0 &&!msg_printed) { - if(errno>0) - fprintf(stderr,"+++ Error : %s\n",strerror(errno)); - else if(ret==-1) - fprintf(stderr, - "+++ Program run failed (probably due to lack of memory)\n"); - else - fprintf(stderr,"+++ Program run failed\n"); - } - Cgen_destroy(&cgen,0); - exit(1-ret); -} diff --git a/libcevap/cgen.h b/libcevap/cgen.h deleted file mode 100644 index 5b464a0..0000000 --- a/libcevap/cgen.h +++ /dev/null @@ -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 */ - diff --git a/libcevap/cgen.txt b/libcevap/cgen.txt deleted file mode 100644 index d260af9..0000000 --- a/libcevap/cgen.txt +++ /dev/null @@ -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] -@ -+ - - diff --git a/libcevap/ctyp.c b/libcevap/ctyp.c deleted file mode 100644 index 2b27575..0000000 --- a/libcevap/ctyp.c +++ /dev/null @@ -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); -} - diff --git a/libcevap/ctyp.h b/libcevap/ctyp.h deleted file mode 100644 index 13657b0..0000000 --- a/libcevap/ctyp.h +++ /dev/null @@ -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 */ - diff --git a/libcevap/extract_cgen_input.sh b/libcevap/extract_cgen_input.sh deleted file mode 100755 index 3ca096f..0000000 --- a/libcevap/extract_cgen_input.sh +++ /dev/null @@ -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 diff --git a/libcevap/libcevap_gen.sh b/libcevap/libcevap_gen.sh deleted file mode 100755 index 48ed786..0000000 --- a/libcevap/libcevap_gen.sh +++ /dev/null @@ -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 "$@" - diff --git a/libcevap/libdax_equip.gif b/libcevap/libdax_equip.gif deleted file mode 100644 index 3df86ae..0000000 Binary files a/libcevap/libdax_equip.gif and /dev/null differ diff --git a/libcevap/libdax_job.gif b/libcevap/libdax_job.gif deleted file mode 100644 index 8138ad2..0000000 Binary files a/libcevap/libdax_job.gif and /dev/null differ diff --git a/libcevap/libdax_model.txt b/libcevap/libdax_model.txt deleted file mode 100644 index 5b5c3c7..0000000 --- a/libcevap/libdax_model.txt +++ /dev/null @@ -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 . - ------------------------------------------------------------------------- diff --git a/libcevap/libdax_overview.gif b/libcevap/libdax_overview.gif deleted file mode 100644 index f4e5715..0000000 Binary files a/libcevap/libdax_overview.gif and /dev/null differ diff --git a/libcevap/main.c b/libcevap/main.c deleted file mode 100644 index b537b5f..0000000 --- a/libcevap/main.c +++ /dev/null @@ -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); -} diff --git a/libcevap/smem.c b/libcevap/smem.c deleted file mode 100644 index 94aed82..0000000 --- a/libcevap/smem.c +++ /dev/null @@ -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); -} - - diff --git a/libcevap/smem.h b/libcevap/smem.h deleted file mode 100644 index 28b5e98..0000000 --- a/libcevap/smem.h +++ /dev/null @@ -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. - -*/ diff --git a/test/Makefile b/test/Makefile deleted file mode 100644 index 062350d..0000000 --- a/test/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -all clean: - $(MAKE) -C .. -$(MAKEFLAGS) $@ - -.PHONY: all clean diff --git a/test/dewav.c b/test/dewav.c deleted file mode 100644 index 6166bc3..0000000 --- a/test/dewav.c +++ /dev/null @@ -1,215 +0,0 @@ - -/* dewav - Demo of libburn extension libdax_audioxtr - Audio track data extraction facility of libdax and libburn. - Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL -*/ - -#include <stdio.h> -#include <ctype.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> - - -/* libdax_audioxtr is quite independent of libburn. It only needs - the messaging facility libdax_msgs. So we got two build variations: -*/ -#ifdef Dewav_without_libburN - -/* This build environment is standalone relying only on libdax components */ -#include "../libburn/libdax_msgs.h" -struct libdax_msgs *libdax_messenger= NULL; - -#else /* Dewav_without_libburN */ - -/* This build environment uses libdax_msgs via libburn */ -/* Thus the API header of libburn */ -#include "../libburn/libburn.h" - -#endif /* ! Dewav_without_libburN */ - - -/* The API for .wav extraction */ -#include "../libburn/libdax_audioxtr.h" - - -int main(int argc, char **argv) -{ - /* This program acts as filter from in_path to out_path */ - char *in_path= "", *out_path= "-"; - - /* The read-and-extract object for use with in_path */ - struct libdax_audioxtr *xtr= NULL; - /* The file descriptor eventually detached from xtr */ - int xtr_fd= -2; - - /* Default output is stdout */ - int out_fd= 1; - - /* Inquired source parameters */ - char *fmt, *fmt_info; - int num_channels, sample_rate, bits_per_sample, msb_first; - off_t data_size; - - /* Auxiliary variables */ - int ret, i, be_strict= 1, buf_count, detach_fd= 0, extract_all= 0; - char buf[2048]; - - if(argc < 2) - goto help; - for(i= 1; i<argc; i++) { - if(strcmp(argv[i],"-o")==0) { - if(i>=argc-1) { - fprintf(stderr,"%s: option -o needs a file address as argument.\n", - argv[0]); - exit(1); - } - i++; - out_path= argv[i]; - } else if(strcmp(argv[i],"--lax")==0) { - be_strict= 0; - } else if(strcmp(argv[i],"--strict")==0) { - be_strict= 1; - } else if(strcmp(argv[i],"--detach_fd")==0) { - /* Test the dirty detach method. Always --extract_all */ - detach_fd= 1; - } else if(strcmp(argv[i],"--extract_all")==0) { - /* Dirty : read all available bytes regardless of data_size */ - extract_all= 1; - } else if(strcmp(argv[i],"--help")==0) { -help:; - fprintf(stderr, - "usage: %s [-o output_path|\"-\"] [--lax|--strict] [source_path|\"-\"]\n", - argv[0]); - exit(0); - } else { - if(in_path[0]!=0) { - fprintf(stderr,"%s: only one input file is allowed.\n", argv[0]); - exit(2); - } - in_path= argv[i]; - } - } - if(in_path[0] == 0) - in_path= "-"; - - -/* Depending on wether this was built standalone or with full libburn : -*/ -#ifdef Dewav_without_libburN - - /* Initialize and set up libdax messaging system */ - ret= libdax_msgs_new(&libdax_messenger,0); - if(ret<=0) { - fprintf(stderr,"Failed to create libdax_messenger object.\n"); - exit(3); - } - libdax_msgs_set_severities(libdax_messenger, LIBDAX_MSGS_SEV_NEVER, - LIBDAX_MSGS_SEV_NOTE, "", 0); - fprintf(stderr, "dewav on libdax\n"); - -#else /* Dewav_without_libburN */ - - /* Initialize libburn and set up its messaging system */ - if(burn_initialize() == 0) { - fprintf(stderr,"Failed to initialize libburn.\n"); - exit(3); - } - /* Print messages of severity NOTE or more directly to stderr */ - burn_msgs_set_severities("NEVER", "NOTE", ""); - fprintf(stderr, "dewav on libburn\n"); - -#endif /* ! Dewav_without_libburN */ - - - /* Open audio source and create extractor object */ - ret= libdax_audioxtr_new(&xtr, in_path, 0); - if(ret<=0) - exit(4); - if(strcmp(out_path,"-")!=0) { - out_fd= open(out_path, O_WRONLY | O_CREAT | O_TRUNC, - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - if(out_fd == -1) { - fprintf(stderr, "Cannot open file: %s\n", out_path); - fprintf(stderr, "Error reported: '%s' (%d)\n",strerror(errno), errno); - exit(5); - } - } - /* Obtain and print parameters of audio source */ - libdax_audioxtr_get_id(xtr, &fmt, &fmt_info, - &num_channels, &sample_rate, &bits_per_sample, &msb_first, 0); - fprintf(stderr, "Detected format: %s\n", fmt_info); - libdax_audioxtr_get_size(xtr, &data_size, 0); - fprintf(stderr, "Data size : %.f bytes\n", (double) data_size); - if((strcmp(fmt,".wav")!=0 && strcmp(fmt,".au")!=0) || - num_channels!=2 || sample_rate!=44100 || bits_per_sample!=16) { - fprintf(stderr, - "%sAudio source parameters do not comply to cdrskin/README specs\n", - (be_strict ? "" : "WARNING: ")); - if(be_strict) - exit(6); - } - if(msb_first==0) - fprintf(stderr, - "NOTE: Extracted data to be written with cdrskin option -swab\n"); - - if(detach_fd) { - /* Take over fd from xtr */; - ret= libdax_audioxtr_detach_fd(xtr, &xtr_fd, 0); - if(ret<=0) { - fprintf(stderr, "Cannot detach file descriptor from extractor\n"); - exit(8); - } - /* not needed any more */ - libdax_audioxtr_destroy(&xtr, 0); - fprintf(stderr, "Note: detached fd and freed extractor object.\n"); - } - - /* Extract and put out raw audio data */; - while(1) { - if(detach_fd) { - buf_count= read(xtr_fd, buf, sizeof(buf)); - if(buf_count==-1) - fprintf(stderr,"Error while reading from detached fd\n(%d) '%s'\n", - errno, strerror(errno)); - } else { - buf_count= libdax_audioxtr_read(xtr, buf, sizeof(buf), !!extract_all); - } - if(buf_count < 0) - exit(7); - if(buf_count == 0) - break; - - ret= write(out_fd, buf, buf_count); - if(ret == -1) { - fprintf(stderr, "Failed to write buffer of %d bytes to: %s\n", - buf_count, out_path); - fprintf(stderr, "Error reported: '%s' (%d)\n", strerror(errno), errno); - exit(5); - } - - } - - /* Shutdown */ - if(out_fd>2) - close(out_fd); - /* ( It is permissible to do this with xtr==NULL ) */ - libdax_audioxtr_destroy(&xtr, 0); - -#ifdef Dewav_without_libburN - - libdax_msgs_destroy(&libdax_messenger,0); - -#else /* Dewav_without_libburN */ - - burn_finish(); - -#endif /* ! Dewav_without_libburN */ - - exit(0); -} diff --git a/test/fake_au.c b/test/fake_au.c deleted file mode 100644 index 01d7a41..0000000 --- a/test/fake_au.c +++ /dev/null @@ -1,164 +0,0 @@ - -/* fake_au - Fakes a file in SUN .au format from a raw little-endian PCM audio file - (e.g. a file extracted from .wav by test/dewav). The input data are assumed - to be 16 bit, stereo, 44100 Hz. - Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL - - Info used: http://www.opengroup.org/public/pubs/external/auformat.html -*/ - - -#include <ctype.h> -#include <sys/types.h> -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <string.h> - - -int fake_write(unsigned char *buf, size_t size, FILE *fp) -{ - int ret; - - ret= fwrite(buf,size,1,fp); - if(ret==1) - return(1); - fprintf(stderr,"Error %d while writing: '%s'\n",errno,strerror(errno)); - return(0); -} - - -int main(int argc, char **argv) -{ - int ret, i; - unsigned data_size= 0,byte_count,exit_value= 0; - FILE *fp_out= stdout,*fp_in= stdin; - unsigned char buf[4]; - char out_path[4096],in_path[4096]; - struct stat stbuf; - - strcpy(out_path,"-"); - strcpy(in_path,""); - if(argc < 2) { - exit_value= 1; - goto help; - } - for(i= 1; i<argc; i++) { - if(strcmp(argv[i],"-o")==0) { - if(i>=argc-1) { - fprintf(stderr,"%s: option -o needs a file address as argument.\n", - argv[0]); - exit(1); - } - i++; - strcpy(out_path, argv[i]); - } else if(strcmp(argv[i],"--stdin_size")==0) { - if(i>=argc-1) { - fprintf(stderr,"%s: option --stdin_size needs a number as argument.\n", - argv[0]); - exit(1); - } - i++; - sscanf(argv[i],"%u",&data_size); - } else if(strcmp(argv[i],"--help")==0) { - exit_value= 0; -help:; - fprintf(stderr,"usage: %s \\\n", argv[0]); - fprintf(stderr," [-o output_path|\"-\"] [source_path | --stdin_size size]\n"); - fprintf(stderr, - "Disguises an extracted .wav stream as .au stereo, 16bit, 44100Hz\n"); - fprintf(stderr, - "stdin gets byte-swapped and appended up to the announced data_size.\n"); - exit(exit_value); - } else { - if(in_path[0]!=0) { - fprintf(stderr,"%s: only one input file is allowed.\n", argv[0]); - exit(1); - } - strcpy(in_path, argv[i]); - } - } - - if(strcmp(in_path,"-")==0 || in_path[0]==0) { - if(data_size==0) { - fprintf(stderr,"%s: input from stdin needs option --stdin_size.\n", - argv[0]); - exit(6); - } - fp_in= stdin; - } else { - fp_in= fopen(in_path,"r"); - if(stat(in_path,&stbuf)!=-1) - data_size= stbuf.st_size; - } - if(fp_in==NULL) { - fprintf(stderr,"Error %d while fopen(\"%s\",\"r\") : '%s'\n", - errno,in_path,strerror(errno)); - exit(2); - } - - if(strcmp(out_path,"-")==0) { - fp_out= stdout; - } else { - if(stat(out_path,&stbuf)!=-1) { - fprintf(stderr,"%s: file '%s' already existing\n",argv[0],out_path); - exit(4); - } - fp_out= fopen(out_path,"w"); - } - if(fp_out==NULL) { - fprintf(stderr,"Error %d while fopen(\"%s\",\"w\") : '%s'\n", - errno,out_path,strerror(errno)); - exit(2); - } - - fake_write((unsigned char *) ".snd",4,fp_out); /* magic number */ - buf[0]= buf[1]= buf[2]= 0; - buf[3]= 32; - fake_write(buf,4,fp_out); /* data_location */ - buf[0]= (data_size>>24)&0xff; - buf[1]= (data_size>>16)&0xff; - buf[2]= (data_size>>8)&0xff; - buf[3]= (data_size)&0xff; - fake_write(buf,4,fp_out); /* data_size */ - buf[0]= buf[1]= buf[2]= 0; - buf[3]= 3; - fake_write(buf,4,fp_out); /* encoding 16 Bit PCM */ - buf[0]= buf[1]= 0; - buf[2]= 172; - buf[3]= 68; - fake_write(buf,4,fp_out); /* sample rate 44100 Hz */ - buf[0]= buf[1]= buf[2]= 0; - buf[3]= 2; - fake_write(buf,4,fp_out); /* number of channels */ - buf[0]= buf[1]= buf[2]= buf[3]= 0; - fake_write(buf,4,fp_out); /* padding */ - fake_write(buf,4,fp_out); /* padding */ - - for(byte_count= 0; byte_count<data_size; byte_count+=2) { - ret= fread(buf,2,1,fp_in); - if(ret<=0) { - fprintf(stderr,"Premature end end of input\n"); - exit_value= 5; - break; - } - buf[3]= buf[0]; - buf[2]= buf[1]; - ret= fake_write(buf+2,2,fp_out); - if(ret<=0) { - exit_value= 3; - break; - } - } - if(fp_out!=stdout) - fclose(fp_out); - if(fp_in!=stdin) - fclose(fp_in); - fprintf(stderr, "Swapped and appended: %u stdin bytes\n",byte_count); - exit(exit_value); -} - diff --git a/test/libburner.c b/test/libburner.c deleted file mode 100644 index b5c261b..0000000 --- a/test/libburner.c +++ /dev/null @@ -1,797 +0,0 @@ - -/* 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 */ - - -/** 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. - - 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 - define the standard way how above three gestures can be implemented and - stay upward compatible for a good while. - - Before you can do anything, you have to initialize libburn by - burn_initialize() - and provide some signal and abort handling, e.g. by the builtin handler, by - burn_set_signal_handling() - as it is done in main() at the end of this file. Then you aquire a - drive in an appropriate way conforming to the API. The two main - approaches are shown here in application functions: - libburner_aquire_by_adr() demonstrates usage as of cdrecord traditions - libburner_aquire_by_driveno() demonstrates a scan-and-choose approach - With that aquired drive you can blank a CD-RW - 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_payload() - When everything is done, main() releases the drive and shuts down libburn: - burn_drive_release(); - burn_finish() - -*/ - -/** See this for the decisive API specs . libburn.h is The Original */ -/* For using the installed header file : #include <libburn/libburn.h> */ -/* This program insists in the own headerfile. */ -#include "../libburn/libburn.h" - -/* libburn is intended for Linux systems with kernel 2.4 or 2.6 for now */ -#include <stdio.h> -#include <ctype.h> -#include <sys/types.h> -#include <unistd.h> -#include <string.h> -#include <stdlib.h> -#include <time.h> -#include <errno.h> -#include <sys/stat.h> -#include <fcntl.h> - - -/** For simplicity i use global variables to represent the drives. - Drives are systemwide global, so we do not give away much of good style. -*/ - -/** This list will hold the drives known to libburn. This might be all CD - drives of the system and thus might impose severe impact on the system. -*/ -static struct burn_drive_info *drive_list; - -/** If you start a long lasting operation with drive_count > 1 then you are - not friendly to the users of other drives on those systems. Beware. */ -static unsigned int drive_count; - -/** This variable indicates wether the drive is grabbed and must be - finally released */ -static int drive_is_grabbed = 0; - -/** A number and a text describing the type of media in aquired drive */ -static int current_profile= -1; -static char current_profile_name[80]= {""}; - - -/* Some in-advance definitions to allow a more comprehensive ordering - of the functions and their explanations in here */ -int libburner_aquire_by_adr(char *drive_adr); -int libburner_aquire_by_driveno(int *drive_no); - - -/* ------------------------------- API gestures ---------------------------- */ - -/** You need to aquire a drive before burning. The API offers this as one - compact call and alternatively as application controllable gestures of - whitelisting, scanning for drives and finally grabbing one of them. - - If you have a persistent address of the drive, then the compact call is - to prefer because it only touches one drive. On modern Linux kernels, - there should be no fatal disturbance of ongoing burns of other libburn - instances with any of our approaches. We use open(O_EXCL) by default. - On /dev/hdX it should cooperate with growisofs and some cdrecord variants. - On /dev/sgN versus /dev/scdM expect it not to respect other programs. -*/ -int libburner_aquire_drive(char *drive_adr, int *driveno) -{ - int ret; - - if(drive_adr != NULL && drive_adr[0] != 0) - ret = libburner_aquire_by_adr(drive_adr); - else - ret = libburner_aquire_by_driveno(driveno); - if (ret <= 0) - return ret; - burn_disc_get_profile(drive_list[0].drive, ¤t_profile, - current_profile_name); - if (current_profile_name[0]) - printf("Detected media type: %s\n", current_profile_name); - return 1; -} - - -/** 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. -*/ -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,"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"); - drive_is_grabbed = 1; - } - return ret; -} - - -/** This method demonstrates how to use libburn without knowing a persistent - drive address in advance. It has to make sure that after assessing the list - of available drives, all unwanted drives get closed again. As long as they - are open, no other libburn instance can see them. This is an intended - locking feature. The application is responsible for giving up the locks - by either burn_drive_release() (only after burn_drive_grab() !), - burn_drive_info_forget(), burn_drive_info_free(), or burn_finish(). - @param driveno the index number in libburn's drive list. This will get - set to 0 on success and will then be the drive index to - use in the further dourse of processing. - @return 1 success , <= 0 failure -*/ -int libburner_aquire_by_driveno(int *driveno) -{ - char adr[BURN_DRIVE_ADR_LEN]; - int ret, i; - - printf("Beginning to scan for devices ...\n"); - while (!burn_drive_scan(&drive_list, &drive_count)) - usleep(100002); - if (drive_count <= 0 && *driveno >= 0) { - printf("FAILED (no drives found)\n"); - return 0; - } - printf("Done\n"); - - /* - Interactive programs may choose the drive number at this moment. - - drive[0] to drive[drive_count-1] are struct burn_drive_info - as defined in libburn/libburn.h . This structure is part of API - and thus will strive for future compatibility on source level. - Have a look at the info offered. - Caution: do not take .location for drive address. Always use - burn_drive_get_adr() or you might become incompatible - in future. - Note: bugs with struct burn_drive_info - if any - will not be - easy to fix. Please report them but also strive for - workarounds on application level. - */ - printf("\nOverview of accessible drives (%d found) :\n", - drive_count); - printf("-----------------------------------------------------------------------------\n"); - for (i = 0; i < drive_count; i++) { - if (burn_drive_get_adr(&(drive_list[i]), adr) <=0) - strcpy(adr, "-get_adr_failed-"); - printf("%d --drive '%s' : '%s' '%s'\n", - i,adr,drive_list[i].vendor,drive_list[i].product); - } - printf("-----------------------------------------------------------------------------\n\n"); - - /* - On multi-drive systems save yourself from sysadmins' revenge. - - Be aware that you hold reserved all available drives at this point. - So either make your choice quick enough not to annoy other system - users, or set free the drives for a while. - - The tested way of setting free all drives is to shutdown the library - and to restart when the choice has been made. The list of selectable - drives should also hold persistent drive addresses as obtained - above by burn_drive_get_adr(). By such an address one may use - burn_drive_scan_and_grab() to finally aquire exactly one drive. - - A not yet tested shortcut should be to call burn_drive_info_free() - and to call either burn_drive_scan() or burn_drive_scan_and_grab() - before accessing any drives again. - - In both cases you have to be aware that the desired drive might get - aquired in the meantime by another user resp. libburn process. - */ - - /* We already made our choice via command line. (default is 0) - So we just have to keep our desired drive and drop all others. - No other libburn instance will have a chance to steal our drive. - */ - if (*driveno < 0) { - printf("Pseudo-drive \"-\" given : bus scanning done.\n"); - return 2; /* the program will end after this */ - } - if (drive_count <= *driveno) { - fprintf(stderr, - "Found only %d drives. Number %d not available.\n", - drive_count, *driveno); - return 0; /* the program will end after this */ - } - - /* Drop all drives which we do not want to use */ - for (i = 0; i < drive_count; i++) { - if (i == *driveno) /* the one drive we want to keep */ - continue; - ret = burn_drive_info_forget(&(drive_list[i]),0); - if (ret != 1) - fprintf(stderr, "Cannot drop drive %d. Please report \"ret=%d\" to libburn-hackers@pykix.org\n", - i, ret); - else - printf("Dropped unwanted drive %d\n",i); - } - /* Make the one we want ready for blanking or burning */ - ret= burn_drive_grab(drive_list[*driveno].drive, 1); - if (ret != 1) - return 0; - drive_is_grabbed = 1; - return 1; -} - - -/** Makes a previously used CD-RW ready for thorough re-usal. - - To our knowledge it is hardly possible to abort an ongoing blank operation - because after start it is entirely handled by the drive. - So expect signal handling to wait the normal blanking timespan until it - can allow the process to end. External kill -9 will not help the drive. -*/ -int libburner_blank_disc(struct burn_drive *drive, int blank_fast) -{ - enum burn_disc_status disc_state; - struct burn_progress p; - double percent = 1.0; - - disc_state = burn_disc_get_status(drive); - printf( - "Drive media status: %d (see libburn/libburn.h BURN_DISC_*)\n", - disc_state); - if (current_profile == 0x13) { - ; /* formatted DVD-RW will get blanked to sequential state */ - } else if (disc_state == BURN_DISC_BLANK) { - fprintf(stderr, - "IDLE: Blank media detected. Will leave it untouched\n"); - return 2; - } else if (disc_state == BURN_DISC_FULL || - disc_state == BURN_DISC_APPENDABLE) { - ; /* this is what libburner is willing to blank */ - } else if (disc_state == BURN_DISC_EMPTY) { - fprintf(stderr,"FATAL: No media detected in drive\n"); - return 0; - } else { - fprintf(stderr, - "FATAL: Unsuitable drive and media state\n"); - return 0; - } - if(!burn_disc_erasable(drive)) { - fprintf(stderr, - "FATAL : Media is not of erasable type\n"); - return 0; - } - printf( - "Beginning to %s-blank media.\n", (blank_fast?"fast":"full")); - burn_disc_erase(drive, blank_fast); - sleep(1); - while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) { - if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */ - percent = 1.0 + ((double) p.sector+1.0) - / ((double) p.sectors) * 98.0; - printf("Blanking ( %.1f%% done )\n", percent); - sleep(1); - } - printf("Done\n"); - return 1; -} - - -/** 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. - - 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. -*/ -int libburner_format_owrt(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"); - return 0; - } - - printf("Beginning to format media.\n"); - burn_disc_format(drive, size, format_flag); - - sleep(1); - while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) { - if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */ - percent = 1.0 + ((double) p.sector+1.0) - / ((double) p.sectors) * 98.0; - printf("Formatting ( %.1f%% done )\n", percent); - sleep(1); - } - 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) { - fprintf(stderr, - "FATAL: Failed to change media profile to desired value\n"); - return 0; - } - return 1; -} - - -/** Brings preformatted track images (ISO 9660, audio, ...) onto media. - To make sure a data image is fully readable on any Linux machine, this - function adds 300 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. - - For simplicity, this function allows memory leaks in case of failure. - In apps which do not abort immediately, one should clean up better. -*/ -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_disc *target_disc; - struct burn_session *session; - struct burn_write_opts *burn_options; - enum burn_disc_status disc_state; - struct burn_track *track, *tracklist[99]; - struct burn_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; - - if (all_tracks_type != BURN_AUDIO) { - 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(); - session = burn_session_create(); - burn_disc_add_session(target_disc, session, BURN_POS_END); - - for (trackno = 0 ; trackno < source_adr_count; trackno++) { - tracklist[trackno] = track = burn_track_create(); - burn_track_define_data(track, 0, padding, 1, all_tracks_type); - - /* Open file descriptor to source of track data */ - adr = source_adr[trackno]; - fixed_size = 0; - if (adr[0] == '-' && adr[1] == 0) { - fd = 0; - } else { - fd = open(adr, O_RDONLY); - if (fd>=0) - if (fstat(fd,&stbuf)!=-1) - if((stbuf.st_mode&S_IFMT)==S_IFREG) - fixed_size = stbuf.st_size; - } - 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); - if (data_src == NULL) { - fprintf(stderr, - "FATAL: Could not open data source '%s'.\n",adr); - if(errno!=0) - fprintf(stderr,"(Most recent system error: %s )\n", - 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"); - 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 */ - disc_state = burn_disc_get_status(drive); - if (disc_state != BURN_DISC_BLANK && - disc_state != BURN_DISC_APPENDABLE) { - if (disc_state == BURN_DISC_FULL) { - fprintf(stderr, "FATAL: Closed media with data detected. Need blank or appendable media.\n"); - if (burn_disc_erasable(drive)) - fprintf(stderr, "HINT: Try --blank_fast\n\n"); - } else if (disc_state == BURN_DISC_EMPTY) - fprintf(stderr,"FATAL: No media detected in drive\n"); - else - fprintf(stderr, - "FATAL: Cannot recognize state of drive and media\n"); - return 0; - } - - burn_options = burn_write_opts_new(drive); - burn_write_opts_set_perform_opc(burn_options, 0); - burn_write_opts_set_multi(burn_options, !!multi); - if(simulate_burn) - printf("\n*** Will TRY to SIMULATE burning ***\n\n"); - burn_write_opts_set_simulate(burn_options, simulate_burn); - burn_drive_set_speed(drive, 0, 0); - burn_write_opts_set_underrun_proof(burn_options, 1); - if (burn_write_opts_auto_write_type(burn_options, target_disc, - reasons, 0) == BURN_WRITE_NONE) { - fprintf(stderr, "FATAL: Failed to find a suitable write mode with this media.\n"); - fprintf(stderr, "Reasons given:\n%s\n", reasons); - return 0; - } - - printf("Burning starts. With e.g. 4x media expect up to a minute of zero progress.\n"); - start_time = time(0); - burn_disc_write(burn_options, target_disc); - - burn_write_opts_free(burn_options); - while (burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING) - usleep(100002); - 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)) - printf( - "Thank you for being patient since %d seconds.", - (int) (time(0) - start_time)); - else if(unpredicted_size) - printf("Track %d : sector %d", progress.track+1, - progress.sector); - else - printf("Track %d : sector %d of %d",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]); - 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 */ - printf("NOTE: Media left appendable.\n"); - if (simulate_burn) - printf("\n*** Did TRY to SIMULATE burning ***\n\n"); - return 1; -} - - -/** The setup parameters of libburner */ -static char drive_adr[BURN_DRIVE_ADR_LEN] = {""}; -static int driveno = 0; -static int do_blank = 0; -static char source_adr[99][4096]; -static int source_adr_count = 0; -static int do_multi = 0; -static int simulate_burn = 0; -static int all_tracks_type = BURN_MODE1; - - -/** Converts command line arguments into above setup parameters. -*/ -int libburner_setup(int argc, char **argv) -{ - int i, insuffient_parameters = 0, print_help = 0; - - for (i = 1; i < argc; ++i) { - if (!strcmp(argv[i], "--audio")) { - all_tracks_type = BURN_AUDIO; - - } else if (!strcmp(argv[i], "--blank_fast")) { - do_blank = 1; - - } else if (!strcmp(argv[i], "--blank_full")) { - do_blank = 2; - - } else if (!strcmp(argv[i], "--burn_for_real")) { - simulate_burn = 0; - - } else if (!strcmp(argv[i], "--drive")) { - ++i; - if (i >= argc) { - fprintf(stderr,"--drive requires an argument\n"); - return 1; - } else if (strcmp(argv[i], "-") == 0) { - drive_adr[0] = 0; - driveno = -1; - } else if (isdigit(argv[i][0])) { - drive_adr[0] = 0; - driveno = atoi(argv[i]); - } else { - if(strlen(argv[i]) >= BURN_DRIVE_ADR_LEN) { - fprintf(stderr,"--drive address too long (max. %d)\n", - BURN_DRIVE_ADR_LEN-1); - return 2; - } - strcpy(drive_adr, argv[i]); - } - } else if (!strcmp(argv[i], "--format_overwrite")) { - do_blank = 101; - - } else if (!strcmp(argv[i], "--multi")) { - do_multi = 1; - - } else if (!strcmp(argv[i], "--stdin_size")) { /* obsoleted */ - i++; - - } else if (!strcmp(argv[i], "--try_to_simulate")) { - simulate_burn = 1; - - } else if (!strcmp(argv[i], "--help")) { - print_help = 1; - - } else if (!strncmp(argv[i], "--",2)) { - fprintf(stderr, "Unidentified option: %s\n", argv[i]); - return 7; - } else { - if(strlen(argv[i]) >= 4096) { - fprintf(stderr, "Source address too long (max. %d)\n", 4096-1); - return 5; - } - if(source_adr_count >= 99) { - fprintf(stderr, "Too many tracks (max. 99)\n"); - return 6; - } - strcpy(source_adr[source_adr_count], argv[i]); - source_adr_count++; - } - } - insuffient_parameters = 1; - if (driveno < 0) - insuffient_parameters = 0; - if (source_adr_count > 0) - insuffient_parameters = 0; - if (do_blank) - insuffient_parameters = 0; - if (print_help || insuffient_parameters ) { - printf("Usage: %s\n", argv[0]); - printf(" [--drive <address>|<driveno>|\"-\"] [--audio]\n"); - printf(" [--blank_fast|--blank_full|--format_overwrite]\n"); - printf(" [--try_to_simulate]\n"); - printf(" [--multi] [<one or more imagefiles>|\"-\"]\n"); - printf("Examples\n"); - printf("A bus scan (needs rw-permissions to see a drive):\n"); - printf(" %s --drive -\n",argv[0]); - printf("Burn a file to drive chosen by number, leave appendable:\n"); - printf(" %s --drive 0 --multi my_image_file\n", argv[0]); - printf("Burn a file to drive chosen by persistent address, close:\n"); - printf(" %s --drive /dev/hdc my_image_file\n", argv[0]); - printf("Blank a used CD-RW (is combinable with burning in one run):\n"); - printf(" %s --drive /dev/hdc --blank_fast\n",argv[0]); - printf("Blank a used DVD-RW (is combinable with burning in one run):\n"); - printf(" %s --drive /dev/hdc --blank_full\n",argv[0]); - printf("Format a DVD-RW to avoid need for blanking before re-use:\n"); - printf(" %s --drive /dev/hdc --format_overwrite\n", argv[0]); - printf("Burn two audio tracks (to CD only):\n"); - printf(" lame --decode -t /path/to/track1.mp3 track1.cd\n"); - printf(" test/dewav /path/to/track2.wav -o track2.cd\n"); - printf(" %s --drive /dev/hdc --audio track1.cd track2.cd\n", argv[0]); - printf("Burn a compressed afio archive on-the-fly:\n"); - printf(" ( cd my_directory ; find . -print | afio -oZ - ) | \\\n"); - printf(" %s --drive /dev/hdc -\n", argv[0]); - printf("To be read from *not mounted* media via: afio -tvZ /dev/hdc\n"); - if (insuffient_parameters) - return 6; - } - return 0; -} - - -int main(int argc, char **argv) -{ - int ret; - - ret = libburner_setup(argc, argv); - if (ret) - exit(ret); - - printf("Initializing libburnia-project.org ...\n"); - if (burn_initialize()) - printf("Done\n"); - else { - printf("FAILED\n"); - fprintf(stderr,"\nFATAL: Failed to initialize.\n"); - exit(33); - } - - /* Print messages of severity SORRY or more directly to stderr */ - burn_msgs_set_severities("NEVER", "SORRY", "libburner : "); - - /* Activate the default signal handler which eventually will try to - properly shutdown drive and library on aborting events. */ - burn_set_signal_handling("libburner : ", NULL, 0); - - /** Note: driveno might change its value in this call */ - ret = libburner_aquire_drive(drive_adr, &driveno); - if (ret<=0) { - fprintf(stderr,"\nFATAL: Failed to aquire drive.\n"); - { ret = 34; goto finish_libburn; } - } - if (ret == 2) - { ret = 0; goto release_drive; } - if (do_blank) { - if (do_blank > 100) - ret = libburner_format_owrt(drive_list[driveno].drive); - else - ret = libburner_blank_disc(drive_list[driveno].drive, - do_blank == 1); - if (ret<=0) - { ret = 36; goto release_drive; } - } - if (source_adr_count > 0) { - ret = libburner_payload(drive_list[driveno].drive, - source_adr, source_adr_count, - do_multi, simulate_burn, all_tracks_type); - if (ret<=0) - { ret = 38; goto release_drive; } - } - ret = 0; -release_drive:; - if (drive_is_grabbed) - burn_drive_release(drive_list[driveno].drive, 0); - -finish_libburn:; - /* This app does not bother to know about exact scan state. - Better to accept a memory leak here. We are done anyway. */ - /* burn_drive_info_free(drive_list); */ - - burn_finish(); - exit(ret); -} - - -/* License and copyright aspects: - -This all is provided under GPL. -Read. Try. Think. Play. Write yourself some code. Be free of my copyright. - -Be also invited to study the code of cdrskin/cdrskin.c et al. - - -Clarification in my name and in the name of Mario Danic, copyright holder -on toplevel of libburnia. To be fully in effect after the remaining other -copyrighted code has been replaced by ours and by copyright-free contributions -of our friends: - -We, the copyright holders, agree on the interpretation that -dynamical linking of our libraries constitutes "use of" and -not "derivation from" our work in the sense of GPL, provided -those libraries are compiled from our unaltered code. - -Thus you may link our libraries dynamically with applications -which are not under GPL. You may distribute our libraries and -application tools in binary form, if you fulfill the usual -condition of GPL to offer a copy of the source code -altered -or unaltered- under GPL. - -We ask you politely to use our work in open source spirit -and with the due reference to the entire open source community. - -If there should really arise the case where above clarification -does not suffice to fulfill a clear and neat request in open source -spirit that would otherwise be declined for mere formal reasons, -only in that case we will duely consider to issue a special license -covering only that special case. -It is the open source idea of responsible freedom which will be -decisive and you will have to prove that you exhausted all own -means to qualify for GPL. - -For now we are firmly committed to maintain one single license: GPL. - -History: -libburner is a compilation of my own contributions to test/burniso.c and -fresh code which replaced the remaining parts under copyright of -Derek Foreman. -My respect and my thanks to Derek for providing me a start back in 2005. - -*/ - diff --git a/test/open-cd-excl.c b/test/open-cd-excl.c deleted file mode 100644 index fffe4d0..0000000 --- a/test/open-cd-excl.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * open-cd-excl.c --- This program tries to open a block device - * by various exclusive and non-exclusive gestures in order to explore - * their impact on running CD/DVD recordings. - * - * Copyright 2007, by Theodore Ts'o. - * - * Detail modifications 2007, by Thomas Schmitt. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#define _GNU_SOURCE /* for O_LARGEFILE *//*ts A70417: or _LARGEFILE64_SOURCE */ - -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <stdlib.h> -#include <fcntl.h> -#include <getopt.h> - -const char *progname; - -static void usage(void) -{ - fprintf(stderr, "Usage: %s [-feirw] device\n", progname); - exit(1); -} - -/* ts A70417: added parameter do_rdwr */ -static void init_flock(struct flock *fl, int do_rdwr) -{ - memset(fl, 0, sizeof(struct flock)); - if (do_rdwr) - fl->l_type = F_WRLCK; - else - fl->l_type = F_RDLCK; - fl->l_whence = SEEK_SET; - fl->l_start = 0; - fl->l_len = 0; -} - -int main(int argc, char **argv) -{ - struct flock fl; - char *device_name; - int fd, c, f_opt = 0, do_rdwr = 0, end_immediately = 0; - int flags = O_NONBLOCK|O_LARGEFILE; - - progname = argv[0]; - - /* ts A70417: added -w , -r , -i */ - while ((c = getopt (argc, argv, "feirw")) != EOF) { - switch (c) { - case 'e': - flags |= O_EXCL; - break; - case 'f': - f_opt++; - break; - case 'i': - end_immediately = 1; - break; - case 'r': - do_rdwr = 0; - break; - case 'w': - do_rdwr = 1; - break; - case '?': - usage(); - exit(1); - } - } - - if (optind == argc) - usage(); - device_name = argv[optind++]; - - /* ts A70417 : made read-write adjustable independently of f_opt */ - if (do_rdwr) { - flags |= O_RDWR; - printf("Using O_RDWR\n"); - } else { - flags |= O_RDONLY; - printf("Using O_RDONLY\n"); - } - - if (flags & O_EXCL) - printf("Trying to open %s with O_EXCL ...\n", device_name); - fd = open(device_name, flags, 0); - if (fd < 0) { - perror("open"); - printf("failed\n"); - exit(1); - } - if (flags & O_EXCL) - printf("succeeded\n"); - - if (f_opt) { - init_flock(&fl, do_rdwr); - if (fcntl(fd, F_GETLK, &fl) < 0) { - perror("fcntl: F_GETLK: "); - exit(1); - } - printf("fcntl lock apparently %sLOCKED\n", - (fl.l_type == F_UNLCK) ? "NOT " : ""); - - init_flock(&fl, do_rdwr); - printf("Trying to grab fcntl lock...\n"); - if (fcntl(fd, F_SETLK, &fl) < 0) { - perror("fcntl: F_SETLK: "); - printf("failed\n"); - exit(1); - } - printf("succeeded\n"); - } - - /* ts A70417: added end_immediately */ - printf("Holding %s open.\n", device_name); - usleep(100000); - if (end_immediately) - exit(0); - printf("Press ^C to exit.\n"); - while (1) { - sleep(300); - } - /* NOTREACHED */ - return 0; -} diff --git a/test/poll.c b/test/poll.c deleted file mode 100644 index cd22f15..0000000 --- a/test/poll.c +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ - -#include "libburn/libburn.h" -#include "libburn/toc.h" -#include "libburn/mmc.h" - -#include <unistd.h> -#include <stdio.h> -#include <signal.h> -#include <assert.h> - -static struct burn_drive_info *drives; -static unsigned int n_drives; -int NEXT; - -static void catch_int () -{ - NEXT = 1; -} - -static void poll_drive(int d) -{ - enum burn_disc_status s; - - fprintf(stderr, "polling disc in %s - %s:\n", - drives[d].vendor, drives[d].product); - - if (!burn_drive_grab(drives[d].drive, 1)) { - fprintf(stderr, "Unable to open the drive!\n"); - return; - } - - while (burn_drive_get_status(drives[d].drive, NULL)) - usleep(1000); - - while ((s = burn_disc_get_status(drives[d].drive)) - == BURN_DISC_UNREADY) - usleep(1000); - - while (NEXT == 0) { - sleep(2); - mmc_get_event(drives[d].drive); - } - burn_drive_release(drives[d].drive, 0); -} - -int main() -{ - int i; - struct sigaction newact; - struct sigaction oldact; - fprintf(stderr, "Initializing library..."); - if (burn_initialize()) - fprintf(stderr, "Success\n"); - else { - printf("Failed\n"); - return 1; - } - - fprintf(stderr, "Scanning for devices..."); - while (!burn_drive_scan(&drives, &n_drives)) ; - fprintf(stderr, "Done\n"); - if (!drives) { - printf("No burner found\n"); - return 1; - } - - newact.sa_handler = catch_int; - sigaction(SIGINT, &newact, &oldact); - for (i = 0; i < n_drives; i++) { - NEXT=0; - poll_drive(i); - } - sigaction(SIGINT, &oldact, NULL); - burn_drive_info_free(drives); - burn_finish(); - return 0; -} diff --git a/test/structest.c b/test/structest.c deleted file mode 100644 index defa274..0000000 --- a/test/structest.c +++ /dev/null @@ -1,48 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <libburn/libburn.h> - -int main(int argc, char **argv) -{ - int i; - const char *path; - struct burn_track *track; - struct burn_disc *disc; - struct burn_session *session; - struct burn_source *src; - - disc = burn_disc_create(); - session = burn_session_create(); - burn_disc_add_session(disc, session, BURN_POS_END); - - /* Define a source for all of the tracks */ - path = strdup("/etc/hosts"); - src = burn_file_source_new(path, NULL); - - /* Add ten tracks to a session */ - for (i = 0; i < 10; i++) { - track = burn_track_create(); - burn_session_add_track(session, track, 0); - if (burn_track_set_source(track, src) != BURN_SOURCE_OK) { - printf("problem with the source\n"); - return 0; - } - } - - /* Add ten tracks to a session */ - for (i = 0; i < 10; i++) { - track = burn_track_create(); - burn_session_add_track(session, track, 0); - if (burn_track_set_source(track, src) != BURN_SOURCE_OK) { - printf("problem with the source\n"); - return 0; - } - } - - /* Delete a session */ - burn_session_remove_track(session, track); - - burn_structure_print_disc(disc); - return EXIT_SUCCESS; -} diff --git a/test/telltoc.c b/test/telltoc.c deleted file mode 100644 index 63f4089..0000000 --- a/test/telltoc.c +++ /dev/null @@ -1,921 +0,0 @@ - -/* test/telltoc.c , API illustration of obtaining media status info */ -/* Copyright (C) 2006 - 2007 Thomas Schmitt <scdbackup@gmx.net> - Provided under GPL version 2 */ - -/** 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 - 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 - to serve the libburn team as reference application. telltoc.c does indeed - define the standard way how above gestures can be implemented and stay upward - compatible for a good while. - - Before you can do anything, you have to initialize libburn by - burn_initialize() - as it is done in main() at the end of this file. Then you aquire a - drive in an appropriate way conforming to the API. The two main - approaches are shown here in application functions: - telltoc_aquire_by_adr() demonstrates usage as of cdrecord traditions - telltoc_aquire_by_driveno() demonstrates a scan-and-choose approach - With that aquired drive you can call - 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() - -*/ - -/** See this for the decisive API specs . libburn.h is The Original */ -/* For using the installed header file : #include <libburn/libburn.h> */ -/* This program insists in the own headerfile. */ -#include "../libburn/libburn.h" - -/* libburn is intended for Linux systems with kernel 2.4 or 2.6 for now */ -#include <stdio.h> -#include <ctype.h> -#include <sys/types.h> -#include <unistd.h> -#include <string.h> -#include <stdlib.h> -#include <time.h> -#include <errno.h> -#include <sys/stat.h> -#include <fcntl.h> - - -/** For simplicity i use global variables to represent the drives. - Drives are systemwide global, so we do not give away much of good style. -*/ - -/** This list will hold the drives known to libburn. This might be all CD - drives of the system and thus might impose severe impact on the system. -*/ -static struct burn_drive_info *drive_list; - -/** If you start a long lasting operation with drive_count > 1 then you are - not friendly to the users of other drives on those systems. Beware. */ -static unsigned int drive_count; - -/** This variable indicates wether the drive is grabbed and must be - finally released */ -static int drive_is_grabbed = 0; - - -/* Some in-advance definitions to allow a more comprehensive ordering - of the functions and their explanations in here */ -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 - compact call and alternatively as application controllable gestures of - whitelisting, scanning for drives and finally grabbing one of them. - - If you have a persistent address of the drive, then the compact call is - to prefer because it only touches one drive. On modern Linux kernels, - there should be no fatal disturbance of ongoing burns of other libburn - instances with any of our approaches. We use open(O_EXCL) by default. - On /dev/hdX it should cooperate with growisofs and some cdrecord variants. - On /dev/sgN versus /dev/scdM expect it not to respect other programs. -*/ -int telltoc_aquire_drive(char *drive_adr, int *driveno, int silent_drive) -{ - int ret; - - if(drive_adr != NULL && drive_adr[0] != 0) - ret = telltoc_aquire_by_adr(drive_adr); - else - ret = telltoc_aquire_by_driveno(driveno, silent_drive); - return ret; -} - - -/** 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", - drive_adr); - return 0; - } - - /* <<< 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); - - if (ret <= 0) { - fprintf(stderr,"FAILURE with persistent drive address '%s'\n", - libburn_drive_adr); - } else { - fprintf(stderr,"Done\n"); - drive_is_grabbed = 1; - } - - /* <<< ts A70907 FOR TESTING ONLY ! - burn_drive_info_free(test_drive_list); - */ - - return ret; -} - - -/** This method demonstrates how to use libburn without knowing a persistent - drive address in advance. It has to make sure that after assessing the list - of available drives, all unwanted drives get closed again. As long as they - are open, no other libburn instance can see them. This is an intended - locking feature. The application is responsible for giving up the locks - by either burn_drive_release() (only after burn_drive_grab() !), - burn_drive_info_forget(), burn_drive_info_free(), or burn_finish(). - @param driveno the index number in libburn's drive list. This will get - set to 0 on success and will then be the drive index to - use in the further dourse of processing. - @param silent_drive 1=do not print "Drive found :" line with *driveno >= 0 - @return 1 success , <= 0 failure -*/ -int telltoc_aquire_by_driveno(int *driveno, int silent_drive) -{ - char adr[BURN_DRIVE_ADR_LEN]; - int ret, i; - - fprintf(stderr, "Beginning to scan for devices ...\n"); - while (!burn_drive_scan(&drive_list, &drive_count)) - usleep(100002); - if (drive_count <= 0 && *driveno >= 0) { - fprintf(stderr, "FAILED (no drives found)\n"); - return 0; - } - fprintf(stderr, "Done\n"); - - for (i = 0; i < drive_count; i++) { - if (*driveno >= 0 && (silent_drive || *driveno != i)) - continue; - if (burn_drive_get_adr(&(drive_list[i]), adr) <=0) - strcpy(adr, "-get_adr_failed-"); - printf("Drive found : %d --drive '%s' : ", i,adr); - printf("%-8s %-16s (%4s)\n", - drive_list[i].vendor,drive_list[i].product, - drive_list[i].revision); - } - if (*driveno < 0) { - fprintf(stderr, - "Pseudo-drive \"-\" given : bus scanning done.\n"); - return 2; /* the program will end after this */ - } - - /* We already made our choice via command line. (default is 0) - So we just have to keep our desired drive and drop all others. - */ - if (drive_count <= *driveno) { - fprintf(stderr, - "Found only %d drives. Number %d not available.\n", - drive_count, *driveno); - return 0; /* the program will end after this */ - } - - /* Drop all drives which we do not want to use */ - for (i = 0; i < drive_count; i++) { - if (i == *driveno) /* the one drive we want to keep */ - continue; - ret = burn_drive_info_forget(&(drive_list[i]),0); - if (ret != 1) - fprintf(stderr, "Cannot drop drive %d. Please report \"ret=%d\" to libburn-hackers@pykix.org\n", - i, ret); - else - fprintf(stderr, "Dropped unwanted drive %d\n",i); - } - /* Make the one we want ready for inquiry */ - ret= burn_drive_grab(drive_list[*driveno].drive, 1); - if (ret != 1) - return 0; - drive_is_grabbed = 1; - return 1; -} - - -/** This gesture is necessary to get my NEC DVD_RW ND-4570A out of a state - of noisy overexcitement after its tray was loaded and it then was inquired - for Next Writeable Address. - The noise then still lasts 20 seconds. Same with cdrecord -toc, btw. - This opens a small gap for losing the drive to another libburn instance. - Not a problem in telltoc. This is done as very last drive operation. - Eventually the other libburn instance will have the same sanitizing effect. -*/ -int telltoc_regrab(struct burn_drive *drive) { - int ret; - - if (drive_is_grabbed) - burn_drive_release(drive, 0); - drive_is_grabbed = 0; - ret = burn_drive_grab(drive, 0); - if (ret != 0) { - drive_is_grabbed = 1; - } - return !!ret; -} - - -int telltoc_media(struct burn_drive *drive) -{ - int ret, media_found = 0, profile_no = -1; - double max_speed = 0.0, min_speed = 0.0, speed_conv; - off_t available = 0; - enum burn_disc_status s; - char profile_name[80], speed_unit[40]; - struct burn_multi_caps *caps; - struct burn_write_opts *o = NULL; - - printf("Media current: "); - ret = burn_disc_get_profile(drive, &profile_no, profile_name); - if (profile_no > 0 && ret > 0) { - if (profile_name[0]) - printf("%s\n", profile_name); - else - printf("%4.4Xh\n", profile_no); - } else - printf("is not recognizable\n"); - - speed_conv = 176.4; - strcpy(speed_unit,"176.4 kB/s (CD, data speed 150 KiB/s)"); - if (strstr(profile_name, "DVD") == profile_name) { - speed_conv = 1385.0; - strcpy(speed_unit,"1385.0 kB/s (DVD)"); - } - - /* >>> libburn does not obtain full profile list yet */ - - printf("Media status : "); - s = burn_disc_get_status(drive); - if (s == BURN_DISC_FULL) { - printf("is written , is closed\n"); - media_found = 1; - } else if (s == BURN_DISC_APPENDABLE) { - printf("is written , is appendable\n"); - media_found = 1; - } else if (s == BURN_DISC_BLANK) { - printf("is blank\n"); - media_found = 1; - } else if (s == BURN_DISC_EMPTY) - printf("is not present\n"); - else - printf("is not recognizable\n"); - - printf("Media reuse : "); - if (media_found) { - if (burn_disc_erasable(drive)) - printf("is erasable\n"); - else - printf("is not erasable\n"); - } else - printf("is not recognizable\n"); - - ret = burn_disc_get_multi_caps(drive, BURN_WRITE_NONE, &caps, 0); - if (ret > 0) { - /* Media appears writeable */ - printf("Write multi : "); - printf("%s multi-session , ", - caps->multi_session == 1 ? "allows" : "prohibits"); - if (caps->multi_track) - printf("allows multiple tracks\n"); - else - printf("enforces single track\n"); - printf("Write start : "); - if (caps->start_adr == 1) - printf( - "allows addresses [%.f , %.f]s , alignment=%.fs\n", - (double) caps->start_range_low / 2048 , - (double) caps->start_range_high / 2048 , - (double) caps->start_alignment / 2048 ); - else - printf("prohibits write start addressing\n"); - printf("Write modes : "); - if (caps->might_do_tao) - printf("TAO%s", - caps->advised_write_mode == BURN_WRITE_TAO ? - " (advised)" : ""); - if (caps->might_do_sao) - printf("%sSAO%s", - caps->might_do_tao ? " , " : "", - caps->advised_write_mode == BURN_WRITE_SAO ? - " (advised)" : ""); - if (caps->might_do_raw) - printf("%sRAW%s", - caps->might_do_tao | caps->might_do_sao ? - " , " : "", - caps->advised_write_mode == BURN_WRITE_RAW ? - " (advised)" : ""); - printf("\n"); - printf("Write dummy : "); - if (caps->might_simulate) - printf("supposed to work with non-RAW modes\n"); - else - printf("will not work\n"); - o= burn_write_opts_new(drive); - if (o != NULL) { - burn_write_opts_set_perform_opc(o, 0); - if(caps->advised_write_mode == BURN_WRITE_TAO) - burn_write_opts_set_write_type(o, - BURN_WRITE_TAO, BURN_BLOCK_MODE1); - else if (caps->advised_write_mode == BURN_WRITE_SAO) - burn_write_opts_set_write_type(o, - BURN_WRITE_SAO, BURN_BLOCK_SAO); - else { - burn_write_opts_free(o); - o = NULL; - } - } - available = burn_disc_available_space(drive, o); - printf("Write space : %.1f MiB (%.fs)\n", - ((double) available) / 1024.0 / 1024.0, - ((double) available) / 2048.0); - burn_disc_free_multi_caps(&caps); - if (o != NULL) - burn_write_opts_free(o); - } - - ret = burn_drive_get_write_speed(drive); - max_speed = ((double ) ret) / speed_conv; - ret = burn_drive_get_min_write_speed(drive); - min_speed = ((double ) ret) / speed_conv; - if (!media_found) - printf("Drive speed : max=%.1f , min=%.1f\n", - max_speed, min_speed); - else - printf("Avail. speed : max=%.1f , min=%.1f\n", - max_speed, min_speed); - - ret = 0; - if (media_found) - ret = burn_disc_read_atip(drive); - if(ret>0) { - ret = burn_drive_get_min_write_speed(drive); - min_speed = ((double ) ret) / speed_conv; - ret = burn_drive_get_write_speed(drive); - max_speed = ((double ) ret) / speed_conv; - printf("Media speed : max=%.1f , min=%.1f\n", - max_speed, min_speed); - } - printf("Speed unit 1x: %s\n", speed_unit); - - return 1; -} - - -int telltoc_speedlist(struct burn_drive *drive) -{ - int ret, has_modern_entries = 0; - struct burn_speed_descriptor *speed_list, *sd; - - ret = burn_drive_get_speedlist(drive, &speed_list); - if (ret <= 0) { - fprintf(stderr, "SORRY: Cannot obtain speed list info\n"); - return 2; - } - for (sd = speed_list; sd != NULL; sd = sd->next) - if (sd->source == 2) - has_modern_entries = 1; - for (sd = speed_list; sd != NULL; sd = sd->next) { - if (has_modern_entries && sd->source < 2) - continue; - if (sd->write_speed <= 0) - continue; - printf("Speed descr. : %d kB/s", sd->write_speed); - if (sd->end_lba >= 0) - printf(", %.1f MiB", ((double) sd->end_lba) / 512.0); - if (sd->profile_name[0]) - printf(", %s", sd->profile_name); - printf("\n"); - } - burn_drive_free_speedlist(&speed_list); - return 1; -} - - -int telltoc_formatlist(struct burn_drive *drive) -{ - int ret, i, status, num_formats, profile_no, type; - off_t size; - unsigned dummy; - char status_text[80], profile_name[90]; - - ret = burn_disc_get_formats(drive, &status, &size, &dummy, - &num_formats); - if (ret <= 0) { - fprintf(stderr, "SORRY: Cannot obtain format list info\n"); - return 2; - } - if (status == BURN_FORMAT_IS_UNFORMATTED) - sprintf(status_text, "unformatted, up to %.1f MiB", - ((double) size) / 1024.0 / 1024.0); - else if(status == BURN_FORMAT_IS_FORMATTED) - sprintf(status_text, "formatted, with %.1f MiB", - ((double) size) / 1024.0 / 1024.0); - else if(status == BURN_FORMAT_IS_UNKNOWN) { - burn_disc_get_profile(drive, &profile_no, profile_name); - if (profile_no > 0) - sprintf(status_text, "intermediate or unknown"); - else - sprintf(status_text, "no media or unknown media"); - } else - sprintf(status_text, "illegal status according to MMC-5"); - printf("Format status: %s\n", status_text); - - for (i = 0; i < num_formats; i++) { - ret = burn_disc_get_format_descr(drive, i, - &type, &size, &dummy); - if (ret <= 0) - continue; - printf("Format descr.: %2.2Xh , %.1f MiB (%.fs)\n", - type, ((double) size) / 1024.0 / 1024.0, - ((double) size) / 2048.0); - } - return 1; -} - - -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 session_no, track_no; - char profile_name[80]; - struct burn_disc *disc= NULL; - struct burn_session **sessions; - struct burn_track **tracks; - struct burn_toc_entry toc_entry; - - disc = burn_drive_get_disc(drive); - if (disc==NULL) { - fprintf(stderr, "SORRY: Cannot obtain Table Of Content\n"); - return 2; - } - sessions = burn_disc_get_sessions(disc, &num_sessions); - for (session_no = 0; session_no<num_sessions; session_no++) { - tracks = burn_session_get_tracks(sessions[session_no], - &num_tracks); - if (tracks==NULL) - continue; - for(track_no= 0; track_no<num_tracks; track_no++) { - track_count++; - burn_track_get_entry(tracks[track_no], &toc_entry); - if (toc_entry.extensions_valid & 1) { - /* DVD extension valid */ - lba = toc_entry.start_lba; - burn_lba_to_msf(lba, &pmin, &psec, &pframe); - } else { - pmin = toc_entry.pmin; - psec = toc_entry.psec; - pframe = toc_entry.pframe; - lba= burn_msf_to_lba(pmin, psec, pframe); - } - printf("Media content: session %2d ", session_no+1); - printf("track %2d %s lba: %9d %4.2d:%2.2d:%2.2d\n", - 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); - if (toc_entry.extensions_valid & 1) { - lba = toc_entry.start_lba; - burn_lba_to_msf(lba, &pmin, &psec, &pframe); - } else { - pmin = toc_entry.pmin; - psec = toc_entry.psec; - pframe = toc_entry.pframe; - lba= burn_msf_to_lba(pmin, psec, pframe); - } - 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); - return 1; -} - - -int telltoc_msinfo(struct burn_drive *drive, - int msinfo_explicit, int msinfo_alone) -{ - int ret, lba, nwa = -123456789, aux_lba; - enum burn_disc_status s; - struct burn_write_opts *o= NULL; - - s = burn_disc_get_status(drive); - if (s!=BURN_DISC_APPENDABLE) { - if (!msinfo_explicit) - return 2; - fprintf(stderr, - "SORRY: --msinfo can only operate on appendable media.\n"); - return 0; - } - - /* man mkisofs , option -C : - The first number is the sector number of the first sector in - the last session of the disk that should be appended to. - */ - ret = burn_disc_get_msc1(drive, &lba); - if (ret <= 0) { - fprintf(stderr, - "SORRY: Cannot obtain start address of last session\n"); - { ret = 0; goto ex; } - } - - /* man mkisofs , option -C : - The second number is the starting sector number of the new session. - */ - /* Set some roughly suitable write opts to be sent to drive. */ - o= burn_write_opts_new(drive); - if(o!=NULL) { - burn_write_opts_set_perform_opc(o, 0); - burn_write_opts_set_write_type(o, - BURN_WRITE_TAO, BURN_BLOCK_MODE1); - } - /* Now try to inquire nwa from drive */ - ret= burn_disc_track_lba_nwa(drive,o,0,&aux_lba,&nwa); - telltoc_regrab(drive); /* necessary to calm down my NEC drive */ - if(ret<=0) { - fprintf(stderr, - "SORRY: Cannot obtain next writeable address\n"); - { ret = 0; goto ex; } - } - - if (!msinfo_alone) - printf("Media msinfo : mkisofs ... -C "); - printf("%d,%d\n",lba,nwa); - ret = 1; -ex:; - if (o != NULL) - burn_write_opts_free(o); - return ret; -} - - -/** - @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; -static int do_media = 0; -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. - drive_adr[] must provide at least BURN_DRIVE_ADR_LEN bytes. - source_adr[] must provide at least 4096 bytes. -*/ -int telltoc_setup(int argc, char **argv) -{ - int i; - - for (i = 1; i < argc; ++i) { - if (!strcmp(argv[i], "--drive")) { - ++i; - if (i >= argc) { - fprintf(stderr,"--drive requires an argument\n"); - return 1; - } else if (strcmp(argv[i], "-") == 0) { - drive_adr[0] = 0; - driveno = -1; - } else if (isdigit(argv[i][0])) { - drive_adr[0] = 0; - driveno = atoi(argv[i]); - } else { - if(strlen(argv[i]) >= BURN_DRIVE_ADR_LEN) { - fprintf(stderr,"--drive address too long (max. %d)\n", - BURN_DRIVE_ADR_LEN-1); - return 2; - } - strcpy(drive_adr, argv[i]); - } - } else if (strcmp(argv[i],"--media")==0) { - do_media = 1; - - } else if (!strcmp(argv[i], "--msinfo")) { - do_msinfo = 1; - - } else if (!strcmp(argv[i], "--capacities")) { - do_capacities = 1; - - } 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; - - } else { - fprintf(stderr, "Unidentified option: %s\n", argv[i]); - return 7; - } - } - if (argc==1) - print_help = 1; - if (print_help) { - 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]); - printf("Obtain info about the type of loaded media:\n"); - printf(" %s --drive /dev/hdc --media\n",argv[0]); - printf("Obtain table of content:\n"); - printf(" %s --drive /dev/hdc --toc\n",argv[0]); - printf("Obtain parameters for option -C of program mkisofs:\n"); - printf(" msinfo=$(%s --drive /dev/hdc --msinfo 2>/dev/null)\n", - argv[0]); - 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; -} - - -int main(int argc, char **argv) -{ - int ret, toc_failed = 0, msinfo_alone = 0, msinfo_explicit = 0; - int full_default = 0; - - ret = telltoc_setup(argc, argv); - if (ret) - exit(ret); - - /* Behavior shall be different if --msinfo is only option */ - if (do_msinfo) { - msinfo_explicit = 1; - if (!(do_media || do_toc)) - 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(print_help) - exit(0); - full_default = do_media = do_msinfo = do_capacities= do_toc= 1; - } - - fprintf(stderr, "Initializing libburnia-project.org ...\n"); - if (burn_initialize()) - fprintf(stderr, "Done\n"); - else { - fprintf(stderr,"\nFATAL: Failed to initialize.\n"); - 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); - - /** Note: driveno might change its value in this call */ - ret = telltoc_aquire_drive(drive_adr, &driveno, !full_default); - if (ret<=0) { - fprintf(stderr,"\nFATAL: Failed to aquire drive.\n"); - { ret = 34; goto finish_libburn; } - } - if (ret == 2) - { ret = 0; goto release_drive; } - - if (do_media) { - ret = telltoc_media(drive_list[driveno].drive); - if (ret<=0) - {ret = 36; goto release_drive; } - } - if (do_capacities) { - ret = telltoc_speedlist(drive_list[driveno].drive); - if (ret<=0) - {ret = 39; goto release_drive; } - ret = telltoc_formatlist(drive_list[driveno].drive); - if (ret<=0) - {ret = 39; goto release_drive; } - } - if (do_toc) { - ret = telltoc_toc(drive_list[driveno].drive); - if (ret<=0) - {ret = 37; goto release_drive; } - if (ret==2) - toc_failed = 1; - } - if (do_msinfo) { - ret = telltoc_msinfo(drive_list[driveno].drive, - msinfo_explicit, msinfo_alone); - 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) - ret = 37; -release_drive:; - if (drive_is_grabbed) - burn_drive_release(drive_list[driveno].drive, 0); - -finish_libburn:; - /* This app does not bother to know about exact scan state. - Better to accept a memory leak here. We are done anyway. */ - /* burn_drive_info_free(drive_list); */ - - burn_finish(); - exit(ret); -} - -/* License and copyright aspects: - See libburner.c -*/ - diff --git a/version.h.in b/version.h.in deleted file mode 100644 index 13ada99..0000000 --- a/version.h.in +++ /dev/null @@ -1,3 +0,0 @@ -#define BURN_MAJOR_VERSION @BURN_MAJOR_VERSION@ -#define BURN_MINOR_VERSION @BURN_MINOR_VERSION@ -#define BURN_MICRO_VERSION @BURN_MICRO_VERSION@