From 7058c87020ed3603be43d42d3ec61eca13d78d65 Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Sun, 11 May 2008 10:26:51 +0000 Subject: [PATCH] Tagged libburn-0.4.6 --- AUTHORS | 3 - CONTRIBUTORS | 6 - COPYING | 280 - COPYRIGHT | 18 - ChangeLog | 1 - INSTALL | 234 - Makefile.am | 202 - NEWS | 1 - README | 332 - acinclude.m4 | 22 - bootstrap | 10 - cdrskin/README | 481 -- cdrskin/add_ts_changes_to_libburn_0_4_6 | 244 - cdrskin/add_ts_changes_to_libburn_0_4_7 | 245 - cdrskin/cdrecord_spy.sh | 37 - cdrskin/cdrfifo.c | 1253 ---- cdrskin/cdrfifo.h | 171 - cdrskin/cdrskin.1 | 1334 ---- cdrskin/cdrskin.c | 8292 ----------------------- cdrskin/cdrskin_eng.html | 500 -- cdrskin/cdrskin_timestamp.h | 1 - cdrskin/changelog.txt | 5561 --------------- cdrskin/cleanup.c | 215 - cdrskin/cleanup.h | 34 - cdrskin/compile_cdrskin.sh | 216 - cdrskin/convert_man_to_html.sh | 78 - cdrskin/doener_150x200_tr.png | Bin 10595 -> 0 bytes cdrskin/doener_150x200_tr_octx.png | Bin 9433 -> 0 bytes cdrskin/make_timestamp.sh | 9 - cdrskin/wiki_plain.txt | 318 - configure.ac | 181 - doc/Makefile | 4 - doc/comments | 180 - doc/cookbook.txt | 1201 ---- doc/ddlp.txt | 388 -- doc/doxygen.conf.in | 1300 ---- libburn-1.pc.in | 12 - libburn/Makefile | 4 - libburn/Makefile.am | 65 - libburn/asserts.txt | 792 --- libburn/async.c | 545 -- libburn/async.h | 14 - libburn/back_hacks.h | 54 - libburn/cleanup.c | 215 - libburn/cleanup.h | 34 - libburn/crc.c | 122 - libburn/crc.h | 9 - libburn/ddlpa.c | 614 -- libburn/ddlpa.h | 107 - libburn/debug.c | 35 - libburn/debug.h | 8 - libburn/drive.c | 2469 ------- libburn/drive.h | 128 - libburn/error.h | 8 - libburn/file.c | 542 -- libburn/file.h | 62 - libburn/init.c | 416 -- libburn/init.h | 21 - libburn/lec.c | 451 -- libburn/lec.h | 12 - libburn/libburn.h | 2369 ------- libburn/libdax_audioxtr.c | 326 - libburn/libdax_audioxtr.h | 229 - libburn/libdax_msgs.c | 439 -- libburn/libdax_msgs.h | 682 -- libburn/libdax_msgs_to_xyz_msgs.sh | 37 - libburn/mmc.c | 3494 ---------- libburn/mmc.h | 80 - libburn/null.c | 31 - libburn/null.h | 10 - libburn/options.c | 447 -- libburn/options.h | 100 - libburn/os-freebsd.h | 61 - libburn/os-linux.h | 76 - libburn/os.h | 34 - libburn/read.c | 490 -- libburn/read.h | 14 - libburn/sbc.c | 114 - libburn/sbc.h | 18 - libburn/sector.c | 846 --- libburn/sector.h | 35 - libburn/sg-freebsd-port.c | 631 -- libburn/sg-freebsd.c | 673 -- libburn/sg-linux.c | 1444 ---- libburn/sg.c | 17 - libburn/sg.h | 36 - libburn/source.c | 55 - libburn/source.h | 10 - libburn/spc.c | 997 --- libburn/spc.h | 62 - libburn/structure.c | 517 -- libburn/structure.h | 112 - libburn/toc.c | 141 - libburn/toc.h | 48 - libburn/transport.h | 361 - libburn/util.c | 60 - libburn/util.h | 8 - libburn/write.c | 2334 ------- libburn/write.h | 48 - libcevap/cgen.c | 1503 ---- libcevap/cgen.h | 35 - libcevap/cgen.txt | 222 - libcevap/ctyp.c | 364 - libcevap/ctyp.h | 41 - libcevap/extract_cgen_input.sh | 30 - libcevap/libcevap_gen.sh | 16 - libcevap/libdax_equip.gif | Bin 10751 -> 0 bytes libcevap/libdax_job.gif | Bin 10532 -> 0 bytes libcevap/libdax_model.txt | 944 --- libcevap/libdax_overview.gif | Bin 12521 -> 0 bytes libcevap/main.c | 39 - libcevap/smem.c | 445 -- libcevap/smem.h | 165 - test/Makefile | 4 - test/dewav.c | 215 - test/fake_au.c | 164 - test/libburner.c | 797 --- test/open-cd-excl.c | 133 - test/poll.c | 78 - test/structest.c | 48 - test/telltoc.c | 921 --- version.h.in | 3 - 122 files changed, 53744 deletions(-) delete mode 100644 AUTHORS delete mode 100644 CONTRIBUTORS delete mode 100644 COPYING delete mode 100644 COPYRIGHT delete mode 100644 ChangeLog delete mode 100644 INSTALL delete mode 100644 Makefile.am delete mode 100644 NEWS delete mode 100644 README delete mode 100644 acinclude.m4 delete mode 100755 bootstrap delete mode 100644 cdrskin/README delete mode 100755 cdrskin/add_ts_changes_to_libburn_0_4_6 delete mode 100755 cdrskin/add_ts_changes_to_libburn_0_4_7 delete mode 100755 cdrskin/cdrecord_spy.sh delete mode 100644 cdrskin/cdrfifo.c delete mode 100644 cdrskin/cdrfifo.h delete mode 100644 cdrskin/cdrskin.1 delete mode 100644 cdrskin/cdrskin.c delete mode 100644 cdrskin/cdrskin_eng.html delete mode 100644 cdrskin/cdrskin_timestamp.h delete mode 100644 cdrskin/changelog.txt delete mode 100644 cdrskin/cleanup.c delete mode 100644 cdrskin/cleanup.h delete mode 100755 cdrskin/compile_cdrskin.sh delete mode 100755 cdrskin/convert_man_to_html.sh delete mode 100644 cdrskin/doener_150x200_tr.png delete mode 100644 cdrskin/doener_150x200_tr_octx.png delete mode 100755 cdrskin/make_timestamp.sh delete mode 100644 cdrskin/wiki_plain.txt delete mode 100644 configure.ac delete mode 100644 doc/Makefile delete mode 100644 doc/comments delete mode 100644 doc/cookbook.txt delete mode 100644 doc/ddlp.txt delete mode 100644 doc/doxygen.conf.in delete mode 100644 libburn-1.pc.in delete mode 100644 libburn/Makefile delete mode 100644 libburn/Makefile.am delete mode 100644 libburn/asserts.txt delete mode 100644 libburn/async.c delete mode 100644 libburn/async.h delete mode 100644 libburn/back_hacks.h delete mode 100644 libburn/cleanup.c delete mode 100644 libburn/cleanup.h delete mode 100644 libburn/crc.c delete mode 100644 libburn/crc.h delete mode 100644 libburn/ddlpa.c delete mode 100644 libburn/ddlpa.h delete mode 100644 libburn/debug.c delete mode 100644 libburn/debug.h delete mode 100644 libburn/drive.c delete mode 100644 libburn/drive.h delete mode 100644 libburn/error.h delete mode 100644 libburn/file.c delete mode 100644 libburn/file.h delete mode 100644 libburn/init.c delete mode 100644 libburn/init.h delete mode 100644 libburn/lec.c delete mode 100644 libburn/lec.h delete mode 100644 libburn/libburn.h delete mode 100644 libburn/libdax_audioxtr.c delete mode 100644 libburn/libdax_audioxtr.h delete mode 100644 libburn/libdax_msgs.c delete mode 100644 libburn/libdax_msgs.h delete mode 100755 libburn/libdax_msgs_to_xyz_msgs.sh delete mode 100644 libburn/mmc.c delete mode 100644 libburn/mmc.h delete mode 100644 libburn/null.c delete mode 100644 libburn/null.h delete mode 100644 libburn/options.c delete mode 100644 libburn/options.h delete mode 100644 libburn/os-freebsd.h delete mode 100644 libburn/os-linux.h delete mode 100644 libburn/os.h delete mode 100644 libburn/read.c delete mode 100644 libburn/read.h delete mode 100644 libburn/sbc.c delete mode 100644 libburn/sbc.h delete mode 100644 libburn/sector.c delete mode 100644 libburn/sector.h delete mode 100644 libburn/sg-freebsd-port.c delete mode 100644 libburn/sg-freebsd.c delete mode 100644 libburn/sg-linux.c delete mode 100644 libburn/sg.c delete mode 100644 libburn/sg.h delete mode 100644 libburn/source.c delete mode 100644 libburn/source.h delete mode 100644 libburn/spc.c delete mode 100644 libburn/spc.h delete mode 100644 libburn/structure.c delete mode 100644 libburn/structure.h delete mode 100644 libburn/toc.c delete mode 100644 libburn/toc.h delete mode 100644 libburn/transport.h delete mode 100644 libburn/util.c delete mode 100644 libburn/util.h delete mode 100644 libburn/write.c delete mode 100644 libburn/write.h delete mode 100644 libcevap/cgen.c delete mode 100644 libcevap/cgen.h delete mode 100644 libcevap/cgen.txt delete mode 100644 libcevap/ctyp.c delete mode 100644 libcevap/ctyp.h delete mode 100755 libcevap/extract_cgen_input.sh delete mode 100755 libcevap/libcevap_gen.sh delete mode 100644 libcevap/libdax_equip.gif delete mode 100644 libcevap/libdax_job.gif delete mode 100644 libcevap/libdax_model.txt delete mode 100644 libcevap/libdax_overview.gif delete mode 100644 libcevap/main.c delete mode 100644 libcevap/smem.c delete mode 100644 libcevap/smem.h delete mode 100644 test/Makefile delete mode 100644 test/dewav.c delete mode 100644 test/fake_au.c delete mode 100644 test/libburner.c delete mode 100644 test/open-cd-excl.c delete mode 100644 test/poll.c delete mode 100644 test/structest.c delete mode 100644 test/telltoc.c delete mode 100644 version.h.in 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 bffad014dc4a2ca621d33980eff597c922397f76..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10595 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 diff --git a/cdrskin/doener_150x200_tr_octx.png b/cdrskin/doener_150x200_tr_octx.png deleted file mode 100644 index 7f8e9838896ac345a085b314c83f913a9c1d222f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9433 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%0Dp&oOUD5 zf5Ypt<eE{J*K+gY0DdZ%!|3!oI2!<_gT%6(H;u+OAhvu=FDhuUp~lZclU2@G<h8{J zUz=NYq%)O_V2TTWvfYd5Z2%Ke|LP4^nRe9;GC^$Gm%w#~E_hPqEwiF1P00UFtTn?S c@M>h@r+qEWf&ua0=YwxD5{lxrqQ=4h1IEa__W%F@ 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 3df86aee659d6d21ff64a771e46b0272c777cad2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10751 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 OoZ)B!*5d~N{Qm<)=B3*J diff --git a/libcevap/libdax_job.gif b/libcevap/libdax_job.gif deleted file mode 100644 index 8138ad25c020c2bd196c53d1558849ab283f249e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10532 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 M1-lnG7=XzC16(KeYXATM 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 f4e5715cf9359fb244032880551ea6d24a2dfc7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12521 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 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@