Compare commits
No commits in common. "master" and "python@386" have entirely different histories.
master
...
python@386
@ -1,6 +0,0 @@
|
|||||||
Joe Neeman
|
|
||||||
Philippe Rouquier
|
|
||||||
Gabriel Craciunescu
|
|
||||||
George Danchev
|
|
||||||
Jean-Francois Wauthy
|
|
||||||
Lorenzo Taylor
|
|
280
COPYING
280
COPYING
@ -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
|
|
18
COPYRIGHT
18
COPYRIGHT
@ -1,18 +0,0 @@
|
|||||||
Derek Foreman <derek@signalmarketing.com> and Ben Jansens <xor@orodu.net>
|
|
||||||
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
|
|
||||||
Mario Danic <mario.danic@gmail.com>, Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Copyright (C) 2006-2017 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 or later
|
|
||||||
as published by the Free Software Foundation.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
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
|
|
526
ChangeLog
526
ChangeLog
@ -1,526 +0,0 @@
|
|||||||
git clone git@dev.lovelyhq.com:libburnia/libburn.git
|
|
||||||
(to become libburn-1.5.8 or higher)
|
|
||||||
===============================================================================
|
|
||||||
- no novelties yet -
|
|
||||||
|
|
||||||
|
|
||||||
libburn-1.5.6.tar.gz Wed Jun 07 2023
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: Overburning with cdrskin option -force ended by a libburn error
|
|
||||||
* New API call burn_write_opts_set_bdr_obs_exempt()
|
|
||||||
* New cdrskin option --bdr_obs_exempt
|
|
||||||
* Officially enabled overburning with burn_write_opts_set_force(,1)
|
|
||||||
|
|
||||||
libburn-1.5.4.tar.gz Sat Jan 30 2021
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: Early SCSI commands from sg-linux.c were not logged
|
|
||||||
* New API call burn_drive_set_speed_exact()
|
|
||||||
* New API call burn_nominal_slowdown()
|
|
||||||
|
|
||||||
libburn-1.5.2.pl01.tar.gz Mon Nov 25 2019
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: cdrskin multi-track burning was slow and stalled after track 1.
|
|
||||||
Regression introduced in version 1.5.0 by commit 84fad99, 2018.02.05
|
|
||||||
O_DIRECT is now disabled for track sources.
|
|
||||||
|
|
||||||
libburn-1.5.2.tar.gz Sat Oct 26 2019
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: No lock was obtained for setting up a fifo object
|
|
||||||
* Bug fix: Stream recording was applied regardless whether the drive offers it.
|
|
||||||
This caused Xfburn failures with some MATSHITA laptop drives.
|
|
||||||
* Bug fix: TDK Corporation was not recognized as manufacturer of DVD-R "TTH02"
|
|
||||||
* Made libburn ready for building out-of-source. Thanks Ross Burton.
|
|
||||||
* New API calls burn_drive_get_feature_codes(), burn_drive_get_feature()
|
|
||||||
* New cdrskin option --list_features
|
|
||||||
|
|
||||||
libburn-1.5.0.tar.gz Sat Sep 15 2018
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: cdrskin threw errno 22 on data file input if libburn is
|
|
||||||
configured with --enable-track-src-odirect
|
|
||||||
* Bug fix: SIGSEGV could happen if a track ended by reaching its fixed size
|
|
||||||
while the track source still was willing to deliver bytes.
|
|
||||||
Thanks to user swordragon.
|
|
||||||
* Bug fix: Device file comparison parameters were recorded wrong with Linux sg
|
|
||||||
|
|
||||||
libburn-1.4.8.tar.gz Tue Sep 12 2017
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: Option -dummy did not affect writing by direct_write_amount=
|
|
||||||
* New API call burn_drive_reset_simulate()
|
|
||||||
* New API call burn_drive_get_bd_r_pow()
|
|
||||||
* Refusing to write to BD-R if formatted to Pseudo Overwrite
|
|
||||||
|
|
||||||
libburn-1.4.6.tar.gz Fri Sep 16 2016
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: SAO CD could be perceived 2 blocks to short.
|
|
||||||
Regression in 1.4.4 by rev 5672.
|
|
||||||
* Now operating optical drives on OpenBSD. Thanks to SASANO Takayoshi.
|
|
||||||
* New API call burn_drive_set_immed()
|
|
||||||
* New cdrskin option use_immed_bit=
|
|
||||||
|
|
||||||
libburn-1.4.4.tar.gz Fri Jul 01 2016
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: Option drive_scsi_dev_family=sg did not convert /dev/sr* to /dev/sg*
|
|
||||||
* Bug fix: burn_make_input_sheet_v07t() falsly recognized double byte encoding.
|
|
||||||
Affected cdrskin option: cdtext_to_v07t=
|
|
||||||
* Bug fix: Double free at end of run if burn_write_opts_set_leadin_text() is
|
|
||||||
used. Affected cdrskin option: textfile=
|
|
||||||
* Bug fix: DVD book type of DVD+RW DL and DVD+R DL was reported wrong.
|
|
||||||
Thanks to Etienne Bergeron.
|
|
||||||
|
|
||||||
libburn-1.4.2.pl01.tar.gz Fri Jan 29 2016
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: cdrskin "failed to attach fifo" when burning from stdin.
|
|
||||||
Regression of 1.4.2, rev 5522.
|
|
||||||
|
|
||||||
libburn-1.4.2.tar.gz Sat Nov 28 2015
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: burn_disc_get_media_id() returned BD identifiers 2 chars too long
|
|
||||||
* Bug fix: burn_disc_get_multi_caps() returned 2048 bytes too many in
|
|
||||||
caps.start_range_high
|
|
||||||
* Bug fix: Media summary session count of blank and closed media was short by 1
|
|
||||||
* Bug fix: Endless loop if transport error occurs while waiting for drive ready
|
|
||||||
* New API calls burn_drive_get_serial_no() and burn_drive_get_media_sno()
|
|
||||||
* Result of a Coverity audit: 40+ code changes, but no easy-to-trigger bugs
|
|
||||||
|
|
||||||
libburn-1.4.0.tar.gz Sun May 17 2015
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: Double free with cdrskin -vvv.
|
|
||||||
Introduced with rev 5065, version 1.3.1
|
|
||||||
* Bug fix: Wrong read access to memory. Reported by valgrind of lian jianfei.
|
|
||||||
|
|
||||||
libburn-1.3.8.tar.gz Sat Jun 28 2014
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: Wrong stack usage caused SIGBUS on sparc when compiled by gcc -O2
|
|
||||||
* Bug fix: Minimum drive buffer fill was measured by cdrskin before the buffer
|
|
||||||
could get full
|
|
||||||
* Bug fix: A failed MMC BLANK command did not cause error indication by libburn
|
|
||||||
* Bug fix: A final fsync(2) was performed with stdio drives, even if not
|
|
||||||
desired
|
|
||||||
|
|
||||||
libburn-1.3.6.pl01.tar.gz Tue Mar 18 2013
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: CD TAO with multiple tracks could cause a buffer overrun
|
|
||||||
* Bug fix: Compilation warning for unsupported systems mutated into an error
|
|
||||||
|
|
||||||
libburn-1.3.6.tar.gz Tue Mar 04 2013
|
|
||||||
===============================================================================
|
|
||||||
* New system adapter for NetBSD
|
|
||||||
|
|
||||||
libburn-1.3.4.tar.gz Thu Dec 12 2013
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: Drive error reports were ignored during blanking and formatting
|
|
||||||
* Bug fix: Drive LG BH16NS40 stalls on inspection of unformatted DVD+RW
|
|
||||||
* New API call burn_disc_pretend_full_uncond()
|
|
||||||
|
|
||||||
libburn-1.3.2.tar.gz Wed Aug 07 2013
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: cdrskin -msinfo on DVD and BD reported
|
|
||||||
old session start = next writable address.
|
|
||||||
Regression introduced by version 1.2.8 (rev 4956).
|
|
||||||
* Bug fix: The signal handler aborted on SIGCONT, SIGTSTP, SIGTTIN, SIGTTOU
|
|
||||||
* New API call burn_make_input_sheet_v07t()
|
|
||||||
* API call burn_session_input_sheet_v07t(): read multiple blocks from same file
|
|
||||||
* New API calls burn_drive_extract_audio(), burn_drive_extract_audio_track()
|
|
||||||
* New cdrskin option textfile_to_v07t=
|
|
||||||
* New cdrskin options cdtext_to_textfile= and cdtext_to_v07t=
|
|
||||||
* New cdrskin options extract_audio_to= , extract_tracks= , extract_basename= ,
|
|
||||||
--extract_dap
|
|
||||||
* New cdrskin option --pacifier_with_newline
|
|
||||||
* Improved granularity of SCSI log time measurement, now with timestamp
|
|
||||||
* Optional "make doc" now demands doxygen 1.8.4
|
|
||||||
|
|
||||||
libburn-1.3.0.pl01.tar.gz Fri May 31 2013
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: cdrskin -msinfo on DVD and BD reported
|
|
||||||
old session start = next writable address.
|
|
||||||
Regression introduced by version 1.2.8.
|
|
||||||
|
|
||||||
libburn-1.3.0.tar.gz Fri May 17 2013
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: Full formatting of BD-RE used certification regardless of drive
|
|
||||||
capabilities
|
|
||||||
* Bug fix: DVD+R with damaged TOC were reported by -minfo with wrong end
|
|
||||||
address
|
|
||||||
|
|
||||||
libburn-1.2.8.tar.gz Mon Mar 18 2013
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: All CD tracks were reported with the sizes of the tracks in the
|
|
||||||
first session. Regression introduced with version 1.2.0 (rev 4552).
|
|
||||||
* Bug fix: On some drives the request for minimum speed yielded maximum speed
|
|
||||||
* New cdrskin option --list_speeds
|
|
||||||
* -toc and -minfo now report about tracks in the incomplete session
|
|
||||||
* New API call burn_disc_get_incomplete_sessions()
|
|
||||||
* New burn_toc_entry component .track_status_bits
|
|
||||||
|
|
||||||
libburn-1.2.6.tar.gz Tue Jan 08 2013
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: Speed setting had no effect on BD media
|
|
||||||
* New cdrskin option --no_load
|
|
||||||
* New API call burn_read_audio()
|
|
||||||
* New API call burn_list_sev_texts()
|
|
||||||
|
|
||||||
libburn-1.2.4.tar.gz Fri Jul 20 2012
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: CD SAO sessions with data tracks started by an audio pause
|
|
||||||
* Bug fix: CD tracks were perceived 2 sectors too short.
|
|
||||||
Nice with TAO, bad with SAO.
|
|
||||||
* Bug fix: cdrskin SIGSEGV if track source was added when no drive was available
|
|
||||||
* New API call burn_write_opts_set_obs_pad(), ./configure --enable-dvd-obs-pad
|
|
||||||
* New cdrskin option --obs_pad
|
|
||||||
|
|
||||||
libburn-1.2.2.tar.gz Mon Apr 02 2012
|
|
||||||
===============================================================================
|
|
||||||
* Small internal refinements
|
|
||||||
|
|
||||||
libburn-1.2.0.tar.gz Sat Jan 28 2012
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: cdrskin produced a memory fault if interupted before writing began
|
|
||||||
* Bug fix: Solaris adapter mishandled write commands which failed on first try
|
|
||||||
* Bug fix: Interrupting libburn while drive tray is loading led to endless loop
|
|
||||||
* Bug fix: Progress report with blanking and formatting could be bogus
|
|
||||||
* New API calls burn_disc_get_leadin_text(), burn_write_opts_set_leadin_text()
|
|
||||||
* New API calls for composing CD-TEXT, see doc/cdtext.txt
|
|
||||||
* New API call burn_session_by_cue_file() for reading CDRWIN .cue files
|
|
||||||
* New API call burn_track_set_isrc_string()
|
|
||||||
* New API calls burn_track_set_index(), burn_track_clear_indice()
|
|
||||||
* New API calls burn_session_set_start_tno(), burn_session_get_start_tno()
|
|
||||||
* New API calls burn_track_set_pregap_size(), burn_track_set_postgap_size()
|
|
||||||
* Implemented cdrskin option textfile=
|
|
||||||
* Implemented cdrskin option combination -vv -toc for cdtext.dat production
|
|
||||||
* Implemented cdrskin options mcn= and isrc=
|
|
||||||
* Implemented cdrskin options -scms -copy -nocopy -preemp -nopreemp
|
|
||||||
* Implemented cdrskin option index=
|
|
||||||
* Partly implemented cdrskin options cuefile= and -text
|
|
||||||
* New cdrskin option input_sheet_v07t= for CD-TEXT definition
|
|
||||||
* New cdrskin options --cdtext_dummy and --cdtext_verbose
|
|
||||||
* New cdrskin options --four_channel --two_channel
|
|
||||||
* New cdrskin option cd_start_tno=
|
|
||||||
* New cdrskin options sao_pregap=, sao_postgap=
|
|
||||||
|
|
||||||
libburn-1.1.8.tar.gz Mon Nov 21 2011
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: Misinterpreted mode page 2A if block descriptors are present
|
|
||||||
* Enabled recognition of QEMU DVD-ROM 0.12
|
|
||||||
* Avoiding to intermediately close and open drive device file
|
|
||||||
* New API call burn_drive_re_assess()
|
|
||||||
|
|
||||||
libburn-1.1.6.tar.gz Tue Sep 27 2011
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: stdio sizes > 4 TB - 32 kB caused integer rollover
|
|
||||||
* Worked around a collision with Linux udev which lets links vanish
|
|
||||||
|
|
||||||
libburn-1.1.4.tar.gz Sun Aug 07 2011
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: Some drives return -150 as NWA of blank CD, rather than 0.
|
|
||||||
libburn forwarded this misleading information to the application.
|
|
||||||
* Bug fix: Some drives returned wrong CD sizes after having burned DVD-R
|
|
||||||
* Bug fix: Empty ROM drive was mistaken to hold an unsuitable disc
|
|
||||||
* Bug fix: Avoiding to load speed descriptor list twice
|
|
||||||
* New API call burn_lookup_device_link()
|
|
||||||
* New API call burn_disc_get_phys_format_info()
|
|
||||||
* New cdrskin option --device_links
|
|
||||||
|
|
||||||
Release 1.1.2 was skipped to get back in sync with libisoburn.
|
|
||||||
|
|
||||||
libburn-1.1.0.pl01.tar.gz Mon Jun 20 2011
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: libburn-1.1.0 compiled only on Linux, FreeBSD, and Solaris
|
|
||||||
|
|
||||||
libburn-1.1.0.tar.gz Sat Jun 18 2011
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: burn_disc_format() on DVD-RW issued wrong block size with type 00h
|
|
||||||
* New API call burn_disc_next_track_is_damaged()
|
|
||||||
* New API call burn_disc_close_damaged()
|
|
||||||
* Dropped suffix .plXY from tarball name
|
|
||||||
|
|
||||||
Release 1.0.8 was skipped to get back in sync with libisofs and libisoburn.
|
|
||||||
|
|
||||||
libburn-1.0.6.pl00.tar.gz Sat Apr 9 2011
|
|
||||||
===============================================================================
|
|
||||||
* Burning DVD-R DAO with 2 kB size granularity rather than 32 kB
|
|
||||||
* New API call burn_allow_drive_role_4()
|
|
||||||
|
|
||||||
libburn-1.0.4.pl00.tar.gz Thu Mar 3 2011
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: Read-only file descriptors were classified as write-only pseudo
|
|
||||||
drives
|
|
||||||
|
|
||||||
libburn-1.0.2.pl00.tar.gz Wed Feb 23 2011
|
|
||||||
===============================================================================
|
|
||||||
* Removed compilation obstacles on Solaris 9.
|
|
||||||
* Improved recognition of non-seekable stdio pseudo-drives.
|
|
||||||
|
|
||||||
libburn-1.0.0.pl00.tar.gz Sun Jan 16 2011
|
|
||||||
===============================================================================
|
|
||||||
* Allowed umask to create stdio-drive files with rw-permissions for all
|
|
||||||
* cdrskin now refuses to burn if the foreseeable size exceeds media capacity
|
|
||||||
|
|
||||||
libburn-0.9.0.pl00.tar.gz Wed Dec 08 2010
|
|
||||||
===============================================================================
|
|
||||||
* Regression fix: SCSI reply data logging was disabled in release 0.8.6
|
|
||||||
|
|
||||||
libburn-0.8.8.pl00.tar.gz Wed Oct 20 2010
|
|
||||||
===============================================================================
|
|
||||||
* New API call burn_offst_source_new()
|
|
||||||
* New API call burn_disc_get_bd_spare_info()
|
|
||||||
|
|
||||||
libburn-0.8.6.pl00.tar.gz Fri Sep 17 2010
|
|
||||||
===============================================================================
|
|
||||||
* Lifted test reservation on DVD-R DL media.
|
|
||||||
* Hiding all non-API symbols from the linker by use of --version-script
|
|
||||||
* Now with history of release notes in ./ChangeLog file.
|
|
||||||
|
|
||||||
libburn-0.8.4.pl00.tar.gz Wed Jun 30 2010
|
|
||||||
===============================================================================
|
|
||||||
* General POSIX system adapters ignore SIGWINCH and SIGURG if defined
|
|
||||||
* Allowed 64 kB max output buffer size on all OSes
|
|
||||||
|
|
||||||
libburn-0.8.2.pl00.tar.gz Fri Jun 11 2010
|
|
||||||
===============================================================================
|
|
||||||
* New system adapter for Solaris uscsi (tested on snv134, kernel 5.11)
|
|
||||||
* Bug fix: CD TOC was not read if the first track did not start at LBA 0
|
|
||||||
* Bug fix: CD-ROM media got attributed random lead-in and lead-out adresses
|
|
||||||
* Bug fix: SIGSEGV of experimental libcdio system adapter if drive list is
|
|
||||||
empty
|
|
||||||
|
|
||||||
libburn-0.8.0.pl00.tar.gz Fri Apr 09 2010
|
|
||||||
===============================================================================
|
|
||||||
* libburn now works with ahci driver on FreeBSD 8-STABLE.
|
|
||||||
|
|
||||||
libburn-0.7.8.pl00.tar.gz Wed Mar 10 2010
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: On FreeBSD, piped input was falsely attributed a small fixed size.
|
|
||||||
* Built-in abort handling is more suitable for FreeBSD now.
|
|
||||||
cdrskin novelties:
|
|
||||||
* Bug fix: Option fs=0 led to SIGSEGV. Regression introduced by version 0.7.4
|
|
||||||
in december 2009.
|
|
||||||
* Abort handling is more suitable for FreeBSD now.
|
|
||||||
|
|
||||||
libburn-0.7.6.pl00.tar.gz Sat Jan 23 2010
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: System adapter for generic X/Open was missing in libburn release
|
|
||||||
tarball
|
|
||||||
* Bug fix: with non-Linux adapters there were 0 readable bytes on block devices
|
|
||||||
* Made FreeBSD system adapter safe from mutal burn spoiling and drive deadlock
|
|
||||||
* Enabled FreeBSD system adapter for Debian kfreebsd
|
|
||||||
* Experimental SCSI transport adapter via GNU libcdio 0.83git
|
|
||||||
cdrskin novelties:
|
|
||||||
* none
|
|
||||||
|
|
||||||
libburn-0.7.4.pl01.tar.gz Sat Dec 26 2009
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: Added missing system adapter for generic X/Open to libburn release
|
|
||||||
tarball
|
|
||||||
|
|
||||||
Libburn 0.7.4.pl00 Mon Dec 07 2009
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: SIGSEGV from NULL pointer with media product id inquiry on LG
|
|
||||||
GH22LS30
|
|
||||||
* Bug fix: DVD DAO track size was rounded up much too generously
|
|
||||||
* Workaround for Pioneer DVR-216D which got stuck on DVD-R burns.
|
|
||||||
(already fixed in 0.7.2.pl01)
|
|
||||||
* Workaround for Pioneer DVR-216D refusal to eject.
|
|
||||||
(already fixed in 0.7.2.pl01)
|
|
||||||
* Configure options --enable-dvd-obs-64k, --enable-track-src-odirect
|
|
||||||
* New API calls burn_write_opts_set_dvd_obs(),
|
|
||||||
burn_write_opts_set_stdio_fsync()
|
|
||||||
* New API call burn_set_scsi_logging()
|
|
||||||
* New API calls burn_fifo_get_statistics(), burn_fifo_next_interval(),
|
|
||||||
burn_fifo_fill()
|
|
||||||
* Re-implemented ECMA-130 P-parity, Q-parity and scrambling for BURN_WRITE_RAW
|
|
||||||
cdrskin novelties:
|
|
||||||
* cdrskin option -V for logging of SCSI commands
|
|
||||||
* New cdrskin options dvd_obs= and stdio_fsync=
|
|
||||||
* New compile_cdrskin.sh option -dvd_obs_64k
|
|
||||||
|
|
||||||
libburn-0.7.2.pl01.tar.gz Fri Nov 13 2009
|
|
||||||
===============================================================================
|
|
||||||
* Workaround for Pioneer DVR-216D which got stuck on DVD-R burns.
|
|
||||||
* Workaround for Pioneer DVR-216D refusal to eject.
|
|
||||||
|
|
||||||
Libburn 0.7.2.pl00 Mon Oct 12 2009
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: CD TAO sessions with multiple tracks did not work in -dummy mode
|
|
||||||
* New API calls burn_get_media_product_id() , burn_guess_manufacturer() ,
|
|
||||||
burn_guess_cd_manufacturer()
|
|
||||||
* New API call burn_disc_get_cd_info()
|
|
||||||
* New API call burn_track_set_cdxa_conv()
|
|
||||||
cdrskin novelties:
|
|
||||||
* Better interpretation of options -mode2, -xa, -xa1, -xa2
|
|
||||||
* New option --xa1-ignore
|
|
||||||
* New -atip report lines "Product Id:" and "Producer:"
|
|
||||||
|
|
||||||
libburn-0.7.0.pl00.tar.gz Thu Aug 27 2009
|
|
||||||
===============================================================================
|
|
||||||
* New API calls burn_drive_get_all_profiles(), burn_obtain_profile_name() allow
|
|
||||||
to inquire and process the list of supported media types. cdrskin lists all
|
|
||||||
supported profiles with option -atip -v
|
|
||||||
* New API call burn_drive_snooze() allows to calm down a drive when no i/o is
|
|
||||||
expected for a while.
|
|
||||||
* Bug fix: Some SCSI commands stalled on U3 memory sticks which appear as a hub
|
|
||||||
with a memory stick and a CD-ROM drive containing a small CD. These commands
|
|
||||||
make not much sense with a CD-ROM and are now avoided for this media
|
|
||||||
situation.
|
|
||||||
|
|
||||||
libburn-0.6.8.pl00.tar.gz Tue Jul 14 2009
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: Old MMC-1 drives were rejected because of mode page 2Ah length.
|
|
||||||
* cdrskin -scanbus now works with high SCSI bus numbers.
|
|
||||||
|
|
||||||
libburn-0.6.6.pl00.tar.gz Fri May 8 2009
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: Improper abort handling with broken pipe during outputto a stdio:
|
|
||||||
pseudo-drive.
|
|
||||||
* Bug fix: Device scan stalled on FreeBSD with non-burner USB device
|
|
||||||
|
|
||||||
libburn-0.6.4.pl00.tar.gz Fri Mar 13 2009
|
|
||||||
===============================================================================
|
|
||||||
* New operating system adapter "dummy" for stdio on general X/Open systems
|
|
||||||
* New API function burn_drive_set_stream_recording() allows to write the
|
|
||||||
crucial start blocks of a filesystem with slow BD-RE Defect Management and to
|
|
||||||
write the bulk of data with full nominal speed.
|
|
||||||
|
|
||||||
libburn-0.6.2.pl00.tar.gz Fri Feb 20 2009
|
|
||||||
===============================================================================
|
|
||||||
* Improvements with build system for FreeBSD
|
|
||||||
|
|
||||||
libburn-0.6.0.pl01.tar.gz Wed Jan 07 2009
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: BD-R were not correctly finalized
|
|
||||||
|
|
||||||
libburn-0.6.0.pl00.tar.gz Sun Jan 04 2009
|
|
||||||
===============================================================================
|
|
||||||
* Formatting and writing of BD-R media
|
|
||||||
* New API function burn_get_read_capacity()
|
|
||||||
|
|
||||||
libburn-0.5.8.pl00.tar.gz Mon Dec 08 2008
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: A session without leadout entry on CD caused a SIGSEGV by NULL
|
|
||||||
* Improvements about BD-RE formatting
|
|
||||||
|
|
||||||
libburn-0.5.6.pl00.tar.gz Wed Nov 12 2008
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: libburn fifo thread was not aborted when burn run was aborted which
|
|
||||||
could lead to use of freed memory.
|
|
||||||
|
|
||||||
libburn-0.5.4.pl00.tar.gz Mon Oct 6 2008
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: On Linux 2.4 /dev/sr0 was accepted as enumerable address but then
|
|
||||||
failed to work.
|
|
||||||
|
|
||||||
libburn-0.5.2.pl00.tar.gz Wed Aug 20 2008
|
|
||||||
===============================================================================
|
|
||||||
* Larger set of possibly acceptable drive device file names
|
|
||||||
|
|
||||||
libburn-0.5.0.pl00.tar.gz Thu Jul 17 2008
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: cdrskin option drive_scsi_dev_family=scd lead to buffer overflow
|
|
||||||
* Ability to use /dev/scd as fallback if /dev/sr does not exist
|
|
||||||
* New API call burn_fifo_peek_data()
|
|
||||||
|
|
||||||
libburn-0.4.8.pl00.tar.gz Sat May 17 2008
|
|
||||||
===============================================================================
|
|
||||||
* Bug fix: Random access addressing for DVD-RAM and BD-RE did not work.
|
|
||||||
* cdrskin: Affected were options write_start_address= and
|
|
||||||
-- grow_overwriteable_iso on DVD-RAM or BD-RE.
|
|
||||||
* xorriso: Affected were sessions on DVD-RAM or BD-RE after the first one.
|
|
||||||
|
|
||||||
libburn-0.4.6.pl00.tar.gz Sun May 11 2008
|
|
||||||
===============================================================================
|
|
||||||
* Support for BD-RE media is now official
|
|
||||||
* New burn_write_opts_set_stream_recording() can speed up DVD-RAM and BD-RE
|
|
||||||
* New cdrskin option --list_formats
|
|
||||||
* New cdrskin blank types for expert formatting of DVD-RAM and BD-RE
|
|
||||||
* New cdrskin blank type blank=as_needed for automatic handling of media
|
|
||||||
|
|
||||||
libburn-0.4.4.tar.gz Thu April 10 2008
|
|
||||||
===============================================================================
|
|
||||||
* Support for DVD+R/DL media is now official
|
|
||||||
|
|
||||||
libburn-0.4.2.tar.gz Sun Feb 3 2008
|
|
||||||
===============================================================================
|
|
||||||
* Long term commitment to ABI libburn.so.4.
|
|
||||||
* ABI compatibility is guaranteed for any older feature set released since
|
|
||||||
libburn-0.3.2 about one year ago.
|
|
||||||
* libburn provides means for compile time and runtime checking of its version.
|
|
||||||
* Compile time check in cdrskin for proper version of libburn include file.
|
|
||||||
Required is at least 0.4.2.
|
|
||||||
* Runtime check in cdrskin prevents dynamic linking with outdated version of
|
|
||||||
libburn.so.4. Required is at least the version seen in the include file at
|
|
||||||
compile time.
|
|
||||||
|
|
||||||
libburn-0.4.0.tar.gz Mon Oct 29 2007
|
|
||||||
===============================================================================
|
|
||||||
* New option direct_write_amount=
|
|
||||||
* New option --grow_overwriteable_iso
|
|
||||||
* New option --allow_emulated_drives dev=stdio:<path>
|
|
||||||
* More cdrecord options supported: -format, -inq, -load, -lock, -immed, -waiti
|
|
||||||
* New option fallback_program=
|
|
||||||
* A lot of libburn API additions.
|
|
||||||
|
|
||||||
libburn-0.3.8.tar.gz Tue Jul 31 2007
|
|
||||||
===============================================================================
|
|
||||||
* 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
|
|
||||||
* Note: ABI has not been broken.
|
|
||||||
|
|
||||||
libburn-0.3.6.tar.gz Thu Apr 26 2007
|
|
||||||
===============================================================================
|
|
||||||
* On Linux kernel 2.6, /dev/sr* gets used rather than /dev/sg*.
|
|
||||||
* DVD+R now get finalized (if not -multi is given)
|
|
||||||
|
|
||||||
libburn-0.3.4.tar.gz Mon Mar 12 2007
|
|
||||||
===============================================================================
|
|
||||||
* Multi-session recording on DVD+R, including -toc, -msinfo
|
|
||||||
* Options --tell_media_space , assert_write_lba=
|
|
||||||
* Bug fix of rare multi track fifo stall
|
|
||||||
|
|
||||||
libburn-0.3.2.tar.gz Feb 11 2007
|
|
||||||
===============================================================================
|
|
||||||
* Burnfree enabled by default
|
|
||||||
* Multi-session recording on sequential DVD-R[W], including -toc, -msinfo
|
|
||||||
* DVD-R[W] Disk-at-once recording
|
|
||||||
|
|
||||||
libburn-0.3.0.1.tar.gz Tue Jan 30 2007
|
|
||||||
===============================================================================
|
|
||||||
* 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
|
|
||||||
* 0.3.0.1 release notes *
|
|
||||||
* Bug fix enabling tracks >= 1.3 GB from disk file
|
|
||||||
|
|
||||||
libburn-0.2.6.3.tar.gz Fri Dec 29 2006
|
|
||||||
===============================================================================
|
|
||||||
* 0.2.6 release notes (Wed Nov 22 2006)
|
|
||||||
* After a lot of time with dedication to this project, we proudly present you
|
|
||||||
libburn 0.2.6. It is the first version of cdrskin and libburn after they have
|
|
||||||
been split from genisofs and libisofs. Main new features are write mode TAO
|
|
||||||
and support for multi session.
|
|
||||||
* 0.2.6.1 release notes (Fri Nov 24 2006)
|
|
||||||
* Point release to fix misleading version numbers in messages and documentation
|
|
||||||
* 0.2.6.2 release notes (Sat Dec 16 2006)
|
|
||||||
* cdrskin man page backported from development version 0.2.7.
|
|
||||||
* 0.2.6.3 release notes (Fri Dec 29 2006)
|
|
||||||
* Point release to fix build system problems people have experienced with the
|
|
||||||
past release.
|
|
||||||
|
|
||||||
libburn-0.2.3.snapshot02.tar.gz Thu Nov 02 2006
|
|
||||||
===============================================================================
|
|
||||||
* Stabilized snapshot including release 0.2.4.pl01 of cdrskin
|
|
||||||
* cdrskin 0.2.4 release notes
|
|
||||||
* Compatibility with cdrecord has been improved in respect to drive addresses,
|
|
||||||
audio extraction from .wav, -scanbus, -toc, drive buffer fill indicator.
|
|
||||||
* Note: The previous snapshot01 with the same source base is handicapped by a
|
|
||||||
broken ./configure setup. It works well on Intel compatible CPUs but is
|
|
||||||
supposed to be unusable on big-endian architectures.
|
|
||||||
|
|
||||||
libburn-0.2.2.tar.gz Wed Sep 20 2006
|
|
||||||
===============================================================================
|
|
||||||
Initial release of libburnia's libburn combined with cdrskin.
|
|
234
INSTALL
234
INSTALL
@ -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.
|
|
||||||
|
|
236
Makefile.am
236
Makefile.am
@ -1,236 +0,0 @@
|
|||||||
|
|
||||||
# ts A90315 : LIBBURNIA_PKGCONFDIR is defined OS specific in acinclude.m4
|
|
||||||
# was: pkgconfigdir=$(libdir)/pkgconfig
|
|
||||||
pkgconfigdir=$(LIBBURNIA_PKGCONFDIR)
|
|
||||||
|
|
||||||
libincludedir=$(includedir)/libburn
|
|
||||||
|
|
||||||
lib_LTLIBRARIES = libburn/libburn.la
|
|
||||||
ACLOCAL_AMFLAGS = -I ./
|
|
||||||
|
|
||||||
## ========================================================================= ##
|
|
||||||
|
|
||||||
# Build libraries
|
|
||||||
libburn_libburn_la_LDFLAGS = \
|
|
||||||
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) $(LIBLDFLAGS)
|
|
||||||
# This causes undesired .o names
|
|
||||||
# configure.ac appends -D options to variable CFLAG
|
|
||||||
### libburn_libburn_la_CFLAGS = $(LIBBURN_DVD_OBS_64K)
|
|
||||||
libburn_libburn_la_LIBADD = $(LIBBURN_ARCH_LIBS) $(THREAD_LIBS)
|
|
||||||
libburn_libburn_la_SOURCES = \
|
|
||||||
libburn/async.c \
|
|
||||||
libburn/async.h \
|
|
||||||
libburn/back_hacks.h \
|
|
||||||
libburn/cdtext.c \
|
|
||||||
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/ecma130ab.c \
|
|
||||||
libburn/ecma130ab.h \
|
|
||||||
libburn/error.h \
|
|
||||||
libburn/file.c \
|
|
||||||
libburn/file.h \
|
|
||||||
libburn/init.c \
|
|
||||||
libburn/init.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
|
|
||||||
|
|
||||||
## libburn/sg-@ARCH@.c \
|
|
||||||
|
|
||||||
libinclude_HEADERS = \
|
|
||||||
libburn/libburn.h
|
|
||||||
|
|
||||||
install-exec-hook:
|
|
||||||
$(LIBBURNIA_LDCONFIG_CMD) "$(DESTDIR)$(libdir)" || echo 'NOTE: Explicit dynamic library configuration failed. If needed, configure manually for:' "$(DESTDIR)$(libdir)"
|
|
||||||
|
|
||||||
## ========================================================================= ##
|
|
||||||
|
|
||||||
## Build test applications
|
|
||||||
noinst_PROGRAMS = \
|
|
||||||
test/libburner \
|
|
||||||
test/offst_source \
|
|
||||||
test/telltoc \
|
|
||||||
test/dewav \
|
|
||||||
test/fake_au \
|
|
||||||
test/poll
|
|
||||||
|
|
||||||
bin_PROGRAMS = \
|
|
||||||
cdrskin/cdrskin
|
|
||||||
|
|
||||||
LIBBURN_EXTRALIBS = $(LIBBURN_ARCH_LIBS) $(THREAD_LIBS)
|
|
||||||
|
|
||||||
test_libburner_CPPFLAGS = -Ilibburn
|
|
||||||
test_libburner_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
|
|
||||||
test_libburner_SOURCES = test/libburner.c
|
|
||||||
test_offst_source_CPPFLAGS = -Ilibburn
|
|
||||||
test_offst_source_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
|
|
||||||
test_offst_source_SOURCES = test/offst_source.c
|
|
||||||
test_telltoc_CPPFLAGS = -Ilibburn
|
|
||||||
test_telltoc_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
|
|
||||||
test_telltoc_SOURCES = test/telltoc.c
|
|
||||||
test_dewav_CPPFLAGS = -Ilibburn
|
|
||||||
test_dewav_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
|
|
||||||
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) $(LIBBURN_EXTRALIBS)
|
|
||||||
test_poll_SOURCES = test/poll.c
|
|
||||||
|
|
||||||
## cdrskin construction site - ts A60816 - C30607
|
|
||||||
cdrskin_cdrskin_CPPFLAGS = -Ilibburn
|
|
||||||
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_1_5_7
|
|
||||||
|
|
||||||
# cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
|
|
||||||
# ts A80123, change proposed by Simon Huggins to cause dynamic libburn linking
|
|
||||||
cdrskin_cdrskin_LDADD = libburn/libburn.la $(LIBBURN_EXTRALIBS)
|
|
||||||
|
|
||||||
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"
|
|
||||||
##
|
|
||||||
|
|
||||||
# "make clean" shall remove a few stubborn .libs directories
|
|
||||||
# which George Danchev reported Dec 03 2011.
|
|
||||||
# Learned from: http://www.gnu.org/software/automake/manual/automake.html#Clean
|
|
||||||
clean-local:
|
|
||||||
-rm -rf cdrskin/.libs test/.libs
|
|
||||||
|
|
||||||
|
|
||||||
## ========================================================================= ##
|
|
||||||
|
|
||||||
## 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 $</* $(webhost):$(webpath)
|
|
||||||
|
|
||||||
## ts B00729
|
|
||||||
## Not by default any more.
|
|
||||||
## It is unclear who is supposed to create file ./doc/doc.lock
|
|
||||||
# all: doc
|
|
||||||
|
|
||||||
install-data-local:
|
|
||||||
if [ -f ./doc/doc.lock ]; then \
|
|
||||||
$(mkinstalldirs) $(docdir)/html; \
|
|
||||||
$(INSTALL_DATA) doc/html/* $(docdir)/html; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
uninstall-local:
|
|
||||||
rm -rf $(docdir)
|
|
||||||
|
|
||||||
## ========================================================================= ##
|
|
||||||
|
|
||||||
# Indent source files
|
|
||||||
indent_files = \
|
|
||||||
$(libburn_libburn_la_SOURCES) \
|
|
||||||
$(test_poll_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
|
|
||||||
|
|
||||||
## ========================================================================= ##
|
|
||||||
|
|
||||||
# Extra things
|
|
||||||
nodist_pkgconfig_DATA = \
|
|
||||||
libburn-1.pc
|
|
||||||
|
|
||||||
# http://www.nada.kth.se/cgi-bin/info?(automake.info)Man%20pages
|
|
||||||
man_MANS = cdrskin/cdrskin.1
|
|
||||||
|
|
||||||
EXTRA_DIST = \
|
|
||||||
bootstrap \
|
|
||||||
libburn-1.pc.in \
|
|
||||||
version.h.in \
|
|
||||||
doc/comments \
|
|
||||||
doc/doxygen.conf.in \
|
|
||||||
doc/cookbook.txt \
|
|
||||||
doc/mediainfo.txt \
|
|
||||||
doc/cdtext.txt \
|
|
||||||
doc/waveformat.txt \
|
|
||||||
README \
|
|
||||||
AUTHORS \
|
|
||||||
CONTRIBUTORS \
|
|
||||||
COPYRIGHT \
|
|
||||||
cdrskin/README \
|
|
||||||
cdrskin/cdrecord_spy.sh \
|
|
||||||
cdrskin/compile_cdrskin.sh \
|
|
||||||
cdrskin/convert_man_to_html.sh \
|
|
||||||
cdrskin/changelog.txt \
|
|
||||||
cdrskin/cdrskin_eng.html \
|
|
||||||
cdrskin/wiki_plain.txt \
|
|
||||||
cdrskin/cleanup.h \
|
|
||||||
cdrskin/cleanup.c \
|
|
||||||
libburn/libburn.ver \
|
|
||||||
libburn/os-dummy.h \
|
|
||||||
libburn/os-freebsd.h \
|
|
||||||
libburn/os-linux.h \
|
|
||||||
libburn/os-libcdio.h \
|
|
||||||
libburn/os-solaris.h \
|
|
||||||
libburn/os-netbsd.h \
|
|
||||||
libburn/sg-dummy.c \
|
|
||||||
libburn/sg-freebsd.c \
|
|
||||||
libburn/sg-linux.c \
|
|
||||||
libburn/sg-libcdio.c \
|
|
||||||
libburn/sg-solaris.c \
|
|
||||||
libburn/sg-netbsd.c \
|
|
||||||
COPYING \
|
|
||||||
NEWS \
|
|
||||||
ChangeLog \
|
|
||||||
INSTALL \
|
|
||||||
$(man_MANS)
|
|
||||||
|
|
873
README
873
README
@ -1,873 +0,0 @@
|
|||||||
------------------------------------------------------------------------------
|
|
||||||
libburnia-project.org
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
This all is under GPL.
|
|
||||||
(See GPL reference, our clarification and commitment at the end of this text)
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
libburnia-project.org
|
|
||||||
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Copyright (C) 2006-2023 Mario Danic, Thomas Schmitt
|
|
||||||
Still containing parts of Libburn. By Derek Foreman <derek@signalmarketing.com>
|
|
||||||
and Ben Jansens <xor@orodu.net>
|
|
||||||
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
|
|
||||||
|
|
||||||
http://files.libburnia-project.org/releases/libburn-1.5.6.tar.gz
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Build and Installation
|
|
||||||
|
|
||||||
From tarball
|
|
||||||
|
|
||||||
Obtain libburn-1.5.6.tar.gz, take it to a directory of your choice and do:
|
|
||||||
|
|
||||||
tar xzf libburn-1.5.6.tar.gz
|
|
||||||
cd libburn-1.5.6
|
|
||||||
./configure --prefix=/usr
|
|
||||||
make
|
|
||||||
|
|
||||||
To make libburn accessible for running and application development,
|
|
||||||
and to install the cdrecord compatibility binary cdrskin, do
|
|
||||||
(as Superuser):
|
|
||||||
|
|
||||||
make install
|
|
||||||
|
|
||||||
This procedure installs libburn.so.4 and cdrskin depending on it.
|
|
||||||
For a standalone cdrskin binary, see cdrskin/README.
|
|
||||||
|
|
||||||
A behavioral conflict is known between any burn software and demons like hald
|
|
||||||
which probe CD drives. This can spoil burn runs for CD-R or CD-RW.
|
|
||||||
You may have to keep your hald away from the drive. See for example
|
|
||||||
http://www.freebsd.org/gnome/docs/halfaq.html
|
|
||||||
|
|
||||||
|
|
||||||
From git
|
|
||||||
|
|
||||||
Our build system is based on autotools. For preparing the build of a git
|
|
||||||
snapshot you will need autotools of at least version 1.7.
|
|
||||||
Do in a directory of your choice:
|
|
||||||
|
|
||||||
git clone https://dev.lovelyhq.com/libburnia/libburn.git libburn-git
|
|
||||||
cd libburn-git
|
|
||||||
./bootstrap
|
|
||||||
./configure --prefix=/usr
|
|
||||||
make
|
|
||||||
make install
|
|
||||||
|
|
||||||
Warning: The master branch might contain experimental features which might
|
|
||||||
not persist until next release.
|
|
||||||
|
|
||||||
|
|
||||||
Special ./configure options
|
|
||||||
|
|
||||||
make install on GNU/Linux will try to run program ldconfig with the library
|
|
||||||
installation directory as only argument. Failure to do so will not abort
|
|
||||||
installation. One may disable ldconfig by ./configure option:
|
|
||||||
--disable-ldconfig-at-install
|
|
||||||
|
|
||||||
In some situations Linux may deliver a better write performance to drives if
|
|
||||||
the track input is read with O_DIRECT (see man 2 open). The API call
|
|
||||||
burn_os_open_track_src() and the input readers of cdrskin and libburn fifo
|
|
||||||
can be told to use this peculiar read mode by:
|
|
||||||
--enable-track-src-odirect
|
|
||||||
|
|
||||||
But often libburn call burn_write_opts_set_dvd_obs(opts, 64*1024) will yield
|
|
||||||
even better performance in such a situation. 64k can be made default at
|
|
||||||
configure time by:
|
|
||||||
--enable-dvd-obs-64k
|
|
||||||
This may be combined with above --enable-track-src-odirect .
|
|
||||||
|
|
||||||
If it is desired that DVD DAO writing and stdio: writing get padded up to
|
|
||||||
a full write chunk of 32k or 64k, then use ./configure option:
|
|
||||||
--enable-dvd-obs-pad
|
|
||||||
|
|
||||||
Alternatively the transport of SCSI commands can be done via libcdio-0.83.
|
|
||||||
You may install it and re-run libburn's ./configure with option
|
|
||||||
--enable-libcdio
|
|
||||||
|
|
||||||
By use of a version script, the libburn.so library exposes no other function
|
|
||||||
names but those of the API definition in libburn/libburn.h.
|
|
||||||
If -Wl,--version-script=... makes problems with the local compiler, then
|
|
||||||
disable this encapsulation feature by
|
|
||||||
--disable-versioned-libs
|
|
||||||
|
|
||||||
Make sure to re-compile all source files after running ./configure
|
|
||||||
make clean ; make
|
|
||||||
make install
|
|
||||||
|
|
||||||
|
|
||||||
Linux only:
|
|
||||||
|
|
||||||
libburn tries to avoid a collision with udev's drive examination by waiting
|
|
||||||
0.1 seconds before opening the device file for a longer time, after udev
|
|
||||||
might have been alarmed by drive scanning activities.
|
|
||||||
The waiting time can be set at ./configure time with microsecond granularity.
|
|
||||||
E.g. 2 seconds:
|
|
||||||
CFLAGS="$CFLAGS -DLibburn_udev_wait_useC=2000000"
|
|
||||||
./configure ...options...
|
|
||||||
Waiting can be disabled by zero waiting time:
|
|
||||||
CFLAGS="$CFLAGS -DLibburn_udev_wait_useC=0"
|
|
||||||
Alternatively, libburn can try to be nice by opening the device file,
|
|
||||||
closing it immediately, waiting, and only then opening it for real:
|
|
||||||
CFLAGS="$CFLAGS -DLibburn_udev_extra_open_cyclE -DLibburn_udev_wait_useC=500000"
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The other parts of the the libburnia project are hosted as neighbors of
|
|
||||||
libburn:
|
|
||||||
|
|
||||||
git clone https://dev.lovelyhq.com/libburnia/libisofs.git
|
|
||||||
git clone https://dev.lovelyhq.com/libburnia/libisoburn.git
|
|
||||||
|
|
||||||
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 CD media, all DVD media, all BD media.
|
|
||||||
|
|
||||||
The project comprises of several more or less interdependent parts which
|
|
||||||
together strive to be a usable foundation for application development.
|
|
||||||
These are libraries, language bindings, and middleware binaries which emulate
|
|
||||||
classical (and valuable) Linux tools.
|
|
||||||
Currently it is supported on GNU/Linux with kernels >= 2.4,
|
|
||||||
on FreeBSD with ATAPI/CAM enabled in the kernel (see man atapicam),
|
|
||||||
on OpenSolaris (tested with kernel 5.11),
|
|
||||||
on NetBSD (tested with 6.1.3).
|
|
||||||
On other X/Open compliant systems there will only be pseudo drives, but no
|
|
||||||
direct MMC operation on real CD/DVD/BD drives.
|
|
||||||
|
|
||||||
For full ports to other systems we would need : login on a development machine
|
|
||||||
or 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, DVDs and BDs.
|
|
||||||
The burn API is quite comprehensively documented and can be used to build a
|
|
||||||
presentable application.
|
|
||||||
We have a functional application 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.
|
|
||||||
An own ISO 9660 extension stores ACLs, xattr, and MD5 of file
|
|
||||||
content.
|
|
||||||
|
|
||||||
- libisoburn is an add-on to libburn and libisofs which coordinates both and
|
|
||||||
also can grow ISO-9660 filesystem images on multi-session media
|
|
||||||
as well as on overwriteable media via the same API.
|
|
||||||
All media peculiarities are handled automatically.
|
|
||||||
It also contains the methods of command oriented application
|
|
||||||
xorriso and offers them via a C language API.
|
|
||||||
|
|
||||||
- cdrskin is a limited cdrecord compatibility wrapper for libburn.
|
|
||||||
cdrecord is a powerful GPL'ed burn program included in Joerg
|
|
||||||
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 deleting, renaming, attribute
|
|
||||||
changing, incremental backups, activating boot images, and
|
|
||||||
extracting of files from ISO images to disk. There is also a
|
|
||||||
sparse emulation of cdrecord and a more laborate one of mkisofs.
|
|
||||||
All features of xorriso are also available via a C language API
|
|
||||||
of libisoburn.
|
|
||||||
A static compilation of xorriso and the libraries is dedicated
|
|
||||||
to the GNU Operating System. See xorriso/README_gnu_xorriso .
|
|
||||||
|
|
||||||
- "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).
|
|
||||||
|
|
||||||
Applications must use 64 bit off_t. E.g. by defining
|
|
||||||
#define _LARGEFILE_SOURCE
|
|
||||||
#define _FILE_OFFSET_BITS 64
|
|
||||||
or take special precautions to interface with the libraries by 64 bit integers
|
|
||||||
where the .h files prescribe off_t. To reduce libburn's off_t size to 32 bit
|
|
||||||
will keep it from processing tracks of more than 2 GB size.
|
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
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 publicly regret it and then - after i
|
|
||||||
got the opportunity to move in with cdrskin - gave me true reason to
|
|
||||||
personally apologize to Derek Foreman, Ben Jansens and the contributors at
|
|
||||||
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 upcoming 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 enable future development.
|
|
||||||
|
|
||||||
- 29th Apr 2008 libisoburn-0.1.4 was made more efficient with reading of
|
|
||||||
image tree nodes. It now depends on libisofs-0.6.4 and libburn-0.4.4.
|
|
||||||
xorriso makes use of new libisofs features by performing incremental
|
|
||||||
updates of directory trees and by cutting oversized data files into
|
|
||||||
pieces. A primitive single session emulation of cdrecord and mkisofs is
|
|
||||||
provided.
|
|
||||||
|
|
||||||
- 10th May 2008 libburn-0.4.6 supports formatting and writing of BD-RE,
|
|
||||||
full nominal speed for DVD-RAM and BD-RE. cdrskin has a unified blank
|
|
||||||
type with automatic media state recognition.
|
|
||||||
|
|
||||||
- 17th May 2008 an old bug with DVD-RAM and now with BD-RE is fixed by
|
|
||||||
libburn-0.4.8. So libisoburn can now perform emulation of multisession
|
|
||||||
on those media.
|
|
||||||
|
|
||||||
- 19th May 2008 libisoburn-0.1.6 brings better table-of-content emulation
|
|
||||||
on overwriteble media and disk files.
|
|
||||||
|
|
||||||
- 1st Jun 2008 libisofs-0.6.6 fixes some problems around device files.
|
|
||||||
|
|
||||||
- 3rd Jun 2008 libisoburn-0.1.8 fixes a bug with overwriteable media.
|
|
||||||
|
|
||||||
- 23rd Jun 2008 libisoburn-0.2.0 introduces extraction of files from
|
|
||||||
ISO images.
|
|
||||||
|
|
||||||
- 16th Jul 2008 libburn-0.5.0 handles systems with no /dev/sr* but only
|
|
||||||
/dev/scd*.
|
|
||||||
|
|
||||||
- 19th Jul 2008 libisoburn/xorriso-0.2.2 can do multi-session in mkisofs
|
|
||||||
and cdrecord style. xorriso now can serve underneath growisofs.
|
|
||||||
|
|
||||||
- 20th Aug 2008 libburn-0.5.2 revokes the necessity that a drive must be
|
|
||||||
enumerable in order to be addressable. Enumeration is enhanced by examining
|
|
||||||
/proc/sys/dev/cdrom/info.
|
|
||||||
|
|
||||||
- 24th Aug 2008 libisoburn/xorriso-0.2.4 introduces a media readability check
|
|
||||||
with data retrieval option.
|
|
||||||
|
|
||||||
- 18th Sep 2008 libisofs-0.6.8 supports ISO 9660 Level 3 which can represent
|
|
||||||
very large data files in the image.
|
|
||||||
|
|
||||||
- 20th Sep 2008 libisoburn/xorriso-0.2.6 takes into respect the new Level 3
|
|
||||||
capabilities of libisofs.
|
|
||||||
|
|
||||||
- 6th Oct 2008 libburn-0.5.4 adjusts the changes of 0.5.2 to the needs of
|
|
||||||
Linux kernel 2.4 and introduces human readable SCSI error messages.
|
|
||||||
|
|
||||||
- 6th Oct 2008 libisofs-0.6.10 fixes two bugs which prevented adding and
|
|
||||||
manipulation of ISOLINUX boot images.
|
|
||||||
|
|
||||||
- 15th Oct 2008 libisoburn/xorriso-0.2.8 can activate and maintain an
|
|
||||||
ISOLINUX boot image by an EL Torito boot record.
|
|
||||||
|
|
||||||
- 12th Nov 2008 libburn-0.5.6 fixes usage of freed memory by the fifo thread
|
|
||||||
of an aborted burn run.
|
|
||||||
|
|
||||||
- 26th Nov 2008 libisofs-0.6.12 can produce a ISOLINUX isohybrid MBR on the fly
|
|
||||||
and can produce ISO images which resemble old mkisofs images.
|
|
||||||
|
|
||||||
- 2nd Dec 2008 libisoburn-0.3.0. xorriso now is ready for exotic character
|
|
||||||
sets, for legacy FreeBSD systems which expect an outdated Rock Ridge
|
|
||||||
signature, and for producing ISO images with MBR which boot from hard disk
|
|
||||||
or USB stick. Three minor bugs were fixed.
|
|
||||||
|
|
||||||
- 7th Dec 2008 libburn-0.5.8 prevents a SIGSEGV with weird CD table-of-content
|
|
||||||
and improves BD-RE formatting.
|
|
||||||
|
|
||||||
- 9th Dec 2008 Our project received a donation from Thomas Weber.
|
|
||||||
|
|
||||||
- 2nd Jan 2009 libburn-0.6.0 learned to format BD-R and write to either
|
|
||||||
formatted or unformatted BD-R.
|
|
||||||
|
|
||||||
- 6th Jan 2009 libisoburn-0.3.2. xorriso can produce and execute commands for
|
|
||||||
mounting older sessions from all kinds of media. Pseudo-drives outside the
|
|
||||||
/dev/ tree can be addressed without prefix "stdio:".
|
|
||||||
|
|
||||||
- 20th Feb 2009 libburn-0.6.2 source release now compiles out of the box
|
|
||||||
on FreeBSD.
|
|
||||||
|
|
||||||
- 28 Feb 2009 libisofs-0.6.14 can record ACLs and Extended Attributes xattr
|
|
||||||
in its ISO images.
|
|
||||||
|
|
||||||
- 01 Mar 2009 libisoburn-0.3.4. xorriso makes use of the ACL and xattr
|
|
||||||
capabilities provided by libisofs for xorriso backup features.
|
|
||||||
|
|
||||||
- 11 Mar 2009 libisofs-0.6.16 of libisofs fixes two bugs which on Solaris
|
|
||||||
prevented to navigate the ISO images by ".." and to recognize the Rock Ridge
|
|
||||||
extensions of ISO images. The ban to build libisofs on operating systems
|
|
||||||
other than Linux and FreeBSD has been lifted.
|
|
||||||
|
|
||||||
- 13 Mar 2009 libburn-0.6.4 got a dummy adapter for SCSI/MMC command transport.
|
|
||||||
It will show no drives and thus libburn will only be able to perform
|
|
||||||
operations on "stdio:" pseudo drives. Nevertheless this was precondition
|
|
||||||
to lift the ban to build libburn on operating systems other than Linux
|
|
||||||
and FreeBSD.
|
|
||||||
|
|
||||||
- 16 Mar 2009 libisoburn-0.3.6: xorriso uses RRIP version 1.10 as default
|
|
||||||
in order to be mountable where mkisofs images are mountable.
|
|
||||||
|
|
||||||
- 17 Apr 2009 libisofs-0.6.18 introduces content filtering of data files.
|
|
||||||
Built-in filters implement compression to formats gzip and zisofs. External
|
|
||||||
filter processes can perform arbitrary data conversions like encryption.
|
|
||||||
|
|
||||||
- 19 Apr 2009 libisoburn-0.3.8 makes use of the new libisofs capability to
|
|
||||||
perform content filtering of data files.
|
|
||||||
|
|
||||||
- 08 May 2009 libburn-0.6.6 fixes a bug with aborting on broken output pipe
|
|
||||||
and a bug with device scan on FreeBSD.
|
|
||||||
|
|
||||||
- 31 May 2009 libisofs-0.6.20 can record hard link relations in ISO images
|
|
||||||
and offers support with restoring them to disk. Current Linux kernels will
|
|
||||||
mount images with such hard links but will attribute a unique inode number
|
|
||||||
to each file.
|
|
||||||
|
|
||||||
- 28 Jun 2009 libisoburn-0.4.0: xorriso can record and restore hard link
|
|
||||||
relations of files. Performance of data reading has been improved. Option
|
|
||||||
-find now supports logical operators with its tests.
|
|
||||||
|
|
||||||
- 14 Jul 2009 libburn-0.6.8 fixes bugs and shortcommings with old MMC-1 drives
|
|
||||||
and with large SCSI bus numbers as handed out by Linux for USB drives.
|
|
||||||
|
|
||||||
- 20 Jul 2009 libisoburn-0.4.0.pl01 fixes a regression in xorriso which caused
|
|
||||||
data loss in older sessions if xorriso was used underneath growisofs.
|
|
||||||
Affected are releases since libisoburn-0.3.2 in january 2009.
|
|
||||||
|
|
||||||
- 25 Aug 2009 libisofs-0.6.22 can record MD5 checksums for the whole session
|
|
||||||
and for each single data file. Checksum tags can be used to verify superblock
|
|
||||||
and directory tree before importing them.
|
|
||||||
|
|
||||||
- 27 Aug 2009 libburn-0.7.0 learned to calm down a drive and to inquire its
|
|
||||||
supported profiles. It works around some pitfalls with U3 enhanced memory
|
|
||||||
sticks which emulate a CD-ROM.
|
|
||||||
|
|
||||||
- 27 Aug 2009 libisoburn-0.4.0.pl00 can record MD5 checksums by which one may
|
|
||||||
verify the session or single data files in the image. When comparing image
|
|
||||||
files with files in the local filesystem, the MD5 sums avoid the need for
|
|
||||||
reading file content from the image.
|
|
||||||
|
|
||||||
- 22 Sep 2009 libisoburn-0.4.0.pl01 fixes a bug in xorriso option -cut_out.
|
|
||||||
|
|
||||||
- 08 Oct 2009 libisofs-0.6.24 fixes a bug which could cause the loss of blanks
|
|
||||||
in file names when a new session got added to an ISO image. With names
|
|
||||||
shorter than 251 characters this happened only to trailing blanks.
|
|
||||||
|
|
||||||
- 08 Oct 2009 libisoburn-0.4.0.pl02 fixes bugs with xorriso option -for_backup,
|
|
||||||
with xorrisofs -help, and with xorrecord -help.
|
|
||||||
|
|
||||||
- 12 Oct 2009 libburn-0.7.2 fixes a bug with CD TAO multi-track dummy sessions.
|
|
||||||
It can retrieve media product info and can process track input which was
|
|
||||||
prepared for CD-ROM XA Mode 2 Form 1. cdrskin now performs option -minfo.
|
|
||||||
|
|
||||||
- 28 Oct 2009 libisoburn-0.4.4 fixes a bug with cdrecord emulation and
|
|
||||||
introduces new information options about media type and ISO image id strings.
|
|
||||||
On Linux it helps with mounting two sessions of the same media
|
|
||||||
simultaneously.
|
|
||||||
|
|
||||||
- 12 Nov 2009 libburn-0.7.2.pl01 works around problems with Pioneer DVR-216D.
|
|
||||||
DVD-R runs made the drive stuck. Ejecting the tray did not work properly.
|
|
||||||
|
|
||||||
- 06 Dec 2009 libburn-0.7.4 works around problems with newer DVD burners,
|
|
||||||
provides throughput enhancements with hampered busses on Linux, and new
|
|
||||||
API calls to log SCSI commands and to control the libburn fifo.
|
|
||||||
|
|
||||||
- 09 Dec 2009 libisoburn-0.4.6 now offers performance tuning of output to DVD
|
|
||||||
drives or disk files.
|
|
||||||
|
|
||||||
- 26 Dec 2009 libburn-0.7.4.pl01 fixes the release tarball which was lacking
|
|
||||||
the files of the generic system adapter for X/Open.
|
|
||||||
|
|
||||||
- 29 Dec 2009 Our project received a donation for purchasing a fine small
|
|
||||||
computer which shall serve as OS farm for development and support.
|
|
||||||
|
|
||||||
- 20 Jan 2010 Version 0.6.26 of libisofs fixes minor bugs and shall enhance
|
|
||||||
portability.
|
|
||||||
|
|
||||||
- 22 Jan 2010 libburn-0.7.6 has an improved system adapter for FreeBSD,
|
|
||||||
fixes bugs about the generic X/Open system adapter, and can use
|
|
||||||
libcdio >= 0.83 as SCSI transport facility.
|
|
||||||
|
|
||||||
- 10 Feb 2010 libisofs-0.6.28 fixes a regression about bootable images which
|
|
||||||
was introduced by version 0.6.22 in August 2009.
|
|
||||||
|
|
||||||
- 23 Feb 2010 libisoburn-0.5.0 marks the transition of the xorriso standalone
|
|
||||||
version to an official GNU project. The name changed to "GNU xorriso" and its
|
|
||||||
license is now GPLv3+.
|
|
||||||
The licenses of libburnia libraries and applications are not affected by
|
|
||||||
this change.
|
|
||||||
|
|
||||||
- 10 Mar 2010 libburn-0.7.8 fixes bugs and improves the built-in abort handler
|
|
||||||
on FreeBSD.
|
|
||||||
|
|
||||||
- 30 Mar 2010 Release 0.5.2 of libisoburn provides xorriso documentation in
|
|
||||||
GNU Texinfo format with embedded extra data to derive a full man page.
|
|
||||||
|
|
||||||
- 09 Apr 2010 libburn-0.8.0 now works with ahci driver on FreeBSD 8-STABLE.
|
|
||||||
|
|
||||||
- 03 May 2010 Version 0.6.32 of libisofs is able to create ISO images with
|
|
||||||
multiple boot images. All boot catalog parameters described in El-Torito
|
|
||||||
specs can be set and inquired. This was needed to use GRUB boot images
|
|
||||||
for EFI.
|
|
||||||
|
|
||||||
- 04 May 2010 Release 0.5.6.pl00 of libisoburn makes use of the new libisofs
|
|
||||||
capabilities about boot images.
|
|
||||||
|
|
||||||
- 11 Jun 2010 libburn-0.8.2 now works on Solaris.
|
|
||||||
|
|
||||||
- 14 Jun 2010 By release 0.5.8.pl00 of libisoburn, xorriso becomes a public C
|
|
||||||
language API of libisoburn. The emulations of mkisofs and cdrecord have
|
|
||||||
been enhanced.
|
|
||||||
|
|
||||||
- Tue Jun 29 2010 Version 0.6.34 of libisofs provides new features about
|
|
||||||
hiding file names from directory trees.
|
|
||||||
|
|
||||||
- Wed Jun 30 2010 libburn-0.8.4 removes some restrictions on operating
|
|
||||||
systems other than Linux and FreeBSD.
|
|
||||||
|
|
||||||
- Fri Jul 02 2010 Release 0.6.0.pl00 of libisoburn adds more options to the
|
|
||||||
mkisofs emulation of xorriso. It also fixes minor bugs and shortcommings.
|
|
||||||
|
|
||||||
- Wed Sep 15 2010 Version 0.6.36 of libisofs can produce ISO images which
|
|
||||||
bear a partiton 1 with non-zero start address. They can be mounted from
|
|
||||||
USB stick via the main device file (e.g. /dev/sdb) as well as via the
|
|
||||||
partition device file (e.g. /dev/sdb1).
|
|
||||||
|
|
||||||
- Fri Sep 17 2010 libburn-0.8.6 lifts the test reservation on DVD-R DL media.
|
|
||||||
|
|
||||||
- Sat Sep 18 2010 Release 0.6.2.pl00 of libisoburn introduces a partition
|
|
||||||
with non-zero offset for ISO 9660 images on USB sticks, improves mkisofs
|
|
||||||
emulation, and fixes a regression which existed since version 0.4.2.
|
|
||||||
|
|
||||||
- Wed Oct 20 2010 libburn-0.8.8 can report the used amount of BD spare blocks.
|
|
||||||
|
|
||||||
- Sat Oct 23 2010 Version 0.6.38 of libisofs can use libjte to produce jigdo
|
|
||||||
files along with the ISO image. Further filesystem images may be appended
|
|
||||||
as MBR partitions 1 to 4. The capability was added to produce boot blocks
|
|
||||||
for computers with MIPS CPU.
|
|
||||||
|
|
||||||
- Tue Oct 26 2010 Release 0.6.4.pl00 of libisoburn and xorriso makes use of
|
|
||||||
the new libisofs capabilities.
|
|
||||||
|
|
||||||
- Wed Dec 08 2010 libburn-0.9.0 fixes a regression with SCSI command logging.
|
|
||||||
|
|
||||||
- Fri Dec 10 2010 Version 0.6.40 of libisofs makes the prediction of the
|
|
||||||
emerging image size less expensive and is able to make images bootable
|
|
||||||
for SUN SPARC systems.
|
|
||||||
|
|
||||||
- Sun Dec 12 2010 Release 0.6.6.pl00 of libisoburn and xorriso can read ISO
|
|
||||||
images which were copied to a different start address than they were prepared
|
|
||||||
for.
|
|
||||||
|
|
||||||
- Mon Jan 17 2011 we go for release 1.0.0. This does not indicate a
|
|
||||||
technological overhaul but shall emphasize the maturity of the software.
|
|
||||||
libisofs-1.0.0 fixes a bug about the length of ECMA-119 directory names and
|
|
||||||
is ready to store untranslated ECMA-119 names (violating the specs).
|
|
||||||
libburn-1.0.0.pl00 is now willing to create stdio-drive files with
|
|
||||||
rw-permissions for all, if umask really asks for it. cdrskin now refuses
|
|
||||||
to burn if the foreseeable size exceeds media capacity
|
|
||||||
libisoburn-1.0.0.pl00 can now create an ISO 9660:1999 directory tree,
|
|
||||||
improved the emulation fidelity of command -as mkisofs, lowered the default
|
|
||||||
abort threshold for xorriso batch mode, and increased that threshold for
|
|
||||||
xorriso dialog mode.
|
|
||||||
|
|
||||||
- Wed Feb 23 2011 release 1.0.2:
|
|
||||||
libisofs fixes several bugs and introduces the capability to copy files
|
|
||||||
inside the ISO filesystem.
|
|
||||||
libburn removed a compilation obstacle on Solaris 9 and improved recognition
|
|
||||||
of stdio pseudo-drives.
|
|
||||||
libisoburn and xorriso fix bugs and make use of the new libisofs capability.
|
|
||||||
xorriso improves its mkisofs emulation.
|
|
||||||
|
|
||||||
- Thu Mar 10 2011 release 1.0.4:
|
|
||||||
Several bugs were fixed in the libraries and in the mkisofs emulation of
|
|
||||||
xorriso. This emulation xorrisofs has now an own man page and info document.
|
|
||||||
|
|
||||||
- Sat Apr 09 2011 release 1.0.6:
|
|
||||||
libburn refined its representation of emulated drives. The size alignment
|
|
||||||
of DVD DAO is now 2 kB rather than 32 kB. libisofs produces Joliet names of
|
|
||||||
up to 103 characters. xorriso fixes two bugs and makes use of the library
|
|
||||||
improvements.
|
|
||||||
|
|
||||||
- Thu Apr 14 2011 release libisoburn-1.0.8:
|
|
||||||
A bug in the mkisofs emulation of xorriso could cause options to be ignored.
|
|
||||||
The problem was freshly introduced with libisoburn-1.0.6.
|
|
||||||
|
|
||||||
- Fri May 13 2011 release libisofs-1.0.8:
|
|
||||||
Fixes a few rarely occurring bugs that have been found during the last month.
|
|
||||||
|
|
||||||
- Sat Jun 18 2011 release 1.1.0:
|
|
||||||
The consumption of stack memory was reduced. Statical program analysis found
|
|
||||||
some rarely occurring memory leaks. Several small bugs were fixed.
|
|
||||||
The suffix .plXY was dropped from tarball names of libburn and libisoburn.
|
|
||||||
|
|
||||||
- Mon Jun 20 2011 patch release libburn-1.1.0.pl01:
|
|
||||||
libburn-1.1.0 compiled only on Linux, FreeBSD, and Solaris, but not on
|
|
||||||
other X/Open compliant systems.
|
|
||||||
|
|
||||||
- Fri Jul 08 2011 release libisofs-1.1.2 and libisoburn-1.1.2:
|
|
||||||
A severe regression was fixed in libisoburn and xorriso, which was introduced
|
|
||||||
with version 1.0.6. It caused ISO 9660 images to be unreadable if they were
|
|
||||||
written to a write-only random-access file. E.g. by: xorrisofs ... >image.iso
|
|
||||||
|
|
||||||
- Mon Aug 08 2011 release 1.1.4:
|
|
||||||
Several bugs were fixed in libburn. The most severe of them prevented xorriso
|
|
||||||
on some drives from burning mountable ISO 9660 images to CD media.
|
|
||||||
New means to list drives by their udev symbolic links help to deal with
|
|
||||||
the non-persistent drive addresses on modern GNU/Linux.
|
|
||||||
|
|
||||||
- Tue Sep 27 2011 release 1.1.6:
|
|
||||||
libisoburn now comes with a test suite. See releng/README. Bugs were fixed
|
|
||||||
in several rarely used features. Processing of ACL and extattr was enabled
|
|
||||||
on FreeBSD. Workarounds try to cope with vanishing udev links on GNU/Linux.
|
|
||||||
|
|
||||||
- Mon Nov 21 2011 release libburn-1.1.8 and libisoburn-1.1.8:
|
|
||||||
libburn avoids to close and open drive device files while operating on them.
|
|
||||||
xorriso emulation mode xorrecord now has an own manual. libburn and xorriso
|
|
||||||
were prepared to operate on qemu virtio-blk-pci devices.
|
|
||||||
|
|
||||||
- Sat Jan 28 2012 release 1.2.0:
|
|
||||||
libburn has learned to read and write CD-TEXT with CD SAO audio sessions.
|
|
||||||
It can now read CDRWIN .cue files which define pure audio or pure data
|
|
||||||
sessions. libisofs and libisoburn improved timestamp handling. Several
|
|
||||||
minor bugs were fixed.
|
|
||||||
|
|
||||||
- Mon Apr 02 2012 release 1.2.2:
|
|
||||||
The handling of intentional deviations from ECMA-119 specifications has
|
|
||||||
been improved in libisofs. libisoburn and xorriso now make use of these
|
|
||||||
improvements. Some rarely occurring bugs have been fixed.
|
|
||||||
|
|
||||||
- Fri Jul 20 2012 release 1.2.4:
|
|
||||||
libburn and libisofs got some rarely occurring bugs fixed. libisofs learned
|
|
||||||
to produce HFS+ metadata and Apple Partition Map. The capabilities of
|
|
||||||
isohybrid options --efi and --mac have been implemented (GPT and APM).
|
|
||||||
|
|
||||||
- Tue Jan 08 2013 release 1.2.6:
|
|
||||||
Small improvements were made in libburn. Minor bugs were fixed in the
|
|
||||||
libraries. xorriso improved its capabilities to serve the needs of frontend
|
|
||||||
programs. A proof of concept for a GUI frontend has been implemented:
|
|
||||||
xorriso-tcltk
|
|
||||||
|
|
||||||
- Mon Mar 18 2013 release 1.2.8:
|
|
||||||
Some rarely occurring bugs were fixed in libisofs and libburn. libburn's
|
|
||||||
handling of incomplete sessions has been improved. xorriso's mkisofs
|
|
||||||
emulation learned to set El Torito section id strings.
|
|
||||||
|
|
||||||
- Fri May 17 2013 release 1.3.0:
|
|
||||||
Several bugs were fixed in the libraries and in xorriso. The recently
|
|
||||||
introduced new boot preparation capabilities have been tested. New
|
|
||||||
boot preparation options for GRUB2 were added.
|
|
||||||
|
|
||||||
- Fri May 31 2013 patch release libburn-1.3.0.pl01:
|
|
||||||
cdrskin -msinfo on DVD and BD reported as old session start the same
|
|
||||||
number as the next writable address.
|
|
||||||
Regression introduced by version 1.2.8.
|
|
||||||
|
|
||||||
- Fri Aug 07 2013 release 1.3.2:
|
|
||||||
cdrskin has acquired the capability to copy audio tracks to .wav files.
|
|
||||||
It can extract CD-TEXT in a form that is readable for humans and for
|
|
||||||
cdrskin itself. Several small bugs were fixed in xorriso. Its capabilities
|
|
||||||
to serve frontend programs in dialog mode have been improved.
|
|
||||||
|
|
||||||
- Thu Dec 12 2013 release 1.3.4:
|
|
||||||
A long standing hidden bug was fixed, which affected inspection of
|
|
||||||
unformatted DVD+RW.
|
|
||||||
xorriso now by default puts EL Torito boot images to low block addresses.
|
|
||||||
It can report and set read speeds. Several rarely occurring bugs were fixed.
|
|
||||||
|
|
||||||
- Tue Mar 04 2014 release 1.3.6:
|
|
||||||
libburn learned to operate optical drives and media on NetBSD. libisofs got
|
|
||||||
a bug fix about HFS+ and enhancements about character set conversion.
|
|
||||||
Minor bugs were fixed in libisoburn. xorriso can now find files with names
|
|
||||||
which cannot be represented unchanged in ECMA-119, Joliet, or HFS+.
|
|
||||||
|
|
||||||
- Sat Jun 28 2014 release 1.3.8:
|
|
||||||
libburn got several bugs fixed. libisofs offers new API calls for inspection
|
|
||||||
of boot sectors in ISO 9660 filesystems. xorriso improved its support for
|
|
||||||
NetBSD, offers new features with command -find, and a command to extract
|
|
||||||
ISO 9660 file content onto standard output or into filter processes.
|
|
||||||
|
|
||||||
- Sun May 17 2015 release 1.4.0:
|
|
||||||
This release is mainly about bug fixes and a new feature of xorriso to
|
|
||||||
propose commands or as_mkisofs options which can reproduce the boot
|
|
||||||
equipment of the loaded ISO filesystem.
|
|
||||||
|
|
||||||
- Sat Nov 28 2015 release 1.4.2:
|
|
||||||
libburn got some bugs fixed and learned to inquire the drive serial number.
|
|
||||||
libisofs now sorts data file content by ECMA-119 file names for better
|
|
||||||
reproducability of ISO content. Rock Ridge filenames may be restricted to
|
|
||||||
lengths between 64 and 255 bytes. If needed, a qualified truncation happens.
|
|
||||||
xorriso now can replay boot settings when modifying ISO filesystems.
|
|
||||||
In order to avoid clogging of concurrent Linux SG_IO, xorriso got command
|
|
||||||
-modesty_on_drive to enable an old workaround from IDE master/slave days.
|
|
||||||
The source code underwent a scan by Coverity. About 150 code changes
|
|
||||||
resulted, but no easy-to-trigger bugs were found.
|
|
||||||
|
|
||||||
- Fri Jan 29 2016 patch release libburn-1.4.2.pl01:
|
|
||||||
cdrskin did not work with "-" (stdin) as input.
|
|
||||||
Regression introduced by version 1.4.2.
|
|
||||||
|
|
||||||
- Fri Jul 01 2016 release 1.4.4:
|
|
||||||
The capability to use Linux /dev/sg was revived in order to circumvent the
|
|
||||||
sr_mutex lock which hampers concurrent use of optical drives via SG_IO.
|
|
||||||
libisofs now can use appended partitions by El Torito, avoiding the need
|
|
||||||
for duplicate EFI System Partition images.
|
|
||||||
Several bugs have been fixed.
|
|
||||||
|
|
||||||
- Fri Sep 16 2016 release 1.4.6:
|
|
||||||
libburn now operates optical drives on OpenBSD. libisofs makes pseudo-random
|
|
||||||
id generation reproducible by relating it to the volume date.
|
|
||||||
xorriso interprets environment variable SOURCE_DATE_EPOCH of
|
|
||||||
reproducible-builds.org to prepare a default setting which leads to identical
|
|
||||||
ISO images on identical input and identical constant options.
|
|
||||||
Several moderately embarrassing bugs have been fixed.
|
|
||||||
|
|
||||||
- Tue Sep 12 2017 release 1.4.8:
|
|
||||||
libburn now refuses to write to SRM+POW formatted BD-R, because it would
|
|
||||||
spoil them. libisofs got several bugs fixed and offers new API calls to
|
|
||||||
support new xorriso features. libisoburn and xorriso offer more detail
|
|
||||||
control with particular boot sector types. New bugs and a regression from
|
|
||||||
version 1.4.4 were fixed.
|
|
||||||
|
|
||||||
- Sat Sep 15 2018 release 1.5.0
|
|
||||||
libisofs now can record all xattr namespaces, user defined padding was moved
|
|
||||||
after appended partitions. libisoburn and xorriso make use of the new xattr
|
|
||||||
capability of libisofs.
|
|
||||||
All three libraries got some rarely triggered bugs fixed.
|
|
||||||
|
|
||||||
- Sat Oct 26 2019 release 1.5.2
|
|
||||||
The libraries are now ready for building out-of-source. libisofs got minor
|
|
||||||
API extensions. libburn got a bug fixed which spoiled burn runs on
|
|
||||||
some MATSHITA laptop drives. It is now able to list all features which
|
|
||||||
the drive announces. xorriso can now set GPT type GUIDs with appended
|
|
||||||
partitions and the ISO partition.
|
|
||||||
All three libraries got some rarely triggered bugs fixed.
|
|
||||||
|
|
||||||
- Mon Nov 25 2019 patch release 1.5.2.pl01
|
|
||||||
cdrskin did not properly burn multiple tracks. Track 1 was slow and burning
|
|
||||||
stalled before track 2. Regression introduced by 1.5.0.
|
|
||||||
|
|
||||||
- Sat Jan 30 2021 , 07 Feb 2021 release 1.5.4
|
|
||||||
libburn offers new opportunities to influence drive speed.
|
|
||||||
libisofs got a bug fixed which under medium rare circumstances spoiled
|
|
||||||
zisofs production. libisofs switched to usage of libjte-2.0.0. Further it
|
|
||||||
can now write and read zisofs2 format, which enables compression of files
|
|
||||||
>= 4 GiB. When reading Joliet file trees, the names get stripped of their
|
|
||||||
version numbers by default. After loading metadata, libisofs can now tell
|
|
||||||
which directory tree was loaded and whether Rock Ridge is used.
|
|
||||||
libisoburn and xorriso make use of these new features.
|
|
||||||
xorriso can put out the data stream of -check_media to standard output. It
|
|
||||||
can restore files with many zero bytes as sparse files and it is able to
|
|
||||||
extract recognized boot images into data files on hard disk.
|
|
||||||
A new script xorriso-dd-target helps to put an ISO image onto an USB stick
|
|
||||||
without endangering valuable hard disk content.
|
|
||||||
Several rarely triggered bugs were fixed.
|
|
||||||
|
|
||||||
- Wed Jun 07 2023 release 1.5.6
|
|
||||||
libburn can overburn CD media, i.e. write more data than the drive announced
|
|
||||||
as medium capacity.
|
|
||||||
libisofs can assess many of the features which were in effect when a
|
|
||||||
given ISO 9660 filesystem was created. A safety limit was introduced not
|
|
||||||
to exceed the limit of Linux which is imposed on the number of SUSP CE
|
|
||||||
entries which is good for about 60 KiB of AAIP data. Some rarely occuring
|
|
||||||
bugs were fixed in libisofs.
|
|
||||||
libisoburn and xorriso expose the new library features to the user and
|
|
||||||
got some minor improvements. Many minor bugs were fixed.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License version 2 or later
|
|
||||||
as published by the Free Software Foundation.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
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 or from altered code published under GPL.
|
|
||||||
|
|
||||||
So we will not raise legal protest if you link our libraries dynamically with
|
|
||||||
applications which are not under GPL, or if you distribute our libraries
|
|
||||||
and application tools in binary form, as long as you fulfill the usual
|
|
||||||
condition of GPL to offer a copy of their source code -altered or unaltered-
|
|
||||||
under GPL.
|
|
||||||
|
|
||||||
We ask you politely to use our work in open source spirit
|
|
||||||
and with the due reference to the entire open source community.
|
|
||||||
|
|
||||||
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
|
|
||||||
Agreement joined later by: Vreixo Formoso
|
|
||||||
|
|
241
acinclude.m4
241
acinclude.m4
@ -1,241 +0,0 @@
|
|||||||
AC_DEFUN([LIBBURNIA_SET_FLAGS],
|
|
||||||
[
|
|
||||||
case $target_os in
|
|
||||||
freebsd* | netbsd*)
|
|
||||||
LDFLAGS="$LDFLAGS -L/usr/local/lib"
|
|
||||||
CPPFLAGS="$CPPFLAGS -I/usr/local/include"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
AC_DEFUN([TARGET_SHIZZLE],
|
|
||||||
[
|
|
||||||
ARCH=""
|
|
||||||
LIBBURNIA_PKGCONFDIR="$libdir"/pkgconfig
|
|
||||||
|
|
||||||
AC_MSG_CHECKING([target operating system])
|
|
||||||
|
|
||||||
libburn_check_libcam=
|
|
||||||
LIBBURNIA_LDCONFIG_CMD="echo 'No ldconfig run performed. If needed, configure manually for:'"
|
|
||||||
|
|
||||||
case $target in
|
|
||||||
*-*-linux*)
|
|
||||||
ARCH=linux
|
|
||||||
LIBBURN_ARCH_LIBS=
|
|
||||||
LIBBURNIA_LDCONFIG_CMD=ldconfig
|
|
||||||
;;
|
|
||||||
*-*-freebsd*)
|
|
||||||
ARCH=freebsd
|
|
||||||
LIBBURN_ARCH_LIBS=-lcam
|
|
||||||
LIBBURNIA_PKGCONFDIR=$(echo "$libdir" | sed 's/\/lib$/\/libdata/')/pkgconfig
|
|
||||||
;;
|
|
||||||
*-kfreebsd*-gnu*)
|
|
||||||
ARCH=freebsd
|
|
||||||
LIBBURN_ARCH_LIBS=-lcam
|
|
||||||
libburn_check_libcam=yes
|
|
||||||
;;
|
|
||||||
*-solaris*)
|
|
||||||
ARCH=solaris
|
|
||||||
LIBBURN_ARCH_LIBS=-lvolmgt
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
ARCH=
|
|
||||||
LIBBURN_ARCH_LIBS=
|
|
||||||
# AC_ERROR([You are attempting to compile for an unsupported platform])
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
AC_MSG_RESULT([$ARCH])
|
|
||||||
|
|
||||||
if test x"$libburn_check_libcam" = xyes
|
|
||||||
then
|
|
||||||
LIBBURNIA_CHECK_LIBCAM
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
dnl LIBBURN_ASSERT_VERS_LIBS is by Thomas Schmitt, libburnia project
|
|
||||||
dnl It tests whether -Wl,--version-script=... works with the compiler
|
|
||||||
AC_DEFUN([LIBBURN_ASSERT_VERS_LIBS],
|
|
||||||
[
|
|
||||||
libburnia_save_LDFLAGS="$LDFLAGS"
|
|
||||||
LDFLAGS="$LDFLAGS -Wl,--version-script=$srcdir/libburn/libburn.ver"
|
|
||||||
AC_TRY_LINK([#include <stdio.h>], [printf("Hello\n");],
|
|
||||||
[vers_libs_test="yes"], [vers_libs_test="no"])
|
|
||||||
if test x$vers_libs_test = xyes
|
|
||||||
then
|
|
||||||
LIBLDFLAGS="-Wl,--version-script=$srcdir/libburn/libburn.ver"
|
|
||||||
fi
|
|
||||||
LDFLAGS="$libburnia_save_LDFLAGS"
|
|
||||||
AC_SUBST(LIBLDFLAGS)
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
dnl LIBBURNIA_SET_PKGCONFIG determines the install directory for the *.pc file.
|
|
||||||
dnl Important: Must be performed _after_ TARGET_SHIZZLE
|
|
||||||
dnl
|
|
||||||
AC_DEFUN([LIBBURNIA_SET_PKGCONFIG],
|
|
||||||
[
|
|
||||||
### for testing --enable-libdir-pkgconfig on Linux
|
|
||||||
### LIBBURNIA_PKGCONFDIR="$libdir"data/pkgconfig
|
|
||||||
|
|
||||||
if test "x$LIBBURNIA_PKGCONFDIR" = "x$libdir"/pkgconfig
|
|
||||||
then
|
|
||||||
dummy=dummy
|
|
||||||
else
|
|
||||||
AC_ARG_ENABLE(libdir-pkgconfig,
|
|
||||||
[ --enable-libdir-pkgconfig Install to $libdir/pkgconfig on any OS, default=no],
|
|
||||||
, enable_libdir_pkgconfig="no")
|
|
||||||
AC_MSG_CHECKING([for --enable-libdir-pkgconfig])
|
|
||||||
if test "x$enable_libdir_pkgconfig" = xyes
|
|
||||||
then
|
|
||||||
LIBBURNIA_PKGCONFDIR="$libdir"/pkgconfig
|
|
||||||
fi
|
|
||||||
AC_MSG_RESULT([$enable_libdir_pkgconfig])
|
|
||||||
fi
|
|
||||||
|
|
||||||
libburnia_pkgconfig_override="no"
|
|
||||||
AC_ARG_ENABLE(pkgconfig-path,
|
|
||||||
[ --enable-pkgconfig-path=DIR Absolute path of directory for libisofs-*.pc],
|
|
||||||
libburnia_pkgconfig_override="yes" , enable_pkgconfig_path="none")
|
|
||||||
AC_MSG_CHECKING([for overridden pkgconfig directory path])
|
|
||||||
if test "x$enable_pkgconfig_path" = xno
|
|
||||||
then
|
|
||||||
libburnia_pkgconfig_override="no"
|
|
||||||
fi
|
|
||||||
if test "x$enable_pkgconfig_path" = x -o "x$enable_pkgconfig_path" = xyes
|
|
||||||
then
|
|
||||||
libburnia_pkgconfig_override="invalid argument"
|
|
||||||
fi
|
|
||||||
if test "x$libburnia_pkgconfig_override" = xyes
|
|
||||||
then
|
|
||||||
LIBBURNIA_PKGCONFDIR="$enable_pkgconfig_path"
|
|
||||||
AC_MSG_RESULT([$LIBBURNIA_PKGCONFDIR])
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT([$libburnia_pkgconfig_override])
|
|
||||||
fi
|
|
||||||
AC_SUBST(LIBBURNIA_PKGCONFDIR)
|
|
||||||
|
|
||||||
dnl For debugging only
|
|
||||||
### AC_MSG_RESULT([LIBBURNIA_PKGCONFDIR = $LIBBURNIA_PKGCONFDIR])
|
|
||||||
|
|
||||||
])
|
|
||||||
|
|
||||||
dnl LIBBURNIA_CHECK_ARCH_LIBS is by Thomas Schmitt, libburnia project
|
|
||||||
dnl It tests whether the OS dependent libraries are available.
|
|
||||||
dnl With libisoburn they are needed only for the case that indirect linking
|
|
||||||
dnl does not work. So it is worth a try to omit them.
|
|
||||||
dnl $1 = "mandatory" or "optional" define the action if test linking fails.
|
|
||||||
dnl "silent" is like "optional" but without message.
|
|
||||||
AC_DEFUN([LIBBURNIA_CHECK_ARCH_LIBS],
|
|
||||||
[
|
|
||||||
libburnia_save_LIBS="$LIBS"
|
|
||||||
if test "x$LIBBURN_ARCH_LIBS" = x
|
|
||||||
then
|
|
||||||
dummy=dummy
|
|
||||||
else
|
|
||||||
LIBS="$LIBS $LIBBURN_ARCH_LIBS"
|
|
||||||
AC_TRY_LINK([#include <stdio.h>], [printf("Hello\n");],
|
|
||||||
[archlibs_test="yes"], [archlibs_test="no"])
|
|
||||||
LIBS="$libburnia_save_LIBS"
|
|
||||||
if test x$archlibs_test = xno
|
|
||||||
then
|
|
||||||
if test x"$1" = xmandatory
|
|
||||||
then
|
|
||||||
echo >&2
|
|
||||||
echo "FATAL: Test linking with mandatory library options failed: $LIBBURN_ARCH_LIBS" >&2
|
|
||||||
echo >&2
|
|
||||||
(exit 1); exit 1;
|
|
||||||
else
|
|
||||||
if test x"$1" = xoptional
|
|
||||||
then
|
|
||||||
echo "disabled linking with $LIBBURN_ARCH_LIBS (because not found)"
|
|
||||||
fi
|
|
||||||
LIBBURN_ARCH_LIBS=""
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if test x"$1" = xsilent
|
|
||||||
then
|
|
||||||
dummy=dummy
|
|
||||||
else
|
|
||||||
echo "enabled linking with $LIBBURN_ARCH_LIBS"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
dnl LIBBURNIA_CHECK_LINUX_SCSI is by Thomas Schmitt, libburnia project
|
|
||||||
dnl
|
|
||||||
AC_DEFUN([LIBBURNIA_CHECK_LINUX_SCSI],
|
|
||||||
[
|
|
||||||
dnl Check whether it is a Linux without scsi/scsi.h
|
|
||||||
libburn_scsi_disabled=
|
|
||||||
if test x"$ARCH" = xlinux
|
|
||||||
then
|
|
||||||
AH_TEMPLATE([Libburn_use_sg_dummY],
|
|
||||||
[Define to compile without OS specific SCSI features])
|
|
||||||
AC_MSG_CHECKING([for missing scsi/scsi.h on Linux])
|
|
||||||
AC_TRY_COMPILE([
|
|
||||||
#ifdef __linux
|
|
||||||
#include <scsi/scsi.h>
|
|
||||||
#endif
|
|
||||||
],
|
|
||||||
[;],
|
|
||||||
[AC_MSG_RESULT([no])],
|
|
||||||
[AC_DEFINE([Libburn_use_sg_dummY], [yes])
|
|
||||||
libburn_scsi_disabled=yes
|
|
||||||
AC_MSG_RESULT([yes])]
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
if test x"$libburn_scsi_disabled" = xyes
|
|
||||||
then
|
|
||||||
echo "disabled operation of optical drives via SCSI"
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
dnl LIBBURNIA_CHECK_LIBCAM is by Thomas Schmitt, libburnia project
|
|
||||||
dnl
|
|
||||||
AC_DEFUN([LIBBURNIA_CHECK_LIBCAM],
|
|
||||||
[
|
|
||||||
dnl Check whether libcam is requested for FreeBSD kernel but missing
|
|
||||||
libburn_scsi_disabled=
|
|
||||||
if test x"$LIBBURN_ARCH_LIBS" = x"-lcam"
|
|
||||||
then
|
|
||||||
AH_TEMPLATE([Libburn_use_sg_dummY],
|
|
||||||
[Define to compile without OS specific SCSI features])
|
|
||||||
AC_MSG_CHECKING([for missing libcam for SCSI on FreeBSD kernel])
|
|
||||||
dnl If libcam is not available, LIBBURN_ARCH_LIBS will be made empty
|
|
||||||
LIBBURNIA_CHECK_ARCH_LIBS(silent)
|
|
||||||
if test x"$LIBBURN_ARCH_LIBS" = x
|
|
||||||
then
|
|
||||||
AC_DEFINE([Libburn_use_sg_dummY], [yes])
|
|
||||||
libburn_scsi_disabled=yes
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if test x"$LIBBURN_ARCH_LIBS" = x"-lcam"
|
|
||||||
then
|
|
||||||
AC_MSG_CHECKING([for missing libcam headers])
|
|
||||||
AC_TRY_COMPILE([
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <camlib.h>
|
|
||||||
#include <cam/scsi/scsi_message.h>
|
|
||||||
#include <cam/scsi/scsi_pass.h>
|
|
||||||
],
|
|
||||||
[;],
|
|
||||||
[AC_MSG_RESULT([no])],
|
|
||||||
[AC_DEFINE([Libburn_use_sg_dummY], [yes])
|
|
||||||
libburn_scsi_disabled=yes
|
|
||||||
AC_MSG_RESULT([yes])]
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
if test x"$libburn_scsi_disabled" = xyes
|
|
||||||
then
|
|
||||||
echo "disabled operation of optical drives via SCSI"
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
|
|
10
bootstrap
10
bootstrap
@ -1,10 +0,0 @@
|
|||||||
#!/bin/sh -x
|
|
||||||
|
|
||||||
aclocal -I .
|
|
||||||
libtoolize --copy --force
|
|
||||||
autoconf
|
|
||||||
|
|
||||||
# ts A61101 : libburn is not prepared for config.h
|
|
||||||
# autoheader
|
|
||||||
|
|
||||||
automake --foreign --add-missing --copy --include-deps
|
|
604
cdrskin/README
604
cdrskin/README
@ -1,604 +0,0 @@
|
|||||||
------------------------------------------------------------------------------
|
|
||||||
libburnia-project.org scdbackup.sourceforge.net/cdrskin_eng.html
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
cdrskin. By Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Integrated sub project of libburnia-project.org but also published via:
|
|
||||||
http://scdbackup.sourceforge.net/cdrskin_eng.html
|
|
||||||
http://scdbackup.sourceforge.net/cdrskin-1.5.7.tar.gz
|
|
||||||
|
|
||||||
Copyright (C) 2006-2023 Thomas Schmitt, provided under GPL version 2 or later.
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
cdrskin is a limited cdrecord compatibility wrapper which allows to use
|
|
||||||
most of the libburn features from the command line.
|
|
||||||
|
|
||||||
Currently it is fully supported on GNU/Linux with kernels >= 2.4, on FreeBSD,
|
|
||||||
on OpenSolaris, and on NetBSD.
|
|
||||||
IDE drives under Linux 2.4 need kernel module ide-scsi.
|
|
||||||
ATA and SATA drives under FreeBSD need kernel module atapicam.
|
|
||||||
On other X/Open compliant systems there will only be emulated drives, but no
|
|
||||||
direct MMC operation on real CD/DVD/BD drives.
|
|
||||||
|
|
||||||
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-1.5.7.tar.gz, take it to a directory of your choice and do:
|
|
||||||
|
|
||||||
tar xzf cdrskin-1.5.7.tar.gz
|
|
||||||
cd cdrskin-1.5.7
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
With that static binary you may as well do the few necessary actions manually.
|
|
||||||
If cdrskin was already installed by a previous version, or by "make install"
|
|
||||||
in the course of this installation, then find out where:
|
|
||||||
which cdrskin
|
|
||||||
Copy your standalone binary to exactly the address which you get as reply.
|
|
||||||
E.g.:
|
|
||||||
|
|
||||||
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 totally static 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'
|
|
||||||
|
|
||||||
On Linux, full and insecure enabling of both for everybody would look like
|
|
||||||
chmod a+rw /dev/sr0 /dev/hda
|
|
||||||
This is equivalent to the traditional setup chmod a+x,u+s cdrecord.
|
|
||||||
|
|
||||||
On FreeBSD, device rw-permissions are to be set in /etc/devfs.rules.
|
|
||||||
On Solaris, pfexec privileges may be restricted to "basic,sys_devices".
|
|
||||||
On NetBSD, rw-permission may be granted by chmod a+rw /dev/rcd?d.
|
|
||||||
See below "System Dependend Drive Permission Examples".
|
|
||||||
|
|
||||||
I strongly discourage to run cdrskin with setuid root or via sudo !
|
|
||||||
It is not checked for the necessary degree of hacker safety.
|
|
||||||
Better consider to grant the necessary permissions to group "floppy"
|
|
||||||
and to add users to it.
|
|
||||||
|
|
||||||
|
|
||||||
A behavioral conflict is known between any burn software and demons like hald
|
|
||||||
which probe CD drives. This can spoil burn runs for CD-R or CD-RW.
|
|
||||||
You may have to keep your hald away from the drive. See for example
|
|
||||||
http://www.freebsd.org/gnome/docs/halfaq.html
|
|
||||||
|
|
||||||
|
|
||||||
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 -minfo
|
|
||||||
|
|
||||||
Prepare CD-RW or DVD-RW for re-use, DVD-RAM or BD-RE for first use
|
|
||||||
cdrskin -v dev=/dev/sg1 blank=as_needed -eject
|
|
||||||
|
|
||||||
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 2.iso
|
|
||||||
cdrskin dev=/dev/hdc padsize=300k -multi 3.iso
|
|
||||||
cdrskin dev=/dev/hdc padsize=300k 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 \
|
|
||||||
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
|
|
||||||
|
|
||||||
Extract audio tracks and CD-TEXT from CD into directory /home/me/my_cd:
|
|
||||||
mkdir /home/me/my_cd
|
|
||||||
cdrskin -v dev=/dev/sr0 extract_audio_to=/home/me/my_cd \
|
|
||||||
cdtext_to_v07t=/home/me/my_cd/cdtext.v07t
|
|
||||||
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
On the other hand, the capability of multi-session and of writing streams
|
|
||||||
of unpredicted length 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.
|
|
||||||
Instead of "on" one may also set a start address for stream recording.
|
|
||||||
Like "stream_recording=100m". This will write slowly to the first 100 MB of
|
|
||||||
the media and accelerate when writing to higher addresses.
|
|
||||||
|
|
||||||
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 , DVD-R , DVD-R DL
|
|
||||||
|
|
||||||
DVD-RW are usable if formatted to state "Restricted Overwrite" or if in state
|
|
||||||
"Sequential Recording". DVD-R are always in sequential state. DVD-R DL are
|
|
||||||
always sequential and incapable of multi-session.
|
|
||||||
|
|
||||||
"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 preferably "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 , DVD+R DL , BD-R
|
|
||||||
|
|
||||||
From the view of cdrskin they behave much like DVD-R. Each track gets wrapped
|
|
||||||
into an own session, though.
|
|
||||||
|
|
||||||
DVD+R DL appear as extra large DVD+R. cdrskin does not allow to set the address
|
|
||||||
of the layer break where a reading drive might show some delay while switching
|
|
||||||
between both media layers.
|
|
||||||
|
|
||||||
BD-R are sold unformatted blank. If used without initial formatting then the
|
|
||||||
drive is supposed to format them to maximum payload size with no Defect
|
|
||||||
Management (see also above with BD-RE).
|
|
||||||
If Defect Management is desired then BD-R need to be formatted before the
|
|
||||||
first attempt to write a session to them.
|
|
||||||
blank=format_if_needed will detect the situation and eventually apply
|
|
||||||
default sized Defect Management formatting.
|
|
||||||
blank=format_defectmgt_* will apply non-default parameters to formatting.
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
All following options of ./configure and cdrskin/compile_cdrskin.sh are
|
|
||||||
combinable. After runs of ./configure do as next:
|
|
||||||
make clean ; make
|
|
||||||
|
|
||||||
In some situations Linux may deliver a better write performance to drives if
|
|
||||||
the track input is read with O_DIRECT (see man 2 open). The API call
|
|
||||||
burn_os_open_track_src() and the input readers of cdrskin and libburn fifo
|
|
||||||
can be told to use this peculiar read mode by:
|
|
||||||
--enable-track-src-odirect
|
|
||||||
|
|
||||||
But often cdrskin option dvd_obs=64k will yield even better performance in
|
|
||||||
such a situation. 64k can be made default at compile time by
|
|
||||||
cdrskin/compile_cdrskin.sh -dvd_obs_64k
|
|
||||||
It can also be enabled at configure time by
|
|
||||||
./configure ... --enable-dvd-obs-64k ...
|
|
||||||
|
|
||||||
Alternatively the transport of SCSI commands can be done via libcdio-0.83.
|
|
||||||
You may install it and re-run libburn's ./configure with option
|
|
||||||
--enable-libcdio
|
|
||||||
Add option
|
|
||||||
-use_libcdio
|
|
||||||
to your run of cdrskin/compile_cdrskin.sh .
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
Linux only:
|
|
||||||
|
|
||||||
libburn tries to avoid a collision with udev's drive examination by waiting
|
|
||||||
0.1 seconds before opening the device file for a longer time, after udev
|
|
||||||
might have been alarmed by drive scanning activities.
|
|
||||||
The waiting time can be set at ./configure time with microsecond granularity.
|
|
||||||
E.g. 2 seconds:
|
|
||||||
CFLAGS="$CFLAGS -DLibburn_udev_wait_useC=2000000"
|
|
||||||
./configure ...options...
|
|
||||||
Waiting can be disabled by zero waiting time:
|
|
||||||
CFLAGS="$CFLAGS -DLibburn_udev_wait_useC=0"
|
|
||||||
Alternatively, libburn can try to be nice by opening the device file,
|
|
||||||
closing it immediately, waiting, and only then opening it for real:
|
|
||||||
CFLAGS="$CFLAGS -DLibburn_udev_extra_open_cyclE -DLibburn_udev_wait_useC=500000"
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
System Dependend Drive Permission Examples
|
|
||||||
|
|
||||||
Accessing the optical drives requires privileges which usually are granted
|
|
||||||
only to the superuser. Linux, FreeBSD, Solaris, NetBSD, offer quite different
|
|
||||||
approaches for avoiding the need for unrestricted privileges.
|
|
||||||
|
|
||||||
First check whether some friendly system setting already allows you to
|
|
||||||
access the drives as normal user:
|
|
||||||
cdrskin --devices
|
|
||||||
Those drives of which you see address and type strings are already usable.
|
|
||||||
|
|
||||||
If there remain drives invisible which the superuser can see by the same
|
|
||||||
command, then the following examples might help:
|
|
||||||
|
|
||||||
---------------
|
|
||||||
On all systems:
|
|
||||||
---------------
|
|
||||||
Add the authorized users of CD drives to group "floppy" in /etc/group.
|
|
||||||
If missing: create this group.
|
|
||||||
Changes to /etc/group often only affect new login sessions. So log out and in
|
|
||||||
before making the first tests.
|
|
||||||
|
|
||||||
---------
|
|
||||||
On Linux:
|
|
||||||
---------
|
|
||||||
Allow rw-access to the drives
|
|
||||||
chgrp floppy /dev/sr0 /dev/sr1
|
|
||||||
chmod g+rw /dev/sr0 /dev/sr1
|
|
||||||
It might be necessary to perform chgrp and chmod after each reboot or to
|
|
||||||
edit distro dependent device configuration files for permanent settings.
|
|
||||||
|
|
||||||
-----------
|
|
||||||
On FreeBSD:
|
|
||||||
-----------
|
|
||||||
Edit /etc/devfs.rules and make sure to have these lines
|
|
||||||
[localrules=10]
|
|
||||||
add path 'acd*' mode 0664 group floppy
|
|
||||||
add path 'cd*' mode 0664 group floppy
|
|
||||||
add path 'pass*' mode 0664 group floppy
|
|
||||||
add path 'xpt*' mode 0664 group floppy
|
|
||||||
[localrules=5]
|
|
||||||
add path 'pass*' mode 0664 group floppy
|
|
||||||
add path 'cd*' mode 0664 group floppy
|
|
||||||
add path 'xpt*' mode 0664 group floppy
|
|
||||||
add path 'acd*' mode 0664 group floppy
|
|
||||||
|
|
||||||
Edit /etc/rc.conf and add the following line if missing
|
|
||||||
devfs_system_ruleset="localrules"
|
|
||||||
|
|
||||||
This gets into effect by reboot or by command
|
|
||||||
/etc/rc.d/devfs start
|
|
||||||
|
|
||||||
-----------
|
|
||||||
On Solaris:
|
|
||||||
-----------
|
|
||||||
Run cdrskin by
|
|
||||||
pfexec cdrskin ...arguments...
|
|
||||||
|
|
||||||
The following settings will make pfexec keep original UID and EUID and prevent
|
|
||||||
most superuser powers. Be aware that you still can manipulate all device files
|
|
||||||
if you have the file permissions for that.
|
|
||||||
Full root privileges for cdrskin can then be acquired only by command su.
|
|
||||||
|
|
||||||
Edit /etc/security/exec_attr and add this line to the other "Media Backup"
|
|
||||||
lines:
|
|
||||||
Media Backup:solaris:cmd:::/usr/local/bin/cdrskin:privs=basic,sys_devices
|
|
||||||
Edit /etc/user_attr and add profile "Media Backup" to the user's line:
|
|
||||||
thomas::::profiles=Media Backup,Primary Administrator;roles=root
|
|
||||||
See also man privileges, man exec_attr, man user_attr.
|
|
||||||
|
|
||||||
Then allow the group r-access to the drives
|
|
||||||
pfexec chgrp floppy /dev/rdsk/c3t0d0s2 /dev/rdsk/c4t0d0s2
|
|
||||||
pfexec chmod g+r /dev/rdsk/c3t0d0s2 /dev/rdsk/c4t0d0s2
|
|
||||||
The last two commands have to be executed after each boot. I do not know
|
|
||||||
the relevant device configuration files yet.
|
|
||||||
|
|
||||||
----------
|
|
||||||
On NetBSD:
|
|
||||||
----------
|
|
||||||
Allow rw-access to the drives
|
|
||||||
chgrp floppy /dev/rcd[01]d
|
|
||||||
chmod g+rw /dev/rcd[01]d
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Project aspects and legal stuff
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Important Disclaimer :
|
|
||||||
|
|
||||||
This software is provided as is. There is no warranty implied and no
|
|
||||||
protection against possible damages. You use this on your own risk.
|
|
||||||
Don't blame me or other authors of libburn if anything goes wrong.
|
|
||||||
|
|
||||||
Actually, in case of severe trouble, nearly always the drive and the media
|
|
||||||
are the cause. Any mistake of the burn program is supposed to be caught
|
|
||||||
by the drive's firmware and to lead to mere misburns.
|
|
||||||
The worst mishaps which hit the author imposed the need to reboot the
|
|
||||||
system because of drives gnawing endlessly on ill media. Permanent hardware
|
|
||||||
damage did not occur in 13 years of development. But one never knows ...
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Interested users are invited to participate in the development of cdrskin.
|
|
||||||
Contact: scdbackup@gmx.net or libburn-hackers@pykix.org .
|
|
||||||
We will keep copyright narrow but will of course acknowledge valuable
|
|
||||||
contributions in a due way.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License version 2 or later
|
|
||||||
as published by the Free Software Foundation.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
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 <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Copyright (C) 2006-2023 Mario Danic, Thomas Schmitt
|
|
||||||
|
|
||||||
libburnia-project.org is inspired by and in other components still containing
|
|
||||||
parts of
|
|
||||||
Libburn. By Derek Foreman <derek@signalmarketing.com> and
|
|
||||||
Ben Jansens <xor@orodu.net>
|
|
||||||
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
|
|
||||||
See toplevel README for an overview of the current copyright situation in
|
|
||||||
libburnia-project.org.
|
|
||||||
|
|
||||||
|
|
@ -1,248 +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 (or 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="1.5.6"
|
|
||||||
patch_level=""
|
|
||||||
# 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_dynamic="cdrskin_${skin_rev}-amd64-debian8_0"
|
|
||||||
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"/.*.swo
|
|
||||||
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
|
|
||||||
( cd cdrskin ; cc -g -Wall -o unite_html_b_line unite_html_b_line.c )
|
|
||||||
"$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")
|
|
||||||
|
|
@ -1,249 +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 (or 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="1.5.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_dynamic="cdrskin_${skin_rev}-amd64-debian8_0"
|
|
||||||
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"/.*.swo
|
|
||||||
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
|
|
||||||
|
|
||||||
( cd cdrskin ; cc -g -Wall -o unite_html_b_line unite_html_b_line.c )
|
|
||||||
"$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")
|
|
||||||
|
|
@ -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 "$@"
|
|
||||||
|
|
||||||
|
|
1343
cdrskin/cdrfifo.c
1343
cdrskin/cdrfifo.c
File diff suppressed because it is too large
Load Diff
@ -1,171 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
cdrfifo.c , Copyright 2006 - 2016 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
|
|
||||||
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 bit0= Debugging verbosity
|
|
||||||
@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 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 transferred 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 */
|
|
||||||
|
|
1876
cdrskin/cdrskin.1
1876
cdrskin/cdrskin.1
File diff suppressed because it is too large
Load Diff
10036
cdrskin/cdrskin.c
10036
cdrskin/cdrskin.c
File diff suppressed because it is too large
Load Diff
@ -1,558 +0,0 @@
|
|||||||
<HTML>
|
|
||||||
|
|
||||||
<HEAD>
|
|
||||||
<META NAME="description" CONTENT="cdrskin, a limited cdrecord compatibility wrapper for libburn">
|
|
||||||
<META NAME="keywords" CONTENT="cdrskin, libburn, libburnia, burn, CD, DVD, BD, linux, recording, burning, CD-R, CD-RW, DVD-R, DVD-R DL, DVD-RW, DVD+RW, DVD+R, DVD+R DL, DVD-RAM, BD-RE, BD-R, cdrecord, compatible, scdbackup">
|
|
||||||
<META NAME="robots" CONTENT="follow">
|
|
||||||
<TITLE>cdrskin homepage english</TITLE>
|
|
||||||
</HEAD>
|
|
||||||
|
|
||||||
<BODY BGCOLOR="#F5DEB3" TEXT=#000000 LINK=#0000A0 VLINK=#800000>
|
|
||||||
<FONT SIZE=+1>
|
|
||||||
|
|
||||||
<CENTER>
|
|
||||||
<A HREF="http://en.wikipedia.org/wiki/D%C3%B6ner_kebab">
|
|
||||||
<IMG SRC="doener_150x200_tr_octx.png" BORDER=0
|
|
||||||
ALT="cdrskin logo: Doener mit Scharf">
|
|
||||||
</A>
|
|
||||||
<P><H2> Homepage of </H2>
|
|
||||||
<H1> cdrskin </H1>
|
|
||||||
|
|
||||||
<H2>Limited cdrecord compatibility wrapper for libburn</H2>
|
|
||||||
</CENTER>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
<H2>Purpose:</H2>
|
|
||||||
Burns preformatted data to CD, DVD, and BD media:<BR>
|
|
||||||
CD-R, DVD-R, DVD-R DL, DVD+R, DVD+R DL, BD-R, CD-RW,
|
|
||||||
DVD-RW, DVD-RAM, DVD+RW, BD-RE
|
|
||||||
</P>
|
|
||||||
<P>
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<A HREF="#download">Direct hop to download links -></A>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
<H2>Hardware requirements:</H2>
|
|
||||||
About any CD, DVD, or BD recorder produced in the recent ten years.
|
|
||||||
<BR>
|
|
||||||
<A HREF="http://libburnia-project.org">libburn</A>
|
|
||||||
supports recorders which are compliant to standards MMC-1 for CD and
|
|
||||||
MMC-5 for DVD or BD. Linux, FreeBSD, Solaris, and NetBSD can communicate
|
|
||||||
with drives connected via SCSI, PATA (aka IDE, ATA), USB, or SATA.
|
|
||||||
<BR>
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
<H2>Software requirements :</H2>
|
|
||||||
<DL>
|
|
||||||
<DT>Linux with kernel 2.4 or higher (and libc, of course) :</DT>
|
|
||||||
<DD>With kernel 2.4 an ATA drive has to be under ide-scsi emulation.</DD>
|
|
||||||
<DD>With kernel 2.6 or higher the drive should not be under ide-scsi.</DD>
|
|
||||||
<DT>or FreeBSD (with libc, of course) :</DT>
|
|
||||||
<DD>ATA and SATA drives need atapicam running.</DD>
|
|
||||||
<DD>libcam has to be installed.</DD>
|
|
||||||
<DT>or Solaris (with libc, of course) :</DT>
|
|
||||||
<DD>Tested on kernel 5.11, hopefully suitable for older ones too.</DD>
|
|
||||||
<DT>or NetBSD (with libc, of course) :</DT>
|
|
||||||
<DD>Tested on 6.1.2 and 6.1.3</DD>
|
|
||||||
<DT>libpthread</DT>
|
|
||||||
<DD>is supposed to be a standard system component.</DD>
|
|
||||||
</DL>
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
<H2>
|
|
||||||
GPL software included:<BR>
|
|
||||||
</H2>
|
|
||||||
<DL>
|
|
||||||
<DT>libburn-1.5.6</DT>
|
|
||||||
<DD>(founded by Derek Foreman and Ben Jansens,
|
|
||||||
developed and maintained since August 2006 by
|
|
||||||
Thomas Schmitt from team of libburnia-project.org)
|
|
||||||
</DD>
|
|
||||||
<DD>transfers data to CD, DVD, BD</DD>
|
|
||||||
</DL>
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
This program system has been tested on Intel/AMD with Linux, FreeBSD,
|
|
||||||
OpenSolaris, and NetBSD based operating systems.<BR>
|
|
||||||
Ports to other usable systems are appreciated. Reports are welcome.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
<H2>Special features:</H2>
|
|
||||||
<UL>
|
|
||||||
<LI>Source code is independent of
|
|
||||||
<A HREF="http://cdrecord.berlios.de/old/private/cdrecord.html">cdrecord</A>
|
|
||||||
</LI>
|
|
||||||
</UL>
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
<H2>Commands:</H2>
|
|
||||||
<DL>
|
|
||||||
<DT>The most common options of cdrecord for data and audio on CD media
|
|
||||||
are provided in a compatible way.<BR>
|
|
||||||
On all DVD media, cdrskin is able to perform any recording job
|
|
||||||
which is possible with cdrecord.
|
|
||||||
Other than with cdrecord, option -multi is supported with many DVD types and
|
|
||||||
BD-R. Write mode -tao works with anything but quickly blanked DVD-RW and
|
|
||||||
DVD-R DL, which both support no -multi.
|
|
||||||
</DT>
|
|
||||||
<BR><BR>
|
|
||||||
<DT>Get an overview of drives and their addresses</DT>
|
|
||||||
<DD>#<KBD> cdrskin -scanbus</KBD></DD>
|
|
||||||
<DD>#<KBD> cdrskin dev=ATA -scanbus</KBD></DD>
|
|
||||||
<DD>#<KBD> cdrskin --devices</KBD></DD>
|
|
||||||
<DT>Being superuser avoids permission problems with /dev/srN and /dev/hdX .
|
|
||||||
</DT>
|
|
||||||
<DT>Ordinary users should then get granted access to the /dev files
|
|
||||||
as listed by option --devices. Linux, FreeBSD, and NetBSD demand rw-permission.
|
|
||||||
On Solaris it is r-permission and privileges "basic,sys_devices".</DT>
|
|
||||||
<DT> </DT>
|
|
||||||
|
|
||||||
<DT>Get info about a particular drive or loaded media:</DT>
|
|
||||||
<DD>$<KBD> cdrskin dev=0,1,0 -checkdrive</KBD></DD>
|
|
||||||
<DD>$<KBD> cdrskin dev=ATA:1,0,0 -v -atip</KBD></DD>
|
|
||||||
<DD>$<KBD> cdrskin dev=/dev/hdc -minfo</KBD></DD>
|
|
||||||
|
|
||||||
<DT>Prepare CD-RW or DVD-RW for re-use, DVD-RAM or BD-RE for first use:</DT>
|
|
||||||
<DD>$<KBD> cdrskin -v dev=/dev/sg1 blank=as_needed -eject</KBD></DD>
|
|
||||||
|
|
||||||
<DT>Format DVD-RW to avoid need for blanking before re-use:</DT>
|
|
||||||
<DD>$<KBD> cdrskin -v dev=/dev/sr0 blank=format_overwrite</KBD></DD>
|
|
||||||
|
|
||||||
<DT>De-format DVD-RW to make it capable of multi-session again:</DT>
|
|
||||||
<DD>$<KBD> cdrskin -v dev=/dev/sr0 blank=deformat_sequential</KBD></DD>
|
|
||||||
|
|
||||||
<DT>Write ISO-9660 filesystem image as only one to blank or formatted media:
|
|
||||||
</DT>
|
|
||||||
<DD>$<KBD> cdrskin -v dev=/dev/hdc speed=12 fs=8m \</KBD></DD>
|
|
||||||
<DD><KBD> blank=as_needed -eject padsize=300k my_image.iso</KBD></DD>
|
|
||||||
|
|
||||||
<DT>Write compressed afio archive on-the-fly
|
|
||||||
(not DVD-R DL or minimally blanked DVD-RW):</DT>
|
|
||||||
<DD>$<KBD> find . | afio -oZ - | \</KBD></DD>
|
|
||||||
<DD><KBD> cdrskin -v dev=0,1,0 fs=32m speed=8 \</KBD></DD>
|
|
||||||
<DD><KBD> blank=as_needed padsize=300k -</KBD></DD>
|
|
||||||
|
|
||||||
<DT>Write several sessions to the same CD, DVD-R[W] or DVD+R[/DL]:</DT>
|
|
||||||
<DD>$<KBD> cdrskin dev=/dev/hdc -v padsize=300k -multi 1.iso</KBD>
|
|
||||||
</DD>
|
|
||||||
<DD>$<KBD> cdrskin dev=/dev/hdc -v padsize=300k -multi 2.iso</KBD>
|
|
||||||
</DD>
|
|
||||||
<DD>$<KBD> cdrskin dev=/dev/hdc -v padsize=300k -multi 3.iso</KBD>
|
|
||||||
</DD>
|
|
||||||
<DD>$<KBD> cdrskin dev=/dev/hdc -v padsize=300k 4.iso</KBD></DD>
|
|
||||||
|
|
||||||
<DT>Get multi-session info for option -C of program mkisofs:</DT>
|
|
||||||
<DD>$<KBD> c_values=$(cdrskin dev=/dev/sr0 -msinfo 2>/dev/null)</KBD></DD>
|
|
||||||
<DD>$<KBD> mkisofs ... -C "$c_values" ...</KBD></DD>
|
|
||||||
|
|
||||||
<DT>Inquire free space on media for a -multi run:</DT>
|
|
||||||
<DD>$<KBD> x=$(cdrskin dev=/dev/sr0 -multi \</KBD></DD>
|
|
||||||
<DD><KBD> --tell_media_space 2>/dev/null)</KBD></DD>
|
|
||||||
<DD>$<KBD> echo "Available: $x blocks of 2048 data bytes"</KBD></DD>
|
|
||||||
|
|
||||||
<DT>Accelerate BD-RE writing to full nominal speed after the first 250 MB</DT>
|
|
||||||
<DD>$<KBD> cdrskin ... stream_recording=250m ...</KBD>
|
|
||||||
|
|
||||||
<DT>Write audio tracks to CD:</DT>
|
|
||||||
<DD>$<KBD> cdrskin -v dev=ATA:1,0,0 speed=48 -sao \</KBD></DD>
|
|
||||||
<DD><KBD> track1.wav track2.au -audio -swab track3.raw</KBD></DD>
|
|
||||||
|
|
||||||
<DT>Get overview of the cdrecord compatible options:</DT>
|
|
||||||
<DD>$<KBD> <A HREF="cdrskin_help">cdrskin -help</A></KBD></DD>
|
|
||||||
|
|
||||||
<DT>Get overview of the non-cdrecord options:</DT>
|
|
||||||
<DD>$<KBD> <A HREF="cdrskin__help">cdrskin --help</A></KBD></DD>
|
|
||||||
|
|
||||||
<DT>Read the detailed manual page:</DT>
|
|
||||||
<DD>$<KBD> <A HREF="man_1_cdrskin.html">man cdrskin</A></KBD></DD>
|
|
||||||
</DL>
|
|
||||||
<DL>
|
|
||||||
<DT>Read about the standard for which cdrskin is striving:</DT>
|
|
||||||
<DD>$<KBD>
|
|
||||||
<A HREF="http://cdrecord.berlios.de/old/private/man/cdrecord-2.0.html">
|
|
||||||
man cdrecord</A></KBD></DD>
|
|
||||||
<DD><B>Do not bother Joerg Schilling with any cdrskin problems.</B>
|
|
||||||
(Be cursed if you install cdrskin as "cdrecord" without clearly forwarding
|
|
||||||
this "don't bother Joerg" demand.)
|
|
||||||
</DD>
|
|
||||||
</DL>
|
|
||||||
<DL>
|
|
||||||
<DT>Learn to know a more versatile way to burn ISO 9660 formatted data</DT>
|
|
||||||
<DD>
|
|
||||||
Standalone ISO 9660 multi-session CD/DVD/BD tool
|
|
||||||
<A HREF="http://scdbackup.sourceforge.net/xorriso_eng.html">xorriso</A>.
|
|
||||||
</DD>
|
|
||||||
</DL>
|
|
||||||
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<A NAME="download"></A>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
<DL>
|
|
||||||
<DT>Download as source code (see README):</DT>
|
|
||||||
<DD><A HREF="cdrskin-1.5.6.tar.gz">cdrskin-1.5.6.tar.gz</A>
|
|
||||||
(1075 KB).
|
|
||||||
</DD>
|
|
||||||
<DD><A HREF="cdrskin-1.5.6.tar.gz.sig">cdrskin-1.5.6.tar.gz.sig</A></DD>
|
|
||||||
<DD>
|
|
||||||
(detached GPG signature for verification by
|
|
||||||
<KBD>gpg --verify cdrskin-1.5.6.tar.gz.sig cdrskin-1.5.6.tar.gz</KBD>
|
|
||||||
<BR>
|
|
||||||
after <KBD>gpg --keyserver keyserver.ubuntu.com --recv-keys ABC0A854</KBD>).
|
|
||||||
</DD>
|
|
||||||
<DD>
|
|
||||||
The cdrskin tarballs are source code identical with libburn releases
|
|
||||||
of the same version number.
|
|
||||||
They get produced via a different procedure, though.<BR>
|
|
||||||
cdrskin is part of libburn - full libburn is provided with cdrskin releases.
|
|
||||||
</DD>
|
|
||||||
|
|
||||||
<!-- This is not offered any more since spring 2008
|
|
||||||
<DD> </DD>
|
|
||||||
<DT>Download as single x86 binaries (untar and move to /usr/bin/cdrskin):</DT>
|
|
||||||
<DD><A HREF="cdrskin_0.4.2.pl00-x86-suse9_0.tar.gz">
|
|
||||||
cdrskin_0.4.2.pl00-x86-suse9_0.tar.gz</A>, (110 KB),
|
|
||||||
<DL>
|
|
||||||
<DD>runs on SuSE 9.0 (2.4.21) , RIP-14.4 (2.6.14) ,
|
|
||||||
Gentoo (2.6.15 x86_64 Athlon).</DD>
|
|
||||||
</DL>
|
|
||||||
<DD><A HREF="cdrskin_0.4.2.pl00-x86-suse9_0-static.tar.gz">
|
|
||||||
cdrskin_0.4.2.pl00-x86-suse9_0-static.tar.gz</A>, (310 KB), -static compiled,
|
|
||||||
<DL>
|
|
||||||
<DD>runs on SuSE 7.2 (2.4.4), and on the systems above.</DD>
|
|
||||||
</DL>
|
|
||||||
</DD>
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
</DL>
|
|
||||||
<DL><DT>Documentation:</DT>
|
|
||||||
<DD><A HREF="README_cdrskin">README</A> an introduction</DD>
|
|
||||||
<DD><A HREF="cdrskin__help">cdrskin --help</A> non-cdrecord options</DD>
|
|
||||||
<DD><A HREF="cdrskin_help">cdrskin -help</A> cdrecord compatible options</DD>
|
|
||||||
<DD><A HREF="man_1_cdrskin.html">man cdrskin</A> the manual page</DD>
|
|
||||||
<DD> </DD>
|
|
||||||
</DL>
|
|
||||||
<DL><DT>Contact:</DT>
|
|
||||||
<DD>Thomas Schmitt, <A HREF="mailto:scdbackup@gmx.net">scdbackup@gmx.net</A></DD>
|
|
||||||
<DD>GNU xorriso mailing list, where cdrskin and libburn are on topic, too:
|
|
||||||
<A HREF="mailto:bug-xorriso@gnu.org">bug-xorriso@gnu.org</A></DD>
|
|
||||||
</DL>
|
|
||||||
<DL><DT>License:</DT>
|
|
||||||
<DD><A HREF="COPYING_cdrskin">GPL</A>, an <A HREF="http://www.opensource.org/">Open Source</A> approved license</DD>
|
|
||||||
<DD> </DD>
|
|
||||||
</DL>
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
Enhancements towards previous stable version cdrskin-1.5.4:
|
|
||||||
<UL>
|
|
||||||
<LI>New cdrskin option --bdr_obs_exempt</LI>
|
|
||||||
<LI>Officially enabled overburning on CD media</LI>
|
|
||||||
<!--
|
|
||||||
<LI>none</LI>
|
|
||||||
-->
|
|
||||||
</UL>
|
|
||||||
|
|
||||||
Bug fixes towards cdrskin-1.5.4:
|
|
||||||
<UL>
|
|
||||||
<LI>Overburning with cdrskin option -force ended by a libburn error</LI>
|
|
||||||
</UL>
|
|
||||||
<!--
|
|
||||||
-->
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
<DL>
|
|
||||||
<DT><H3>Development snapshot, version 1.5.7 :</H3></DT>
|
|
||||||
<DD>Enhancements towards current stable version 1.5.6:
|
|
||||||
<UL>
|
|
||||||
<LI>none yet</LI>
|
|
||||||
<!--
|
|
||||||
<LI>none yet</LI>
|
|
||||||
-->
|
|
||||||
</UL>
|
|
||||||
Bug fixes towards cdrskin-1.5.6:
|
|
||||||
<UL>
|
|
||||||
<LI>none yet</LI>
|
|
||||||
<!--
|
|
||||||
<LI>none yet</LI>
|
|
||||||
-->
|
|
||||||
</UL>
|
|
||||||
</DD>
|
|
||||||
|
|
||||||
<DD> </DD>
|
|
||||||
<DD><A HREF="README_cdrskin_devel">README 1.5.7</A>
|
|
||||||
<DD><A HREF="cdrskin__help_devel">cdrskin-1.5.7 --help</A></DD>
|
|
||||||
<DD><A HREF="cdrskin_help_devel">cdrskin-1.5.7 -help</A></DD>
|
|
||||||
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 1.5.7)</A></DD>
|
|
||||||
<DD> </DD>
|
|
||||||
<DT>Maintainers of cdrskin unstable packages please use git of
|
|
||||||
<A HREF="http://libburnia-project.org"> libburnia-project.org</A></DT>
|
|
||||||
<DD>Download: <KBD>
|
|
||||||
<B>git clone https://dev.lovelyhq.com/libburnia/libburn.git</B>
|
|
||||||
</KBD></DD>
|
|
||||||
<DD>Build: <KBD><B>cd libburn ; ./bootstrap ; ./configure --prefix /usr ; make ; cdrskin/compile_cdrskin.sh</B>
|
|
||||||
</KBD></DD>
|
|
||||||
<DD>Build of SVN versions needs <A HREF="http://sources.redhat.com/autobook/">
|
|
||||||
autotools</A> of at least version 1.7 installed.
|
|
||||||
But after the run of <KBD>./bootstrap</KBD>, only
|
|
||||||
vanilla tools like make and gcc are needed.</DD>
|
|
||||||
</DD>
|
|
||||||
<DD> </DD>
|
|
||||||
<DT>The following download is intended for adventurous end users or
|
|
||||||
admins with full system sovereignty.</DT>
|
|
||||||
<DD>Source (./bootstrap is already applied, build tested, for more see
|
|
||||||
<A HREF="README_cdrskin_devel">upcoming README</A> ):
|
|
||||||
</DD>
|
|
||||||
<DD>
|
|
||||||
<A HREF="cdrskin-1.5.7.tar.gz">cdrskin-1.5.7.tar.gz</A>
|
|
||||||
(1075 KB).
|
|
||||||
</DD>
|
|
||||||
|
|
||||||
<!-- This is not offered any more since spring 2008
|
|
||||||
|
|
||||||
<DT>The following downloads are intended for adventurous end users or
|
|
||||||
admins with full system souvereignty.</DT>
|
|
||||||
<DD>Binary (untar and move to /usr/bin/cdrskin):</DD>
|
|
||||||
<DD><A HREF="cdrskin_0.4.3-x86-suse9_0.tar.gz">
|
|
||||||
cdrskin_0.4.3-x86-suse9_0.tar.gz</A>, (110 KB).
|
|
||||||
</DD>
|
|
||||||
<DD><A HREF="cdrskin_0.4.3-x86-suse9_0-static.tar.gz">
|
|
||||||
cdrskin_0.4.3-x86-suse9_0-static.tar.gz</A>, (310 KB)
|
|
||||||
</DD>
|
|
||||||
-->
|
|
||||||
|
|
||||||
</DL>
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
Many thanks to Joerg Schilling for cdrecord,
|
|
||||||
<BR>
|
|
||||||
and to Derek Foreman and Ben Jansens for creating libburn.
|
|
||||||
<BR>
|
|
||||||
Historic versions based on Derek's and Ben's
|
|
||||||
<A HREF="http://icculus.org/burn">icculus.org/burn</A> :<BR>
|
|
||||||
<A HREF="cdrskin-0.1.2.0.2.ts.tar.gz">cdrskin-0.1.2.0.2.ts.tar.gz</A><BR>
|
|
||||||
<A HREF="cdrskin-0.1.3.0.2.ts.tar.gz">cdrskin-0.1.3.0.2.ts.tar.gz</A>
|
|
||||||
<BR>
|
|
||||||
Very special thanks to Andy Polyakov whose
|
|
||||||
<A HREF="http://fy.chalmers.se/~appro/linux/DVD+RW/tools">dvd+rw-tools</A>
|
|
||||||
provide libburn with invaluable examples on how to deal with DVD and BD media.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<A NAME="examples">
|
|
||||||
<P>
|
|
||||||
<DL>
|
|
||||||
<DT>Example for a setup of device permissions.</DT>
|
|
||||||
<DT>
|
|
||||||
Newer Linux distros enable rw-access for the desktop user automatically.
|
|
||||||
So try as normal user whether all your drives are found.
|
|
||||||
CD devices which offer no rw-permission will stay invisible.
|
|
||||||
</DT>
|
|
||||||
<DD>$ <KBD><B>cdrskin --devices</B></KBD></DD>
|
|
||||||
<DT>If not all desired drives show up, become superuser and do again:</DT>
|
|
||||||
</DT>
|
|
||||||
<DD># <KBD><B>cdrskin --devices</B></KBD></DD>
|
|
||||||
<DD><KBD>...</KBD></DD>
|
|
||||||
<DD><KBD>0 dev='/dev/sr0' rwr-r- : 'TEAC' 'CD-ROM CD-532S'</KBD></DD>
|
|
||||||
<DD><KBD>1 dev='/dev/hdc' rwrw-- : 'LITE-ON' 'LTR-48125S'</KBD></DD>
|
|
||||||
<DT>Most simple and most insecure is this equivalent
|
|
||||||
of the usual cdrecord permissions u+s,a+x:</DT>
|
|
||||||
<DD># <KBD><B>chmod a+rw /dev/sr0 /dev/hdc</B></KBD></DD>
|
|
||||||
<DT>
|
|
||||||
More secure is to put the permitted users into a group like
|
|
||||||
"floppy", to assign /dev/sr0 /dev/hdc to this group,
|
|
||||||
and to allow rw-access only to group members.
|
|
||||||
</DT>
|
|
||||||
<DD># <KBD><B>vi /etc/group</B></KBD></DD>
|
|
||||||
<DD><KBD>...</KBD></DD>
|
|
||||||
<DD><KBD>floppy:x:19:thomas,scdbackup</KBD></DD>
|
|
||||||
<DD><KBD>...</KBD></DD>
|
|
||||||
<DD># <KBD><B>chgrp floppy /dev/sr0 /dev/hdc</B></KBD></DD>
|
|
||||||
<DD># <KBD><B>chmod g+rw /dev/sr0 /dev/hdc</B></KBD></DD>
|
|
||||||
</DL>
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<A NAME="k3b">
|
|
||||||
<P>
|
|
||||||
<A HREF="k3b_on_cdrskin.html">
|
|
||||||
Example how to setup K3b to use cdrskin for burning data CD projects.
|
|
||||||
<A><BR>
|
|
||||||
(<A HREF="http://www.k3b.org">K3b</A>
|
|
||||||
is a GUI frontend which uses cdrecord for CD burning.)
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<A NAME="scdbackup">
|
|
||||||
<P>
|
|
||||||
<DL>
|
|
||||||
<DT>Example for a test session with a cdrecord based scdbackup installation:</DT>
|
|
||||||
<DD>$ <KBD><B>cdrskin -scanbus</B></KBD></DD>
|
|
||||||
<DD><KBD>...</KBD></DD>
|
|
||||||
<DD><KBD> 2,0,0 0) 'TEAC' 'CD-ROM CD-532S' '?' Removable CD-ROM</KBD></DD>
|
|
||||||
<DD>$ <KBD><B>cdrskin -scanbus dev=ATA</B></KBD></DD>
|
|
||||||
<DD><KBD>...</KBD></DD>
|
|
||||||
<DD><KBD> 1,0,0 1) 'LITE-ON' 'LTR-48125S' '?' Removable CD-ROM</KBD></DD>
|
|
||||||
<DD>$ <KBD><B>export SCDBACKUP_SCSI_ADR="ATA:1,0,0"</B></KBD></DD>
|
|
||||||
<DD>$ <KBD><B>export SCDBACKUP_CDRECORD="cdrskin -v -v"</B></KBD></DD>
|
|
||||||
<DD>$ <KBD><B>scdbackup_home</B></KBD></DD>
|
|
||||||
</DL>
|
|
||||||
<DL>
|
|
||||||
<DT>Example for a permanent configuration of cdrskin based scdbackup</DT>
|
|
||||||
<DD>$ <KBD><B>cd scdbackup-0.8.6/inst</B></KBD></DD>
|
|
||||||
<DD>$ <KBD><B>export SCDBACKUP_USE_CDRSKIN=1</B></KBD></DD>
|
|
||||||
<DD>$ <KBD><B>./CONFIGURE_CD</B></KBD></DD>
|
|
||||||
<DD><KBD>...</KBD></DD>
|
|
||||||
<DD><KBD>cdrskin 0.3.8 : limited cdrecord compatibility wrapper for libburn</KBD></DD>
|
|
||||||
</DL>
|
|
||||||
If your system is stricken with some ill CD device then this can stall
|
|
||||||
and you will have to press <KBD>Ctrl+C</KBD> to abort.
|
|
||||||
In this case, you may execute
|
|
||||||
<KBD>export SCDBACKUP_NO_SCANBUS=1</KBD>
|
|
||||||
and try again.
|
|
||||||
<DL>
|
|
||||||
<DT></DT>
|
|
||||||
<DD><KBD> ------------------- SCSI devices. To be used like 0,0,0</KBD></DD>
|
|
||||||
<DD><KBD> 2,0,0 0) 'TEAC' 'CD-ROM CD-532S' '?' Removable CD-ROM</KBD></DD>
|
|
||||||
<DD><KBD> ------------------- end of SCSI device list</KBD></DD>
|
|
||||||
<DD><KBD> ------------------- ATA devices. To be used like ATA:0,0,0
|
|
||||||
<DD><KBD> 1,0,0 1) 'LITE-ON' 'LTR-48125S' '?' Removable CD-ROM</KBD></DD>
|
|
||||||
<DD><KBD>...</KBD></DD>
|
|
||||||
<DD><KBD> * Your cdrecord offers -driveropts=burnfree with your recorder.</KBD></DD>
|
|
||||||
<DD><KBD>...</KBD></DD>
|
|
||||||
<DD><KBD>scdbackup for CD 0.8.6 : First stage of installation done.</KBD></DD>
|
|
||||||
<DD><KBD>...</KBD></DD>
|
|
||||||
<DD><KBD>Now give it a try. Run : scdbackup_home</KBD></DD>
|
|
||||||
<DD>$ <KBD><B>unset SCDBACKUP_USE_CDRSKIN</B></KBD></DD>
|
|
||||||
</DL>
|
|
||||||
<DL>
|
|
||||||
<DT>To get back to using cdrecord :</DT>
|
|
||||||
<DD>$ <KBD><B>cd scdbackup-0.8.6/inst</B></KBD></DD>
|
|
||||||
<DD>$ <KBD><B>export SCDBACKUP_USE_CDRSKIN=0</B></KBD></DD>
|
|
||||||
<DD>$ <KBD><B>./CONFIGURE_CD</B></KBD></DD>
|
|
||||||
<DD><KBD>...</KBD></DD>
|
|
||||||
<DD>$ <KBD><B>unset SCDBACKUP_USE_CDRSKIN</B></KBD></DD>
|
|
||||||
</DL>
|
|
||||||
</P>
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<A NAME="cdrecord">
|
|
||||||
<P>
|
|
||||||
<CENTER><H3>About the relationship of cdrecord and cdrskin</H3></CENTER>
|
|
||||||
First of all: this relationship is single sided, as cdrskin has to be aware of
|
|
||||||
cdrecord but not vice versa.
|
|
||||||
<BR>
|
|
||||||
<BR>
|
|
||||||
I was a long time user of cdrecord and it worked fine for me.
|
|
||||||
Especially i do appreciate its write mode -tao which can pipe arbitrary
|
|
||||||
data on CD and CD-RW via stdin. cdrecord is reliable, versatile and well
|
|
||||||
maintained. So for me - there would be no problem with using it for
|
|
||||||
burning CDs.
|
|
||||||
<BR>
|
|
||||||
But the author of cdrecord and the Linux kernel people foster a very hostile
|
|
||||||
relationship. Ok, that's their business, not mine (or ours if you are with me).
|
|
||||||
One has to be aware, though, that this relationship might lead to a situation
|
|
||||||
where cdrecord is no longer available for certain Linux kernels.
|
|
||||||
<BR>
|
|
||||||
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.
|
|
||||||
<BR>
|
|
||||||
<BR>
|
|
||||||
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.
|
|
||||||
<BR>
|
|
||||||
<BR>
|
|
||||||
It is very important to me that this project is not perceived as hostile
|
|
||||||
towards Joerg Schilling and his work.
|
|
||||||
I owe him much. For cdrecord, for mkisofs, for star. Chapeau.
|
|
||||||
<BR>
|
|
||||||
</P>
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<CENTER><FONT SIZE=+0>
|
|
||||||
<!-- <A NAME="bottom" HREF="main_ger.html#bottom">deutsch (german)</A>
|
|
||||||
<BR><BR>
|
|
||||||
-->
|
|
||||||
<A HREF="http://en.wikipedia.org/wiki/D%C3%B6ner_kebab">
|
|
||||||
<IMG SRC="doener_150x200_tr.png" BORDER=0
|
|
||||||
ALT="cdrskin logo: Doener mit Scharf"></A>
|
|
||||||
<BR><BR>
|
|
||||||
<FONT SIZE=+0>Enjoying free Open Source hosting by <A HREF="http://www.webframe.org">www.webframe.org</A><BR>
|
|
||||||
<A HREF="http://www.webframe.org">
|
|
||||||
<IMG SRC="msfree.gif" ALT="100 % Microsoft free" BORDER=0></A><BR>
|
|
||||||
and by <A HREF="http://sourceforge.net">sourceforge.net</A><BR>
|
|
||||||
<A href="http://sourceforge.net">
|
|
||||||
<IMG src="sflogo-88-1.png" BORDER="0" ALT="SourceForge Logo"></A>
|
|
||||||
<!-- on sourceforge use : <IMG src="http://sourceforge.net/sflogo.php?group_id=16010" width="88" height="31" border="0" alt="SourceForge Logo"></A> -->
|
|
||||||
|
|
||||||
<!--
|
|
||||||
<P>
|
|
||||||
Enjoying a FreeBSD shell account with the opportunity to
|
|
||||||
build and install cdrskin at<BR>
|
|
||||||
<A HREF="http://www.en.free-shells.com.ar">free-shells.com.ar</A>
|
|
||||||
</P>
|
|
||||||
-->
|
|
||||||
|
|
||||||
</FONT></CENTER>
|
|
||||||
<HR>
|
|
||||||
<DL>
|
|
||||||
<DT>Links to my other published software projects :
|
|
||||||
<DD><A HREF="http://scdbackup.webframe.org/xorriso_eng.html">
|
|
||||||
xorriso, a standalone ISO 9660 multi-session CD/DVD/BD burn tool.
|
|
||||||
No mkisofs needed.
|
|
||||||
<DL>
|
|
||||||
<DD>
|
|
||||||
<A HREF="http://scdbackup.sourceforge.net/xorriso_eng.html">
|
|
||||||
(a second source of above)</A>
|
|
||||||
</DD>
|
|
||||||
</DL>
|
|
||||||
</DD>
|
|
||||||
<DD><A HREF=http://scdbackup.webframe.org/main_eng.html>
|
|
||||||
scdbackup, multi volume CD backup</A>
|
|
||||||
<DL><DD><A HREF=http://scdbackup.sourceforge.net/main_eng.html>
|
|
||||||
(a second source of above)</A></DD></DL></DD>
|
|
||||||
<DD><A HREF=http://stic.sourceforge.net>Some Tools for Image Collectors</A>
|
|
||||||
</DD>
|
|
||||||
<DD><A HREF=http://scdbackup.webframe.org/pppoem>
|
|
||||||
pppoem, a DSL throughput monitor (mainly for Linux kernel 2.4)</A>
|
|
||||||
</DD>
|
|
||||||
</DL>
|
|
||||||
<BR><BR>
|
|
||||||
Legal statement: This website does not serve any commercial purpose.<BR>
|
|
||||||
</FONT>
|
|
||||||
</BODY>
|
|
||||||
</HTML>
|
|
@ -1 +0,0 @@
|
|||||||
#define Cdrskin_timestamP "2024.09.20.162105"
|
|
14405
cdrskin/changelog.txt
14405
cdrskin/changelog.txt
File diff suppressed because it is too large
Load Diff
@ -1,216 +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;
|
|
||||||
printf("Strange: The system ignored a SIGSEGV: c= %u\n", (unsigned int) c);
|
|
||||||
} else {
|
|
||||||
printf("killme: %d\n",getpid());
|
|
||||||
sleep(3600);
|
|
||||||
}
|
|
||||||
|
|
||||||
Cleanup_set_handlers(NULL,NULL,1);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* Cleanup_standalonE */
|
|
@ -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 */
|
|
||||||
|
|
@ -1,245 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# compile_cdrskin.sh
|
|
||||||
# Copyright 2005 - 2023 Thomas Schmitt, scdbackup@gmx.net, GPL v2 or later
|
|
||||||
# to be executed within ./libburn-* or./cdrskin-*
|
|
||||||
|
|
||||||
debug_opts="-O2"
|
|
||||||
def_opts=
|
|
||||||
largefile_opts="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1"
|
|
||||||
fifo_opts=""
|
|
||||||
libvers="-DCdrskin_libburn_1_5_6"
|
|
||||||
|
|
||||||
# To be used if Makefile.am uses libburn_libburn_la_CFLAGS
|
|
||||||
# burn="libburn/libburn_libburn_la-"
|
|
||||||
burn="libburn/"
|
|
||||||
|
|
||||||
cleanup_src_or_obj="$burn"cleanup.o
|
|
||||||
libdax_msgs_o="$burn"libdax_msgs.o
|
|
||||||
libdax_audioxtr_o="$burn"libdax_audioxtr.o
|
|
||||||
do_strip=0
|
|
||||||
static_opts=
|
|
||||||
warn_opts="-Wall -Wextra -Wno-unused-parameter"
|
|
||||||
libcdio=
|
|
||||||
fifo_source="cdrskin/cdrfifo.c"
|
|
||||||
compile_cdrskin=1
|
|
||||||
compile_cdrfifo=0
|
|
||||||
compile_dewav=0
|
|
||||||
|
|
||||||
libcam=
|
|
||||||
os=$(uname -s)
|
|
||||||
case $os in
|
|
||||||
*FreeBSD)
|
|
||||||
libcam="-lcam"
|
|
||||||
esac
|
|
||||||
|
|
||||||
for i in "$@"
|
|
||||||
do
|
|
||||||
if test "$i" = "-compile_cdrfifo"
|
|
||||||
then
|
|
||||||
compile_cdrfifo=1
|
|
||||||
elif test "$i" = "-compile_dewav"
|
|
||||||
then
|
|
||||||
compile_dewav=1
|
|
||||||
elif test "$i" = "-libburn_1_5_6"
|
|
||||||
then
|
|
||||||
libvers="-DCdrskin_libburn_1_5_6"
|
|
||||||
libdax_audioxtr_o="$burn"libdax_audioxtr.o
|
|
||||||
libdax_msgs_o="$burn"libdax_msgs.o
|
|
||||||
cleanup_src_or_obj="$burn"cleanup.o
|
|
||||||
elif test "$i" = "-libburn_svn"
|
|
||||||
then
|
|
||||||
libvers="-DCdrskin_libburn_1_5_7"
|
|
||||||
libdax_audioxtr_o="$burn"libdax_audioxtr.o
|
|
||||||
libdax_msgs_o="$burn"libdax_msgs.o
|
|
||||||
cleanup_src_or_obj="$burn"cleanup.o
|
|
||||||
elif test "$i" = "-newapi" -o "$i" = "-experimental"
|
|
||||||
then
|
|
||||||
def_opts="$def_opts -DCdrskin_new_api_tesT"
|
|
||||||
elif test "$i" = "-no_largefile"
|
|
||||||
then
|
|
||||||
largefile_opts=
|
|
||||||
elif test "$i" = "-dvd_obs_64k"
|
|
||||||
then
|
|
||||||
def_opts="$def_opts -DCdrskin_dvd_obs_default_64K"
|
|
||||||
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" = "-use_libburn_fifo"
|
|
||||||
then
|
|
||||||
fifo_opts="-DCdrskin_use_libburn_fifO"
|
|
||||||
elif test "$i" = "-use_no_libburn_fifo"
|
|
||||||
then
|
|
||||||
fifo_opts=""
|
|
||||||
elif test "$i" = "-use_no_cdrfifo"
|
|
||||||
then
|
|
||||||
fifo_source=
|
|
||||||
fifo_opts="-DCdrskin_use_libburn_fifO -DCdrskin_no_cdrfifO"
|
|
||||||
elif test "$i" = "-use_libburn_cleanup"
|
|
||||||
then
|
|
||||||
fifo_source=
|
|
||||||
fifo_opts="-DCdrskin_use_libburn_cleanuP -DCdrskin_use_libburn_fifO -DCdrskin_no_cdrfifO"
|
|
||||||
elif test "$i" = "-use_libcdio"
|
|
||||||
then
|
|
||||||
libcdio="-lcdio"
|
|
||||||
elif test "$i" = "-g"
|
|
||||||
then
|
|
||||||
debug_opts="-g"
|
|
||||||
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 " -libburn_1_5_6 set macro to match libburn-1.5.6"
|
|
||||||
echo " -libburn_svn set macro to match current libburn git."
|
|
||||||
echo " -dvd_obs_64k 64 KB default size for DVD/BD writing."
|
|
||||||
echo " -use_libcdio link with -lcdio because libburn uses it."
|
|
||||||
echo " -do_not_compile_cdrskin omit compilation of cdrskin/cdrskin."
|
|
||||||
echo " -use_no_libburn_fifo use cdrfifo even for single track non-CD"
|
|
||||||
echo " -use_no_cdrfifo always use fifo of libburn and never cdrfifo"
|
|
||||||
echo " -experimental use newly introduced libburn features."
|
|
||||||
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 $fifo_source $static_opts $debug_opts $libvers $fifo_opts $def_opts $cleanup_src_or_obj $libcdio $libcam"
|
|
||||||
cc -I. \
|
|
||||||
$warn_opts \
|
|
||||||
$static_opts \
|
|
||||||
$debug_opts \
|
|
||||||
$libvers \
|
|
||||||
$largefile_opts \
|
|
||||||
$fifo_opts \
|
|
||||||
$def_opts \
|
|
||||||
\
|
|
||||||
-DCdrskin_build_timestamP='"'"$timestamp"'"' \
|
|
||||||
\
|
|
||||||
-o cdrskin/cdrskin \
|
|
||||||
\
|
|
||||||
cdrskin/cdrskin.c \
|
|
||||||
$fifo_source \
|
|
||||||
\
|
|
||||||
$cleanup_src_or_obj \
|
|
||||||
\
|
|
||||||
"$burn"async.o \
|
|
||||||
"$burn"cdtext.o \
|
|
||||||
"$burn"debug.o \
|
|
||||||
"$burn"drive.o \
|
|
||||||
"$burn"file.o \
|
|
||||||
"$burn"init.o \
|
|
||||||
"$burn"options.o \
|
|
||||||
"$burn"source.o \
|
|
||||||
"$burn"structure.o \
|
|
||||||
\
|
|
||||||
"$burn"sg.o \
|
|
||||||
"$burn"write.o \
|
|
||||||
"$burn"read.o \
|
|
||||||
$libdax_audioxtr_o \
|
|
||||||
$libdax_msgs_o \
|
|
||||||
\
|
|
||||||
"$burn"mmc.o \
|
|
||||||
"$burn"sbc.o \
|
|
||||||
"$burn"spc.o \
|
|
||||||
"$burn"util.o \
|
|
||||||
\
|
|
||||||
"$burn"sector.o \
|
|
||||||
"$burn"toc.o \
|
|
||||||
\
|
|
||||||
"$burn"crc.o \
|
|
||||||
"$burn"ecma130ab.o \
|
|
||||||
\
|
|
||||||
$libcdio \
|
|
||||||
$libcam \
|
|
||||||
-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 \
|
|
||||||
"$burn"libdax_audioxtr.o \
|
|
||||||
"$burn"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.'
|
|
@ -1,82 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
#
|
|
||||||
# convert_man_to_html.sh - ts A61214 , B50802
|
|
||||||
#
|
|
||||||
# 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/<meta name="generator" content="groff -Thtml, see www.gnu.org">/<meta name="generator" content="groff -Thtml, via man -H, via cdrskin\/convert_man_to_html.sh">/' \
|
|
||||||
-e 's/<meta name="Content-Style" content="text\/css">/<meta name="Content-Style" content="text\/css"><META NAME="description" CONTENT="man page of cdrskin"><META NAME="keywords" CONTENT="man cdrskin, manual, cdrskin, CD-RW, CD-R, DVD-R, DVD-RW, DVD+R, DVD+RW, BD-R, BD-RE, burning, cdrecord, compatible"><META NAME="robots" CONTENT="follow">/' \
|
|
||||||
-e 's/<title>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>/<b>Overview of features:<\/b><BR>/' \
|
|
||||||
-e 's/<b>General information paragraphs:<\/b>/<b>General information paragraphs:<\/b><BR>/' \
|
|
||||||
-e 's/<b>Track recording model:<\/b>/\ <BR><b>Track recording model:<\/b><BR>/' \
|
|
||||||
-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>/<b>Write mode selection:<\/b><BR>/' \
|
|
||||||
-e 's/<b>Recordable CD Media:<\/b>/<b>Recordable CD Media:<\/b><BR>/' \
|
|
||||||
-e 's/<b>Overwriteable DVD or BD Media:<\/b>/<b>Overwriteable DVD or BD Media:<\/b><BR>/' \
|
|
||||||
-e 's/<b>Sequentially Recordable DVD or BD Media:<\/b>/<b>Sequentially Recordable DVD or BD Media:<\/b><BR>/' \
|
|
||||||
-e 's/^The write modes for DVD+R/\ <BR>The write modes for DVD+R/' \
|
|
||||||
-e 's/<b>Drive preparation and addressing:<\/b>/<b>Drive preparation and addressing:<\/b><BR>/' \
|
|
||||||
-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>/<b>Emulated drives:<\/b><BR>/' \
|
|
||||||
-e 's/for normal use: <b><br>/for normal use: <b><br><BR>/' \
|
|
||||||
-e 's/original cdrecord by Joerg Schilling:<\/p>/original cdrecord by Joerg Schilling:<\/p><BR>/' \
|
|
||||||
-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>/' \
|
|
||||||
-e 's/−/-/g' \
|
|
||||||
<"$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"
|
|
||||||
export BROWSER=$(pwd)/'cdrskin/unite_html_b_line "%s" '"$raw_html"
|
|
||||||
man -H "$manpage"
|
|
||||||
# cp "$raw_html" /tmp/x.html
|
|
||||||
"$0" -work_as_filter "$raw_html"
|
|
||||||
rm "$raw_html"
|
|
||||||
rm "$man_dir"/man1
|
|
||||||
|
|
||||||
fi
|
|
Binary file not shown.
Before Width: | Height: | Size: 10 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.2 KiB |
@ -1,9 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Create version timestamp cdrskin/cdrskin_timestamp.h
|
|
||||||
# to be executed within ./libburn-* or ./cdrskin-*
|
|
||||||
|
|
||||||
timestamp="$(date -u '+%Y.%m.%d.%H%M%S')"
|
|
||||||
echo "Version timestamp : $timestamp"
|
|
||||||
echo '#define Cdrskin_timestamP "'"$timestamp"'"' >cdrskin/cdrskin_timestamp.h
|
|
||||||
|
|
@ -1,124 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
( cd cdrskin ; cc -g -Wall -o unite_html_b_line unite_html_b_line.c )
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
Specialized converter for the output of man -H,
|
|
||||||
which unites lines where the line end is between <b> and </b>.
|
|
||||||
|
|
||||||
Copyright 2015 Thomas Schmitt, <scdbackup@gmx.net>
|
|
||||||
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
|
|
||||||
int unite_lines(char *buffer, int *b_open, int *b_state, int flag)
|
|
||||||
{
|
|
||||||
char *cpt;
|
|
||||||
int last_was_nl= 0;
|
|
||||||
|
|
||||||
for(cpt= buffer; *cpt != 0; cpt++) {
|
|
||||||
if(*b_open) {
|
|
||||||
if(*b_state == 0 && *cpt == '<') {
|
|
||||||
*b_state= 1;
|
|
||||||
} else if(*b_state == 1) {
|
|
||||||
if(*cpt == '/')
|
|
||||||
*b_state= 2;
|
|
||||||
else
|
|
||||||
*b_state= 0;
|
|
||||||
} else if(*b_state == 2) {
|
|
||||||
if(*cpt == 'b' || *cpt == 'B')
|
|
||||||
*b_state= 3;
|
|
||||||
else
|
|
||||||
*b_state= 0;
|
|
||||||
} else if(*b_state == 3) {
|
|
||||||
if(*cpt == '>')
|
|
||||||
*b_open= 0;
|
|
||||||
*b_state= 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(*b_state == 0 && *cpt == '<') {
|
|
||||||
*b_state= 1;
|
|
||||||
} else if(*b_state == 1) {
|
|
||||||
if(*cpt == 'b' || *cpt == 'B')
|
|
||||||
*b_state= 2;
|
|
||||||
else
|
|
||||||
*b_state= 0;
|
|
||||||
} else if(*b_state == 2) {
|
|
||||||
if(*cpt == '>')
|
|
||||||
*b_open= 1;
|
|
||||||
*b_state= 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
last_was_nl= (*cpt == '\n');
|
|
||||||
}
|
|
||||||
if(*b_open && last_was_nl) {
|
|
||||||
/* replace newline */
|
|
||||||
*(cpt - 1)= ' ';
|
|
||||||
}
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
FILE *fpin, *fpout;
|
|
||||||
char buffer[4096], *respt;
|
|
||||||
int ret, b_open= 0, b_state= 0;
|
|
||||||
|
|
||||||
if(argc != 3) {
|
|
||||||
fprintf(stderr, "usage: %s input_path output_path\n", argv[0]);
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
if(strcmp(argv[1], "-") == 0) {
|
|
||||||
fpin= stdin;
|
|
||||||
} else {
|
|
||||||
fpin= fopen(argv[1], "rb");
|
|
||||||
if(fpin == 0) {
|
|
||||||
fprintf(stderr, "Error with input file '%s' : %s\n",
|
|
||||||
argv[1], strerror(errno));
|
|
||||||
return(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(strcmp(argv[2], "-") == 0) {
|
|
||||||
fpout= stdout;
|
|
||||||
} else {
|
|
||||||
fpout= fopen(argv[2], "wb");
|
|
||||||
if(fpout == 0) {
|
|
||||||
fprintf(stderr, "Error with output file '%s' : %s\n",
|
|
||||||
argv[2], strerror(errno));
|
|
||||||
return(3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while(1) {
|
|
||||||
respt= fgets(buffer, sizeof(buffer), fpin);
|
|
||||||
if(respt == NULL)
|
|
||||||
break;
|
|
||||||
ret= unite_lines(buffer, &b_open, &b_state, 0);
|
|
||||||
if(ret <= 0)
|
|
||||||
break;
|
|
||||||
ret= fputs(buffer, fpout);
|
|
||||||
if(ret < 0) {
|
|
||||||
fprintf(stderr, "Error writing to output file '%s' : %s\n",
|
|
||||||
argv[2], strerror(errno));
|
|
||||||
return(4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(fpin != stdin)
|
|
||||||
fclose(fpin);
|
|
||||||
if(fpout != stdout)
|
|
||||||
fclose(stdout);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
@ -1,297 +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, BD-R are handled like CD-R[W] with TAO
|
|
||||||
and multi-session. Additionally cdrskin offers cdrecord-ProDVD-like mode DAO
|
|
||||||
with DVD-R[W].
|
|
||||||
|
|
||||||
cdrskin does not contain any bytes copied from cdrecord's sources.
|
|
||||||
Many bytes have been copied from the message output of cdrecord
|
|
||||||
runs, though. The most comprehensive technical overview of cdrskin
|
|
||||||
can be found in [http://libburnia-project.org/browser/libburn/trunk/cdrskin/README?format=txt cdrskin/README].
|
|
||||||
|
|
||||||
About libburn API for burning CD, DVD, and BD: http://api.libburnia-project.org
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
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 can be used by 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 acquire 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> ensures 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 or 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 chosen 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 .
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Advanced multi-session use cases as of dvd+rw-tools:
|
|
||||||
|
|
||||||
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].
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
|
|
378
configure.ac
378
configure.ac
@ -1,378 +0,0 @@
|
|||||||
AC_INIT([libburn], [1.5.7], [http://libburnia-project.org])
|
|
||||||
AC_PREREQ([2.50])
|
|
||||||
dnl AC_CONFIG_HEADER([config.h])
|
|
||||||
|
|
||||||
AC_CANONICAL_HOST
|
|
||||||
AC_CANONICAL_TARGET
|
|
||||||
|
|
||||||
LIBBURNIA_SET_FLAGS
|
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE([subdir-objects])
|
|
||||||
AC_CONFIG_MACRO_DIR([./])
|
|
||||||
|
|
||||||
dnl Notes about version numbers and .so numbers:
|
|
||||||
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 On Linux the name of the dynamic library will be
|
|
||||||
dnl libburn.so.$SONAME.$AGE.$REV
|
|
||||||
dnl In the terminology of this file:
|
|
||||||
dnl CURRENT = LT_CURRENT
|
|
||||||
dnl AGE = LT_AGE
|
|
||||||
dnl REVISION= LT_REVISION
|
|
||||||
dnl
|
|
||||||
dnl Beginning with libburn-0.4.1 a rectified counting was introduced as
|
|
||||||
dnl CURRENT=10, REVISION=1, AGE=6
|
|
||||||
dnl This rectification declared that version to be binary compatible up
|
|
||||||
dnl from libburn-0.3.4.
|
|
||||||
dnl Real compatibility was given since libburn-0.3.2.
|
|
||||||
dnl Beware of libburn-0.2.6 which had SONAME=6 and is not binary compatible.
|
|
||||||
dnl Applications for libburn-0.2 to libburn-0.3.1 need recompilation but no
|
|
||||||
dnl source code changes.
|
|
||||||
dnl
|
|
||||||
dnl Neatly versioned stable releases meanwhile:
|
|
||||||
dnl 0.4.2 = libburn.so.4.7.0
|
|
||||||
dnl 0.4.4 = libburn.so.4.9.0
|
|
||||||
dnl 0.4.6 = libburn.so.4.11.0
|
|
||||||
dnl 0.4.8 = libburn.so.4.13.0
|
|
||||||
dnl 0.5.0 = libburn.so.4.15.0
|
|
||||||
dnl 0.5.2 = libburn.so.4.17.0
|
|
||||||
dnl 0.5.4 = libburn.so.4.19.0
|
|
||||||
dnl 0.5.6 = libburn.so.4.21.0
|
|
||||||
dnl 0.5.8 = libburn.so.4.23.0
|
|
||||||
dnl 0.6.0 = libburn.so.4.25.0
|
|
||||||
dnl 0.6.2 = libburn.so.4.27.0
|
|
||||||
dnl 0.6.4 = libburn.so.4.29.0
|
|
||||||
dnl 0.6.6 = libburn.so.4.31.0
|
|
||||||
dnl 0.6.8 = libburn.so.4.33.0
|
|
||||||
dnl 0.7.0 = libburn.so.4.35.0
|
|
||||||
dnl 0.7.2 = libburn.so.4.37.0
|
|
||||||
dnl 0.7.4 = libburn.so.4.39.0
|
|
||||||
dnl 0.7.6 = libburn.so.4.41.0
|
|
||||||
dnl 0.7.8 = libburn.so.4.43.0
|
|
||||||
dnl 0.8.0 = libburn.so.4.45.0
|
|
||||||
dnl 0.8.2 = libburn.so.4.47.0
|
|
||||||
dnl 0.8.4 = libburn.so.4.49.0
|
|
||||||
dnl 0.8.6 = libburn.so.4.51.0
|
|
||||||
dnl 0.8.8 = libburn.so.4.53.0
|
|
||||||
dnl 0.9.0 = libburn.so.4.55.0
|
|
||||||
dnl 1.0.0 = libburn.so.4.57.0
|
|
||||||
dnl 1.0.2 = libburn.so.4.59.0
|
|
||||||
dnl 1.0.4 = libburn.so.4.61.0
|
|
||||||
dnl 1.0.6 = libburn.so.4.63.0
|
|
||||||
dnl 1.1.0 = libburn.so.4.65.0
|
|
||||||
dnl 1.1.4 = libburn.so.4.67.0
|
|
||||||
dnl 1.1.6 = libburn.so.4.69.0
|
|
||||||
dnl 1.1.8 = libburn.so.4.71.0
|
|
||||||
dnl 1.2.0 = libburn.so.4.73.0
|
|
||||||
dnl 1.2.2 = libburn.so.4.75.0
|
|
||||||
dnl 1.2.4 = libburn.so.4.77.0
|
|
||||||
dnl 1.2.6 = libburn.so.4.79.0
|
|
||||||
dnl 1.2.8 = libburn.so.4.81.0
|
|
||||||
dnl 1.3.0 = libburn.so.4.83.0
|
|
||||||
dnl 1.3.2 = libburn.so.4.85.0
|
|
||||||
dnl 1.3.4 = libburn.so.4.87.0
|
|
||||||
dnl 1.3.6 = libburn.so.4.89.0
|
|
||||||
dnl 1.3.8 = libburn.so.4.91.0
|
|
||||||
dnl 1.4.0 = libburn.so.4.93.0
|
|
||||||
dnl 1.4.2 = libburn.so.4.95.0
|
|
||||||
dnl 1.4.4 = libburn.so.4.97.0
|
|
||||||
dnl 1.4.6 = libburn.so.4.99.0
|
|
||||||
dnl 1.4.8 = libburn.so.4.101.0
|
|
||||||
dnl 1.5.0 = libburn.so.4.103.0
|
|
||||||
dnl 1.5.2 = libburn.so.4.105.0
|
|
||||||
dnl 1.5.4 = libburn.so.4.107.0
|
|
||||||
dnl 1.5.6 = libburn.so.4.109.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=1
|
|
||||||
BURN_MINOR_VERSION=5
|
|
||||||
BURN_MICRO_VERSION=7
|
|
||||||
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 ### This is the release version libburn-1.5.6
|
|
||||||
dnl This is the development version after above release version
|
|
||||||
dnl ### LT_CURRENT++, LT_AGE++ has not yet happened.
|
|
||||||
dnl LT_CURRENT++, LT_AGE++ has happened meanwhile.
|
|
||||||
dnl
|
|
||||||
dnl SONAME = 114 - 110 = 4 . Linux library name = libburn.so.4.110.0
|
|
||||||
LT_CURRENT=114
|
|
||||||
LT_AGE=110
|
|
||||||
LT_REVISION=0
|
|
||||||
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
|
|
||||||
|
|
||||||
dnl ts B90405 : Disabled on advise of Ross Burton
|
|
||||||
dnl AM_MAINTAINER_MODE
|
|
||||||
|
|
||||||
AM_PROG_CC_C_O
|
|
||||||
AC_C_CONST
|
|
||||||
AC_C_INLINE
|
|
||||||
|
|
||||||
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(LIBBURNIA_PKGCONFDIR)
|
|
||||||
AC_SUBST(LIBBURN_ARCH_LIBS)
|
|
||||||
|
|
||||||
dnl ts A90303
|
|
||||||
dnl Check the preconditions for using statvfs() in sg-dummy
|
|
||||||
dnl (sg-linux and sg-freebsd use statvfs() unconditionally)
|
|
||||||
STATVFS_DEF=-DLibburn_os_has_statvfS
|
|
||||||
AC_CHECK_HEADER(sys/statvfs.h, X=, STATVFS_DEF=)
|
|
||||||
AC_CHECK_FUNC([statvfs], X=, STATVFS_DEF=)
|
|
||||||
dnl If this would be done more specifically in Makefile.am
|
|
||||||
dnl via libburn_libburn_la_CFLAGS then undesired .o file names would emerge
|
|
||||||
CFLAGS="$STATVFS_DEF $CFLAGS"
|
|
||||||
|
|
||||||
dnl ts A91122
|
|
||||||
AC_ARG_ENABLE(track-src-odirect,
|
|
||||||
[ --enable-track-src-odirect Banned for now: (Enable use of O_DIRECT with track input, default=no)],
|
|
||||||
, enable_track_src_odirect=no)
|
|
||||||
if test x$enable_track_src_odirect = xyes; then
|
|
||||||
# LIBBURN_O_DIRECT_DEF="-DLibburn_read_o_direcT"
|
|
||||||
# echo "enabled use of O_DIRECT with track input"
|
|
||||||
echo "REFUSED to enable use of O_DIRECT with track input because of cdrskin multi-track bug"
|
|
||||||
else
|
|
||||||
LIBBURN_O_DIRECT_DEF=
|
|
||||||
echo "disabled use of O_DIRECT with track input"
|
|
||||||
fi
|
|
||||||
dnl Avoid the need for libburn_libburn_la_CFLAGS in Makefile.am (ugly .o names)
|
|
||||||
dnl ### AC_SUBST(LIBBURN_O_DIRECT_DEF)
|
|
||||||
CFLAGS="$LIBBURN_O_DIRECT_DEF $CFLAGS"
|
|
||||||
|
|
||||||
dnl ts A91116
|
|
||||||
AC_ARG_ENABLE(dvd-obs-64k,
|
|
||||||
[ --enable-dvd-obs-64k 64 KB default size for DVD writing, default=no],
|
|
||||||
, enable_dvd_obs_64k=no)
|
|
||||||
if test x$enable_dvd_obs_64k = xyes; then
|
|
||||||
LIBBURN_DVD_OBS_64K="-DLibburn_dvd_obs_default_64K"
|
|
||||||
echo "enabled write size default 64 KB on DVD"
|
|
||||||
else
|
|
||||||
LIBBURN_DVD_OBS_64K=
|
|
||||||
echo "disabled write size default 64 KB on DVD"
|
|
||||||
fi
|
|
||||||
CFLAGS="$LIBBURN_DVD_OBS_64K $CFLAGS"
|
|
||||||
|
|
||||||
dnl ts B20413
|
|
||||||
AC_ARG_ENABLE(dvd-obs-pad,
|
|
||||||
[ --enable-dvd-obs-pad pad DVD DAO sessions to 32 or 64 KB, default=no],
|
|
||||||
, enable_dvd_obs_pad=no)
|
|
||||||
if test x$enable_dvd_obs_pad = xyes; then
|
|
||||||
LIBBURN_DVD_OBS_PAD="-DLibburn_dvd_always_obs_paD"
|
|
||||||
echo "enabled padding of DVD DAO sessions to 32 or 64 KB"
|
|
||||||
else
|
|
||||||
LIBBURN_DVD_OBS_64K=
|
|
||||||
echo "disabled padding of DVD DAO sessions to 32 or 64 KB"
|
|
||||||
fi
|
|
||||||
CFLAGS="$LIBBURN_DVD_OBS_PAD $CFLAGS"
|
|
||||||
|
|
||||||
dnl ts A91218 - B21002
|
|
||||||
case $host_os in
|
|
||||||
cygwin*|mingw*)
|
|
||||||
default_libcdio=yes
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
default_libcdio=no
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
# Check for proper library versions if this is desired.
|
|
||||||
# (It fails too often on too many systems.)
|
|
||||||
AC_ARG_ENABLE(pkg-check-modules,
|
|
||||||
[ --enable-pkg-check-modules Enable pkg-config check for libcdio , default=no],
|
|
||||||
, enable_pkg_check_modules=no)
|
|
||||||
AC_ARG_ENABLE(libcdio,
|
|
||||||
[ --enable-libcdio Enable use of libcdio as system adapter, default=no (except on MSWindows)],
|
|
||||||
, enable_libcdio=$default_libcdio)
|
|
||||||
PKG_PROG_PKG_CONFIG
|
|
||||||
if test x$enable_libcdio = xyes; then
|
|
||||||
dnl Check whether there is libcdio-devel and libcdio-runtime.
|
|
||||||
dnl If not, erase this macro
|
|
||||||
LIBCDIO_DEF="-DLibburn_use_libcdiO"
|
|
||||||
dnl The empty yes case obviously causes -lcdio to be linked
|
|
||||||
AC_CHECK_HEADER(cdio/cdio.h, AC_CHECK_LIB(cdio, mmc_last_cmd_sense, , LIBCDIO_DEF= ), LIBCDIO_DEF= )
|
|
||||||
else
|
|
||||||
LIBCDIO_DEF=
|
|
||||||
fi
|
|
||||||
if test x$LIBCDIO_DEF = x
|
|
||||||
then
|
|
||||||
if test x$enable_libcdio = xyes
|
|
||||||
then
|
|
||||||
echo "WARNING: could not enable use of libcdio as system adapter"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "enabled use of libcdio as system adapter"
|
|
||||||
CFLAGS="$LIBCDIO_DEF $CFLAGS"
|
|
||||||
|
|
||||||
if test x$enable_pkg_check_modules = xyes; then
|
|
||||||
LIBCDIO_REQUIRED=0.83
|
|
||||||
PKG_CHECK_MODULES(LIBCDIO, libcdio >= $LIBCDIO_REQUIRED)
|
|
||||||
else
|
|
||||||
echo "checking for LIBCDIO... skipped, no --enable-pkg-check-modules"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl ts B70127
|
|
||||||
# There are Linuxes with no public generic SCSI interface
|
|
||||||
LIBBURNIA_CHECK_LINUX_SCSI
|
|
||||||
|
|
||||||
dnl ts B00704
|
|
||||||
# Library versioning normally serves a complex purpose.
|
|
||||||
# Since libburn obeys strict ABI backward compatibility, it needs only the
|
|
||||||
# simple feature to declare function names "global:" or "local:". Only the
|
|
||||||
# global ones are visible to applications at library load time.
|
|
||||||
AC_ARG_ENABLE(versioned-libs,
|
|
||||||
[ --enable-versioned-libs Enable strict symbol encapsulation , default=yes],
|
|
||||||
, enable_versioned_libs=yes)
|
|
||||||
if test x$enable_versioned_libs = xyes; then
|
|
||||||
vers_libs_test=no
|
|
||||||
LIBBURN_ASSERT_VERS_LIBS
|
|
||||||
if test x$vers_libs_test = xno
|
|
||||||
then
|
|
||||||
echo "disabled strict symbol encapsulation (test failed)"
|
|
||||||
else
|
|
||||||
echo "enabled strict symbol encapsulation"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "disabled strict symbol encapsulation"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for system dependent mandatory libraries (LIBBURN_ARCH_LIBS)
|
|
||||||
LIBBURNIA_CHECK_ARCH_LIBS(mandatory)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(ldconfig-at-install,
|
|
||||||
[ --enable-ldconfig-at-install On GNU/Linux run ldconfig, default=yes],
|
|
||||||
, ldconfig_at_install=yes)
|
|
||||||
if test x$ldconfig_at_install = xyes; then
|
|
||||||
dummy=dummy
|
|
||||||
else
|
|
||||||
LIBBURNIA_LDCONFIG_CMD="echo 'NOTE: ldconfig is disabled. If needed, configure manually for:'"
|
|
||||||
echo "disabled run of ldconfig during installation on GNU/Linux"
|
|
||||||
fi
|
|
||||||
AC_SUBST(LIBBURNIA_LDCONFIG_CMD)
|
|
||||||
|
|
||||||
|
|
||||||
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="-O3 $CFLAGS"
|
|
||||||
CFLAGS="-fexpensive-optimizations $CFLAGS"
|
|
||||||
fi
|
|
||||||
CFLAGS="-DNDEBUG $CFLAGS"
|
|
||||||
else
|
|
||||||
if test x$GCC = xyes; then
|
|
||||||
CFLAGS="-g -pedantic -Wall -Wextra -Wno-unused-parameter -Wno-char-subscripts $CFLAGS"
|
|
||||||
fi
|
|
||||||
CFLAGS="-DDEBUG $CFLAGS"
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl Determine target directory for libburn-*.pc
|
|
||||||
dnl Important: Must be performed _after_ TARGET_SHIZZLE
|
|
||||||
dnl
|
|
||||||
LIBBURNIA_SET_PKGCONFIG
|
|
||||||
|
|
||||||
|
|
||||||
AC_CONFIG_FILES([
|
|
||||||
Makefile
|
|
||||||
doc/doxygen.conf
|
|
||||||
version.h
|
|
||||||
libburn-1.pc
|
|
||||||
])
|
|
||||||
AC_OUTPUT
|
|
@ -1,4 +0,0 @@
|
|||||||
all clean:
|
|
||||||
$(MAKE) -C .. -$(MAKEFLAGS) $@
|
|
||||||
|
|
||||||
.PHONY: all clean
|
|
736
doc/cdtext.txt
736
doc/cdtext.txt
@ -1,736 +0,0 @@
|
|||||||
|
|
||||||
Description of CD-TEXT
|
|
||||||
|
|
||||||
Guided by Leon Merten Lohse via libcdio-devel@gnu.org
|
|
||||||
by reading mmc3r10g.pdf from http://www.t10.org/ftp/t10/drafts/mmc3/
|
|
||||||
by docs and results of cdtext.zip from http://www.sonydadc.com/file/
|
|
||||||
by reading http://digitalx.org/cue-sheet/syntax
|
|
||||||
by reading source of libcdio from http://www.gnu.org/s/libcdio
|
|
||||||
which quotes source of cdrecord from ftp://ftp.berlios.de/pub/cdrecord/alpha
|
|
||||||
by reading cdrecord.1 from ftp://ftp.berlios.de/pub/cdrecord/alpha
|
|
||||||
|
|
||||||
Language codes were learned from http://tech.ebu.ch/docs/tech/tech3264.pdf
|
|
||||||
Genre codes were learned from libcdio and confirmed by
|
|
||||||
http://helpdesk.audiofile-engineering.com/index.php?pg=kb.page&id=123
|
|
||||||
|
|
||||||
For libburnia-project.org by Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
|
|
||||||
Content:
|
|
||||||
- CD-TEXT from the view of the user
|
|
||||||
- Content specifications of particular pack types
|
|
||||||
- Format of a CD-TEXT packs array
|
|
||||||
- Overview of libburn API calls for CD-TEXT
|
|
||||||
- Sony Text File Format (Input Sheet Version 0.7T)
|
|
||||||
- CDRWIN cue sheet files
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
CD-TEXT from the view of the user:
|
|
||||||
|
|
||||||
CD-TEXT records attributes of disc and tracks on audio CD.
|
|
||||||
|
|
||||||
The attributes are grouped into blocks which represent particular languages.
|
|
||||||
Up to 8 blocks are possible.
|
|
||||||
|
|
||||||
There are 13 defined attribute categories, which are called Pack Types and are
|
|
||||||
identified by a single-byte code:
|
|
||||||
0x80 = Title
|
|
||||||
0x81 = Names of Performers
|
|
||||||
0x82 = Names of Songwriters
|
|
||||||
0x83 = Names of Composers
|
|
||||||
0x84 = Names of Arrangers
|
|
||||||
0x85 = Messages
|
|
||||||
0x86 = text-and-binary: Disc Identification
|
|
||||||
0x87 = text-and-binary: Genre Identification
|
|
||||||
0x88 = binary: Table of Content information
|
|
||||||
0x89 = binary: Second Table of Content information
|
|
||||||
(0x8a to 0x8c are reserved.)
|
|
||||||
0x8d = Closed Information
|
|
||||||
0x8e = UPC/EAN code of the album and ISRC code of each track
|
|
||||||
0x8f = binary: Size Information of the Block
|
|
||||||
|
|
||||||
Some of these categories apply to the whole disc only:
|
|
||||||
0x86, 0x87, 0x88, 0x89, 0x8d
|
|
||||||
Some have to be additionally attributed to each track, if they are present for
|
|
||||||
the whole disc:
|
|
||||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x8e
|
|
||||||
One describes the overall content of a block and in part of all other blocks:
|
|
||||||
0x8f
|
|
||||||
|
|
||||||
The total size of a block's attribute set is restricted by the fact that it
|
|
||||||
has to be stored in at most 253 records with 12 bytes of payload. These records
|
|
||||||
are called Text Packs.
|
|
||||||
A shortcut for repeated identical track texts is provided, so that a text
|
|
||||||
that is identical to the one of the previous track occupies only 2 or 4 bytes.
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Content specification of particular pack types:
|
|
||||||
|
|
||||||
Pack types 0x80 to 0x85 and 0x8e contain 0-terminated cleartext. If double byte
|
|
||||||
characters are used, then two 0-bytes terminate the cleartext.
|
|
||||||
The meaning of 0x80 to 0x85 should be clear by above list. They are encoded
|
|
||||||
according to the Character Code of their block. Either as ISO-8859-1 single
|
|
||||||
byte characters, or as 7-bit ASCII single byte characters, or as MS-JIS double
|
|
||||||
byte characters.
|
|
||||||
More info to 0x8e is given below.
|
|
||||||
|
|
||||||
Pack type 0x86 (Disc Identification) is documented by Sony as "Catalog Number:
|
|
||||||
(use ASCII Code) Catalog Number of the album". So it is not really binary
|
|
||||||
but might be non-printable, and should contain only bytes with bit7 = 0.
|
|
||||||
|
|
||||||
Pack type 0x87 contains 2 binary bytes, followed by 0-terminated cleartext.
|
|
||||||
The two binary bytes form a big-endian index to the following list.
|
|
||||||
0x0000 = "Not Used" (Sony prescribes to use this if no genre applies)
|
|
||||||
0x0001 = "Not Defined"
|
|
||||||
0x0002 = "Adult Contemporary"
|
|
||||||
0x0003 = "Alternative Rock"
|
|
||||||
0x0004 = "Childrens Music"
|
|
||||||
0x0005 = "Classical"
|
|
||||||
0x0006 = "Contemporary Christian"
|
|
||||||
0x0007 = "Country"
|
|
||||||
0x0008 = "Dance"
|
|
||||||
0x0009 = "Easy Listening"
|
|
||||||
0x000a = "Erotic"
|
|
||||||
0x000b = "Folk"
|
|
||||||
0x000c = "Gospel"
|
|
||||||
0x000d = "Hip Hop"
|
|
||||||
0x000e = "Jazz"
|
|
||||||
0x000f = "Latin"
|
|
||||||
0x0010 = "Musical"
|
|
||||||
0x0011 = "New Age"
|
|
||||||
0x0012 = "Opera"
|
|
||||||
0x0013 = "Operetta"
|
|
||||||
0x0014 = "Pop Music"
|
|
||||||
0x0015 = "Rap"
|
|
||||||
0x0016 = "Reggae"
|
|
||||||
0x0017 = "Rock Music"
|
|
||||||
0x0018 = "Rhythm & Blues"
|
|
||||||
0x0019 = "Sound Effects"
|
|
||||||
0x001a = "Spoken Word"
|
|
||||||
0x001b = "World Music"
|
|
||||||
Sony documents the cleartext part as "Genre information that would supplement
|
|
||||||
the Genre Code, such as 'USA Rock music in the 60s'". Always ASCII encoded.
|
|
||||||
|
|
||||||
Pack type 0x88 records information from the CD's Table of Content, as of
|
|
||||||
READ PMA/TOC/ATIP Format 0010b (mmc3r10g.pdf, table 237 TOC Track Descriptor
|
|
||||||
Format, Q Sub-channel).
|
|
||||||
See below, Format of a CD-TEXT packs array, for more details about the content
|
|
||||||
of pack type 0x88.
|
|
||||||
|
|
||||||
Pack type 0x89 is yet quite unclear. It might be a representation of Playback
|
|
||||||
Skip Interval, Mode-5 Q sub-channel, POINT 01 to 40 (mmc3r10g.pdf 4.2.3.6.3).
|
|
||||||
If so, then this seems not to apply to write type SAO, because the CUE SHEET
|
|
||||||
format offers no way to express Mode-5 Q.
|
|
||||||
See below, Format of a CD-TEXT packs array, for an example of this pack type.
|
|
||||||
|
|
||||||
Pack type 0x8d is documented by Sony as "Closed Information: (use 8859-1 Code)
|
|
||||||
Any information can be recorded on disc as memorandum. Information in this
|
|
||||||
field will not be read by CD TEXT players available to the public."
|
|
||||||
Always ISO-8859-1 encoded.
|
|
||||||
|
|
||||||
Pack type 0x8e is documented by Sony as "UPC/EAN Code (POS Code) of the album.
|
|
||||||
This field typically consists of 13 characters." Always ASCII encoded.
|
|
||||||
It applies to tracks as "ISRC code [which] typically consists of 12 characters"
|
|
||||||
and is always ISO-8859-1 encoded.
|
|
||||||
MMC calls these information entities Media Catalog Number and ISRC.
|
|
||||||
The catalog number consists of 13 decimal digits.
|
|
||||||
ISRC consists of 12 characters: 2 country code [0-9A-Z], 3 owner code [0-9A-Z],
|
|
||||||
2 year digits (00 to 99), 5 serial number digits (00000 to 99999).
|
|
||||||
|
|
||||||
Pack type 0x8f summarizes the whole list of text packs of a block.
|
|
||||||
See below, Format of a CD-TEXT packs array, for details.
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Format of a CD-TEXT packs array:
|
|
||||||
|
|
||||||
The attributes are represented on CD as Text Packs in the sub-channel of
|
|
||||||
the Lead-in of the disc. See doc/cookbook.txt for a description how to write
|
|
||||||
the readily formatted CD-TEXT pack array to CD, and how to read CD-TEXT packs
|
|
||||||
from CD.
|
|
||||||
|
|
||||||
The format is explained in part in MMC-3 (mmc3r10g.pdf, Annex J) and in part by
|
|
||||||
the documentation in Sony's cdtext.zip :
|
|
||||||
|
|
||||||
Each pack consists of a 4-byte header, 12 bytes of payload, and 2 bytes of CRC.
|
|
||||||
|
|
||||||
The first byte of each pack tells the pack type. See above for a list of types.
|
|
||||||
|
|
||||||
The second byte tells the track number to which the first text piece in
|
|
||||||
a pack is associated. Number 0 means the whole album. Higher numbers are
|
|
||||||
valid for types 0x80 to 0x85, and 0x8e. With these types, there should be
|
|
||||||
one text for the disc and one for each track.
|
|
||||||
With types 0x88 and 0x89, the second byte bears a track number, too.
|
|
||||||
With type 0x8f, the second byte counts the record parts from 0 to 2.
|
|
||||||
|
|
||||||
The third byte is a sequential counter.
|
|
||||||
|
|
||||||
The fourth byte is the Block Number and Character Position Indicator.
|
|
||||||
It consists of three bit fields:
|
|
||||||
bit7 = Double Bytes Character Code (0= single byte characters)
|
|
||||||
bit4-6 = Block Number (groups text packs in language blocks)
|
|
||||||
bit0-3 = Character position. Either the number of characters which
|
|
||||||
the current text inherited from the previous pack, or
|
|
||||||
15 if the current text started before the previous pack.
|
|
||||||
|
|
||||||
The 12 payload bytes contain pieces of 0-terminated texts or binary data.
|
|
||||||
A text may span over several packs. Unused characters in a pack are used for
|
|
||||||
the next text of the same pack type. If no text of the same type follows,
|
|
||||||
then the remaining text bytes are set to 0.
|
|
||||||
|
|
||||||
The CRC algorithm uses divisor 0x11021. The resulting 16-bit residue of the
|
|
||||||
polynomial division gets inverted and written as big-endian number to bytes
|
|
||||||
16 and 17 of the pack.
|
|
||||||
|
|
||||||
|
|
||||||
The text packs are grouped in up to 8 blocks of at most 256 packs. Each block
|
|
||||||
is in charge for one language. Sequence numbers of each block are counted
|
|
||||||
separately. All packs of block 0 come before the packs of block 1.
|
|
||||||
|
|
||||||
The limitation of block number and sequence numbers imply that there are at
|
|
||||||
most 2048 text packs possible. (READ TOC/PMA/ATIP could retrieve 3640 packs,
|
|
||||||
as it is limited to 64 kB - 2.)
|
|
||||||
|
|
||||||
|
|
||||||
If a text of a track (pack types 0x80 to 0x85 and 0x8e) repeats identically
|
|
||||||
for the next track, then it may be represented by a TAB character (ASCII 9)
|
|
||||||
for single byte texts, and two TAB characters for double byte texts.
|
|
||||||
(This should be used because 256 * 12 bytes is few space for 99 tracks.)
|
|
||||||
|
|
||||||
The two binary bytes of pack type 0x87 are written to the first 0x87 pack of
|
|
||||||
a block. They may or may not be repeated at the start of the follow-up packs
|
|
||||||
of type 0x87.
|
|
||||||
|
|
||||||
The first pack of type 0x88 in a block records in its payload bytes:
|
|
||||||
0 : PMIN of POINT A1 = First Track Number
|
|
||||||
1 : PMIN of POINT A2 = Last Track Number
|
|
||||||
2 : unknown, 0 in Sony example
|
|
||||||
3 : PMIN of POINT A2 = Start position of Lead-Out
|
|
||||||
4 : PSEC of POINT A2 = Start position of Lead-Out
|
|
||||||
5 : PFRAME of POINT A2 = Start position of Lead-Out
|
|
||||||
6 to 11 : unknown, 0 in Sony example
|
|
||||||
The following packs record PMIN, PSEC, PFRAME of the POINTs between the
|
|
||||||
lowest track number (min 01h) and the highest track number (max 63h).
|
|
||||||
The payload of the last pack is padded by 0s.
|
|
||||||
The Sony .TOC example:
|
|
||||||
A0 01
|
|
||||||
A1 14
|
|
||||||
A2 63:02:18
|
|
||||||
01 00:02:00
|
|
||||||
02 04:11:25
|
|
||||||
03 08:02:50
|
|
||||||
04 11:47:62
|
|
||||||
...
|
|
||||||
13 53:24:25
|
|
||||||
14 57:03:25
|
|
||||||
yields
|
|
||||||
88 00 23 00 01 0e 00 3f 02 12 00 00 00 00 00 00 12 00
|
|
||||||
88 01 24 00 00 02 00 04 0b 19 08 02 32 0b 2f 3e 67 2d
|
|
||||||
...
|
|
||||||
88 0d 27 00 35 18 19 39 03 19 00 00 00 00 00 00 ea af
|
|
||||||
|
|
||||||
Pack type 0x89 is yet quite unclear. Especially what the information shall
|
|
||||||
mean to the user of the CD. The time points in the Sony example are in the
|
|
||||||
time range of the tracks numbers that are given before the time points:
|
|
||||||
01 02:41:48 01 02:52:58
|
|
||||||
06 23:14:25 06 23:29:60
|
|
||||||
07 28:30:39 07 28:42:30
|
|
||||||
13 55:13:26 13 55:31:50
|
|
||||||
yields
|
|
||||||
89 01 28 00 01 04 00 00 00 00 02 29 30 02 34 3a f3 0c
|
|
||||||
89 06 29 00 02 04 00 00 00 00 17 0e 19 17 1d 3c 73 92
|
|
||||||
89 07 2a 00 03 04 00 00 00 00 1c 1e 27 1c 2a 1e 72 20
|
|
||||||
89 0d 2b 00 04 04 00 00 00 00 37 0d 1a 37 1f 32 0b 62
|
|
||||||
The track numbers are stored in the track number byte of the packs. The two
|
|
||||||
time points are stored in byte 6 to 11 of the payload. Byte 0 of the payload
|
|
||||||
seems to be a sequential counter. Byte 1 always 4 ? Byte 2 to 5 always 0 ?
|
|
||||||
|
|
||||||
Pack type 0x8f summarizes the whole list of text packs of a block.
|
|
||||||
So there is one group of three 0x8f packs per block.
|
|
||||||
Nevertheless each 0x8f group tells the highest sequence number and the
|
|
||||||
language code of all blocks.
|
|
||||||
The payload bytes of three 0x8f packs form a 36 byte record. The track number
|
|
||||||
bytes of the three packs have the values 0, 1, 2.
|
|
||||||
Byte :
|
|
||||||
0 : Character code for pack types 0x80 to 0x85:
|
|
||||||
0x00 = ISO-8859-1
|
|
||||||
0x01 = 7 bit ASCII
|
|
||||||
0x80 = MS-JIS (japanese Kanji, double byte characters)
|
|
||||||
1 : Number of first track
|
|
||||||
2 : Number of last track
|
|
||||||
3 : libcdio source states: "cd-text information copyright byte"
|
|
||||||
Probably 3 means "copyrighted", 0 means "not copyrighted".
|
|
||||||
4 - 19 : Pack count of the various types 0x80 to 0x8f.
|
|
||||||
Byte number N tells the count of packs of type 0x80 + (N - 4).
|
|
||||||
I.e. the first byte in this field of 16 counts packs of type 0x80.
|
|
||||||
20 - 27 : Highest sequence byte number of blocks 0 to 7.
|
|
||||||
28 - 36 : Language code for blocks 0 to 7 (tech3264.pdf appendix 3)
|
|
||||||
Not all of these Codes have ever been seen with CD-TEXT, though.
|
|
||||||
0x00 = Unknown
|
|
||||||
0x01 = Albanian
|
|
||||||
0x02 = Breton
|
|
||||||
0x03 = Catalan
|
|
||||||
0x04 = Croatian
|
|
||||||
0x05 = Welsh
|
|
||||||
0x06 = Czech
|
|
||||||
0x07 = Danish
|
|
||||||
0x08 = German
|
|
||||||
0x09 = English
|
|
||||||
0x0a = Spanish
|
|
||||||
0x0b = Esperanto
|
|
||||||
0x0c = Estonian
|
|
||||||
0x0d = Basque
|
|
||||||
0x0e = Faroese
|
|
||||||
0x0f = French
|
|
||||||
0x10 = Frisian
|
|
||||||
0x11 = Irish
|
|
||||||
0x12 = Gaelic
|
|
||||||
0x13 = Galician
|
|
||||||
0x14 = Icelandic
|
|
||||||
0x15 = Italian
|
|
||||||
0x16 = Lappish
|
|
||||||
0x17 = Latin
|
|
||||||
0x18 = Latvian
|
|
||||||
0x19 = Luxembourgian
|
|
||||||
0x1a = Lithuanian
|
|
||||||
0x1b = Hungarian
|
|
||||||
0x1c = Maltese
|
|
||||||
0x1d = Dutch
|
|
||||||
0x1e = Norwegian
|
|
||||||
0x1f = Occitan
|
|
||||||
0x20 = Polish
|
|
||||||
0x21 = Portuguese
|
|
||||||
0x22 = Romanian
|
|
||||||
0x23 = Romansh
|
|
||||||
0x24 = Serbian
|
|
||||||
0x25 = Slovak
|
|
||||||
0x26 = Slovenian
|
|
||||||
0x27 = Finnish
|
|
||||||
0x28 = Swedish
|
|
||||||
0x29 = Turkish
|
|
||||||
0x2a = Flemish
|
|
||||||
0x2b = Wallon
|
|
||||||
0x45 = Zulu
|
|
||||||
0x46 = Vietnamese
|
|
||||||
0x47 = Uzbek
|
|
||||||
0x48 = Urdu
|
|
||||||
0x49 = Ukrainian
|
|
||||||
0x4a = Thai
|
|
||||||
0x4b = Telugu
|
|
||||||
0x4c = Tatar
|
|
||||||
0x4d = Tamil
|
|
||||||
0x4e = Tadzhik
|
|
||||||
0x4f = Swahili
|
|
||||||
0x50 = Sranan Tongo
|
|
||||||
0x51 = Somali
|
|
||||||
0x52 = Sinhalese
|
|
||||||
0x53 = Shona
|
|
||||||
0x54 = Serbo-croat
|
|
||||||
0x55 = Ruthenian
|
|
||||||
0x56 = Russian
|
|
||||||
0x57 = Quechua
|
|
||||||
0x58 = Pushtu
|
|
||||||
0x59 = Punjabi
|
|
||||||
0x5a = Persian
|
|
||||||
0x5b = Papamiento
|
|
||||||
0x5c = Oriya
|
|
||||||
0x5d = Nepali
|
|
||||||
0x5e = Ndebele
|
|
||||||
0x5f = Marathi
|
|
||||||
0x60 = Moldavian
|
|
||||||
0x61 = Malaysian
|
|
||||||
0x62 = Malagasay
|
|
||||||
0x63 = Macedonian
|
|
||||||
0x64 = Laotian
|
|
||||||
0x65 = Korean
|
|
||||||
0x66 = Khmer
|
|
||||||
0x67 = Kazakh
|
|
||||||
0x68 = Kannada
|
|
||||||
0x69 = Japanese
|
|
||||||
0x6a = Indonesian
|
|
||||||
0x6b = Hindi
|
|
||||||
0x6c = Hebrew
|
|
||||||
0x6d = Hausa
|
|
||||||
0x6e = Gurani
|
|
||||||
0x6f = Gujurati
|
|
||||||
0x70 = Greek
|
|
||||||
0x71 = Georgian
|
|
||||||
0x72 = Fulani
|
|
||||||
0x73 = Dari
|
|
||||||
0x74 = Churash
|
|
||||||
0x75 = Chinese
|
|
||||||
0x76 = Burmese
|
|
||||||
0x77 = Bulgarian
|
|
||||||
0x78 = Bengali
|
|
||||||
0x79 = Bielorussian
|
|
||||||
0x7a = Bambora
|
|
||||||
0x7b = Azerbaijani
|
|
||||||
0x7c = Assamese
|
|
||||||
0x7d = Armenian
|
|
||||||
0x7e = Arabic
|
|
||||||
0x7f = Amharic
|
|
||||||
E.g. these three packs
|
|
||||||
42 : 8f 00 2a 00 01 01 03 00 06 05 04 05 07 06 01 02 48 65
|
|
||||||
43 : 8f 01 2b 00 00 00 00 00 00 00 06 03 2c 00 00 00 c0 20
|
|
||||||
44 : 8f 02 2c 00 00 00 00 00 09 00 00 00 00 00 00 00 11 45
|
|
||||||
decode to
|
|
||||||
Byte :Value Meaning
|
|
||||||
0 : 01 = ASCII 7-bit
|
|
||||||
1 : 01 = first track is 1
|
|
||||||
2 : 03 = last track is 3
|
|
||||||
3 : 00 = copyright (0 = public domain, 3 = copyrighted ?)
|
|
||||||
4 : 06 = 6 packs of type 0x80
|
|
||||||
5 : 05 = 5 packs of type 0x81
|
|
||||||
6 : 04 = 4 packs of type 0x82
|
|
||||||
7 : 05 = 5 packs of type 0x83
|
|
||||||
8 : 07 = 7 packs of type 0x84
|
|
||||||
9 : 06 = 6 packs of type 0x85
|
|
||||||
10 : 01 = 1 pack of type 0x86
|
|
||||||
11 : 02 = 2 packs of type 0x87
|
|
||||||
12 : 00 = 0 packs of type 0x88
|
|
||||||
13 : 00 = 0 packs of type 0x89
|
|
||||||
14 : 00 00 00 00 = 0 packs of types 0x8a to 0x8d
|
|
||||||
18 : 06 = 6 packs of type 0x8e
|
|
||||||
19 : 03 = 3 packs of type 0x8f
|
|
||||||
20 : 2c = last sequence for block 0
|
|
||||||
This matches the sequence number of the last text pack (0x2c = 44)
|
|
||||||
21 : 00 00 00 00 00 00 00 = last sequence numbers for block 1..7 (none)
|
|
||||||
28 : 09 = language code for block 0: English
|
|
||||||
29 : 00 00 00 00 00 00 00 = language codes for block 1..7 (none)
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Overview of libburn API calls for CD-TEXT (see libburn/libburn.h for details):
|
|
||||||
|
|
||||||
libburn can retrieve the array of text packs from a CD:
|
|
||||||
|
|
||||||
int burn_disc_get_leadin_text(struct burn_drive *d,
|
|
||||||
unsigned char **text_packs, int *num_packs,
|
|
||||||
int flag);
|
|
||||||
|
|
||||||
|
|
||||||
It can write a text pack set with a CD SAO session.
|
|
||||||
|
|
||||||
This set may be attached as array of readily formatted text packs by:
|
|
||||||
|
|
||||||
int burn_write_opts_set_leadin_text(struct burn_write_opts *opts,
|
|
||||||
unsigned char *text_packs,
|
|
||||||
int num_packs, int flag);
|
|
||||||
|
|
||||||
The array of text packs may be read from a file by
|
|
||||||
|
|
||||||
int burn_cdtext_from_packfile(char *path, unsigned char **text_packs,
|
|
||||||
int *num_packs, int flag);
|
|
||||||
|
|
||||||
|
|
||||||
Alternatively the pack set may be defined by attaching CD-TEXT attributes
|
|
||||||
to burn_session and burn_track:
|
|
||||||
|
|
||||||
int burn_session_set_cdtext_par(struct burn_session *s,
|
|
||||||
int char_codes[8], int copyrights[8],
|
|
||||||
int languages[8], int flag);
|
|
||||||
|
|
||||||
int burn_session_set_cdtext(struct burn_session *s, int block,
|
|
||||||
int pack_type, char *pack_type_name,
|
|
||||||
unsigned char *payload, int length, int flag);
|
|
||||||
|
|
||||||
int burn_track_set_cdtext(struct burn_track *t, int block,
|
|
||||||
int pack_type, char *pack_type_name,
|
|
||||||
unsigned char *payload, int length, int flag);
|
|
||||||
|
|
||||||
Macros list the texts for genre and language codes:
|
|
||||||
|
|
||||||
BURN_CDTEXT_LANGUAGES_0X00
|
|
||||||
BURN_CDTEXT_FILLER
|
|
||||||
BURN_CDTEXT_LANGUAGES_0X45
|
|
||||||
|
|
||||||
BURN_CDTEXT_GENRE_LIST
|
|
||||||
BURN_CDTEXT_NUM_GENRES
|
|
||||||
|
|
||||||
There is a reader for Sony Input Sheet Version 0.7T:
|
|
||||||
|
|
||||||
int burn_session_input_sheet_v07t(struct burn_session *session,
|
|
||||||
char *path, int block, int flag);
|
|
||||||
|
|
||||||
and a writer which converts an array of text packs to such a Sony Input Sheet:
|
|
||||||
|
|
||||||
int burn_make_input_sheet_v07t(unsigned char *text_packs, int num_packs,
|
|
||||||
int start_tno, int track_count,
|
|
||||||
char **result, int *char_code, int flag);
|
|
||||||
|
|
||||||
CD-TEXT can be read from a CDRWIN cue sheet file which defines the tracks
|
|
||||||
of a session
|
|
||||||
|
|
||||||
int burn_session_by_cue_file(struct burn_session *session,
|
|
||||||
char *path, int fifo_size, struct burn_source **fifo,
|
|
||||||
unsigned char **text_packs, int *num_packs, int flag);
|
|
||||||
|
|
||||||
|
|
||||||
The session and track attributes can then be converted into an array of
|
|
||||||
text packs by:
|
|
||||||
|
|
||||||
int burn_cdtext_from_session(struct burn_session *s,
|
|
||||||
unsigned char **text_packs, int *num_packs,
|
|
||||||
int flag);
|
|
||||||
|
|
||||||
or they can be written as array of text packs to CD when burning begins and
|
|
||||||
no array of pre-formatted packs was attached to the write options by
|
|
||||||
burn_write_opts_set_leadin_text().
|
|
||||||
|
|
||||||
There are calls for inspecting the attached attributes:
|
|
||||||
|
|
||||||
int burn_session_get_cdtext_par(struct burn_session *s,
|
|
||||||
int char_codes[8], int copyrights[8],
|
|
||||||
int block_languages[8], int flag);
|
|
||||||
|
|
||||||
int burn_session_get_cdtext(struct burn_session *s, int block,
|
|
||||||
int pack_type, char *pack_type_name,
|
|
||||||
unsigned char **payload, int *length, int flag);
|
|
||||||
|
|
||||||
int burn_track_get_cdtext(struct burn_track *t, int block,
|
|
||||||
int pack_type, char *pack_type_name,
|
|
||||||
unsigned char **payload, int *length, int flag);
|
|
||||||
|
|
||||||
and for removing attached attributes:
|
|
||||||
|
|
||||||
int burn_session_dispose_cdtext(struct burn_session *s, int block);
|
|
||||||
|
|
||||||
int burn_track_dispose_cdtext(struct burn_track *t, int block);
|
|
||||||
|
|
||||||
|
|
||||||
UPC/EAN and ISRC not only affect CD-TEXT but also information that is written
|
|
||||||
along with the tracks in Q sub-channel. These can be influenced by
|
|
||||||
burn_session_input_sheet_v07t(), burn_session_by_cue_file() and by
|
|
||||||
|
|
||||||
void burn_write_opts_set_mediacatalog(struct burn_write_opts *opts,
|
|
||||||
unsigned char mediacatalog[13]);
|
|
||||||
|
|
||||||
void burn_write_opts_set_has_mediacatalog(struct burn_write_opts *opts,
|
|
||||||
int has_mediacatalog);
|
|
||||||
|
|
||||||
void burn_track_set_isrc(struct burn_track *t, char *country, char *owner,
|
|
||||||
unsigned char year, unsigned int serial);
|
|
||||||
|
|
||||||
int burn_track_set_isrc_string(struct burn_track *t, char isrc[13],
|
|
||||||
int flag);
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Sony Text File Format (Input Sheet Version 0.7T):
|
|
||||||
|
|
||||||
This text file format provides comprehensive means to define the text
|
|
||||||
attributes of session and tracks for a single block. More than one
|
|
||||||
such file has to be read to form an attribute set with multiple blocks.
|
|
||||||
|
|
||||||
The information is given by text lines of the following form:
|
|
||||||
purpose specifier [whitespace] = [whitespace] content text
|
|
||||||
[whitespace] is zero or more ASCII 32 (space) or ASCII 9 (tab) characters.
|
|
||||||
The purpose specifier tells the meaning of the content text.
|
|
||||||
Empty content text does not cause a CD-TEXT attribute to be attached.
|
|
||||||
|
|
||||||
The following purpose specifiers apply to the session as a whole:
|
|
||||||
Specifier = Meaning
|
|
||||||
-------------------------------------------------------------------------
|
|
||||||
Text Code = Character code for pack type 0x8f
|
|
||||||
"ASCII", "8859"
|
|
||||||
Language Code = One of the language names for pack type 0x8f
|
|
||||||
Album Title = Content of pack type 0x80
|
|
||||||
Artist Name = Content of pack type 0x81
|
|
||||||
Songwriter = Content of pack type 0x82
|
|
||||||
Composer = Content of pack type 0x83
|
|
||||||
Arranger = Content of pack type 0x84
|
|
||||||
Album Message = Content of pack type 0x85
|
|
||||||
Catalog Number = Content of pack type 0x86
|
|
||||||
Genre Code = One of the genre names for pack type 0x87
|
|
||||||
Genre Information = Cleartext part of pack type 0x87
|
|
||||||
Closed Information = Content of pack type 0x8d
|
|
||||||
UPC / EAN = Content of pack type 0x8e
|
|
||||||
Text Data Copy Protection = Copyright value for pack type 0x8f
|
|
||||||
"ON" = 0x03, "OFF" = 0x00
|
|
||||||
First Track Number = The lowest track number used in the file
|
|
||||||
Last Track Number = The highest track number used in the file
|
|
||||||
|
|
||||||
The following purpose specifiers apply to particular tracks:
|
|
||||||
Track NN Title = Content of pack type 0x80
|
|
||||||
Track NN Artist = Content of pack type 0x81
|
|
||||||
Track NN Songwriter = Content of pack type 0x82
|
|
||||||
Track NN Composer = Content of pack type 0x83
|
|
||||||
Track NN Arranger = Content of pack type 0x84
|
|
||||||
Track NN Message = Content of pack type 0x85
|
|
||||||
ISRC NN = Content of pack type 0x8e
|
|
||||||
|
|
||||||
The following purpose specifiers have no effect on CD-TEXT:
|
|
||||||
Remarks = Comments with no influence on CD-TEXT
|
|
||||||
Disc Information NN = Supplementary information for use by record companies.
|
|
||||||
ISO-8859-1 encoded. NN ranges from 01 to 04.
|
|
||||||
Input Sheet Version = "0.7T"
|
|
||||||
|
|
||||||
|
|
||||||
libburn peculiarties:
|
|
||||||
|
|
||||||
libburn may read files of the described format by
|
|
||||||
burn_session_input_sheet_v07t()
|
|
||||||
after the burn_session has been establiched and all burn_track objects have
|
|
||||||
been added. It can convert an array of CD-TEXT packs into this format by
|
|
||||||
burn_make_input_sheet_v07t()
|
|
||||||
|
|
||||||
The following purpose specifiers accept byte values of the form 0xXY.
|
|
||||||
Text Code , Language Code , Genre Code , Text Data Copy Protection
|
|
||||||
E.g. to indicate MS-JIS character code (of which the exact name is unknown):
|
|
||||||
Text Code = 0x80
|
|
||||||
Genre Code is settable by 0xXY or 0xXYZT or 0xXY 0xZT.
|
|
||||||
Genre Code = 0x001b
|
|
||||||
|
|
||||||
Purpose specifiers which have the meaning "Content of pack type 0xXY"
|
|
||||||
may be replaced by the pack type codes. E.g.:
|
|
||||||
0x80 = Session content of pack type 0x80
|
|
||||||
Track 02 0x80 = Track content of pack type 0x80 for track 2.
|
|
||||||
Applicable are pack types 0x80 to 0x86, 0x8d, 0x8e.
|
|
||||||
|
|
||||||
Text Code may be specified only once. It gets speficied to "ISO-8850-1"
|
|
||||||
automatically as soon as content is defined which depends on the text
|
|
||||||
encoding of the block. I.e with pack types 0x80 to 0x85.
|
|
||||||
|
|
||||||
If a track attribute is set, but the corresponding session attribute is not
|
|
||||||
defined or defined with empty text, then the session attribute gets attached
|
|
||||||
as empty test. (Normally empty content is ignored.)
|
|
||||||
|
|
||||||
|
|
||||||
Example cdrskin run with three tracks:
|
|
||||||
|
|
||||||
$ cdrskin dev=/dev/sr0 -v input_sheet_v07t=NIGHTCATS.TXT \
|
|
||||||
-audio -swab track_source_1 track_source_2 track_source_3
|
|
||||||
|
|
||||||
----------------------------------------------------------
|
|
||||||
Content of file NIGHTCATS.TXT :
|
|
||||||
----------------------------------------------------------
|
|
||||||
Input Sheet Version = 0.7T
|
|
||||||
Text Code = 8859
|
|
||||||
Language Code = English
|
|
||||||
Album Title = Joyful Nights
|
|
||||||
Artist Name = United Cat Orchestra
|
|
||||||
Songwriter = Various Songwriters
|
|
||||||
Composer = Various Composers
|
|
||||||
Arranger = Tom Cat
|
|
||||||
Album Message = For all our fans
|
|
||||||
Catalog Number = 1234567890
|
|
||||||
Genre Code = Classical
|
|
||||||
Genre Information = Feline classic music
|
|
||||||
Closed Information = This is not to be shown by CD players
|
|
||||||
UPC / EAN = 1234567890123
|
|
||||||
Text Data Copy Protection = OFF
|
|
||||||
First Track Number = 1
|
|
||||||
Last Track Number = 3
|
|
||||||
Track 01 Title = Song of Joy
|
|
||||||
Track 01 Artist = Felix and The Purrs
|
|
||||||
Track 01 Songwriter = Friedrich Schiller
|
|
||||||
Track 01 Composer = Ludwig van Beethoven
|
|
||||||
Track 01 Arranger = Tom Cat
|
|
||||||
Track 01 Message = Fritz and Louie once were punks
|
|
||||||
ISRC 01 = XYBLG1101234
|
|
||||||
Track 02 Title = Humpty Dumpty
|
|
||||||
Track 02 Artist = Catwalk Beauties
|
|
||||||
Track 02 Songwriter = Mother Goose
|
|
||||||
Track 02 Composer = unknown
|
|
||||||
Track 02 Arranger = Tom Cat
|
|
||||||
Track 02 Message = Pluck the goose
|
|
||||||
ISRC 02 = XYBLG1100005
|
|
||||||
Track 03 Title = Mee Owwww
|
|
||||||
Track 03 Artist = Mia Kitten
|
|
||||||
Track 03 Songwriter = Mia Kitten
|
|
||||||
Track 03 Composer = Mia Kitten
|
|
||||||
Track 03 Arranger = Mia Kitten
|
|
||||||
Track 03 Message =
|
|
||||||
ISRC 03 = XYBLG1100006
|
|
||||||
----------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
CDRWIN cue sheet files:
|
|
||||||
|
|
||||||
A CDRWIN cue sheet file defines the track data source (FILE), various text
|
|
||||||
attributes (CATALOG, TITLE, PERFORMER, SONGWRITER, ISRC), track block types
|
|
||||||
(TRACK), track start addresses (INDEX).
|
|
||||||
The rules for CDRWIN cue sheet files are described at
|
|
||||||
http://digitalx.org/cue-sheet/syntax/
|
|
||||||
There are three more text attributes mentioned in man cdrecord for defining
|
|
||||||
the corresponding CD-TEXT attributes: ARRANGER, COMPOSER, MESSAGE.
|
|
||||||
|
|
||||||
|
|
||||||
--------------------------------------------------------
|
|
||||||
Example of a CDRWIN cue sheet file named NIGHTCATS.CUE :
|
|
||||||
--------------------------------------------------------
|
|
||||||
|
|
||||||
CATALOG 1234567890123
|
|
||||||
FILE "audiodata.bin" BINARY
|
|
||||||
TITLE "Joyful Nights"
|
|
||||||
TRACK 01 AUDIO
|
|
||||||
FLAGS DCP
|
|
||||||
TITLE "Song of Joy"
|
|
||||||
PERFORMER "Felix and The Purrs"
|
|
||||||
SONGWRITER "Friedrich Schiller"
|
|
||||||
ISRC XYBLG1101234
|
|
||||||
INDEX 01 00:00:00
|
|
||||||
TRACK 02 AUDIO
|
|
||||||
FLAGS DCP
|
|
||||||
TITLE "Humpty Dumpty"
|
|
||||||
PERFORMER "Catwalk Beauties"
|
|
||||||
SONGWRITER "Mother Goose"
|
|
||||||
ISRC XYBLG1100005
|
|
||||||
INDEX 01 08:20:12
|
|
||||||
TRACK 03 AUDIO
|
|
||||||
FLAGS DCP
|
|
||||||
TITLE "Mee Owwww"
|
|
||||||
PERFORMER "Mia Kitten"
|
|
||||||
SONGWRITER "Mia Kitten"
|
|
||||||
ISRC XYBLG1100006
|
|
||||||
INDEX 01 13:20:33
|
|
||||||
|
|
||||||
By
|
|
||||||
|
|
||||||
$ cdrskin -v dev=/dev/sr0 -text cuefile=NIGHTCATS.CUE
|
|
||||||
|
|
||||||
this yields as text packs:
|
|
||||||
|
|
||||||
0 : 80 00 00 00 J o y f u l N i g h t f0 f7
|
|
||||||
1 : 80 00 01 0c s 00 S o n g o f J o 43 1c
|
|
||||||
2 : 80 01 02 0a y 00 H u m p t y D u m 43 f9
|
|
||||||
3 : 80 02 03 0a p t y 00 M e e O w w w 24 72
|
|
||||||
4 : 80 03 04 08 w 00 00 00 00 00 00 00 00 00 00 00 6e af
|
|
||||||
5 : 81 00 05 00 00 F e l i x a n d T 4d 51
|
|
||||||
6 : 81 01 06 0b h e P u r r s 00 C a t a7 40
|
|
||||||
7 : 81 02 07 03 w a l k B e a u t i e 59 80
|
|
||||||
8 : 81 02 08 0f s 00 M i a K i t t e n 30 c9
|
|
||||||
9 : 81 03 09 0a 00 00 00 00 00 00 00 00 00 00 00 00 ad 19
|
|
||||||
10 : 82 00 0a 00 00 F r i e d r i c h S 70 8f
|
|
||||||
11 : 82 01 0b 0b c h i l l e r 00 M o t h 33 43
|
|
||||||
12 : 82 02 0c 04 e r G o o s e 00 M i a d6 f5
|
|
||||||
13 : 82 03 0d 03 K i t t e n 00 00 00 00 00 f5 83
|
|
||||||
14 : 8e 00 0e 00 1 2 3 4 5 6 7 8 9 0 1 2 92 3e
|
|
||||||
15 : 8e 00 0f 0c 3 00 X Y B L G 1 1 0 1 2 c0 2b
|
|
||||||
16 : 8e 01 10 0a 3 4 00 X Y B L G 1 1 0 0 bb b3
|
|
||||||
17 : 8e 02 11 09 0 0 5 00 X Y B L G 1 1 0 f3 bf
|
|
||||||
18 : 8e 03 12 08 0 0 0 6 00 00 00 00 00 00 00 00 5b 5c
|
|
||||||
19 : 8f 00 13 00 00 01 03 00 05 05 04 00 00 00 00 00 9b fe
|
|
||||||
20 : 8f 01 14 00 00 00 00 00 00 00 05 03 15 00 00 00 11 0b
|
|
||||||
21 : 8f 02 15 00 00 00 00 00 09 00 00 00 00 00 00 00 da 77
|
|
||||||
|
|
||||||
--------------------------------------
|
|
||||||
|
|
||||||
Some restrictions apply in the libburn call burn_session_by_cue_file():
|
|
||||||
|
|
||||||
Only FILE types BINARY, MOTOROLA, WAVE are allowed.
|
|
||||||
Only TRACK datatypes AUDIO, MODE1/2048 are allowed. They may not be mixed in
|
|
||||||
the same session.
|
|
||||||
|
|
||||||
On the other hand, ARRANGER, COMPOSER, MESSAGE are supported unconditionally.
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
This text is copyright 2011 - 2012 Thomas Schmitt <scdbackup@gmx.net>.
|
|
||||||
Permission is granted to copy, modify, and distribute it, as long as the
|
|
||||||
references to the original information sources are maintained.
|
|
||||||
There is NO WARRANTY, to the extent permitted by law.
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
119
doc/comments
119
doc/comments
@ -1,119 +0,0 @@
|
|||||||
/**
|
|
||||||
@author Mario Danic, Thomas Schmitt
|
|
||||||
|
|
||||||
@mainpage Libburn Documentation Index
|
|
||||||
|
|
||||||
@section intro Introduction
|
|
||||||
|
|
||||||
Libburnia is an open-source project for reading, mastering and writing
|
|
||||||
optical discs. This page is about its capability to handle optical media.
|
|
||||||
For now this means CD-R, CD-RW, DVD-RAM, DVD+RW, DVD+R, DVD+R/DL, DVD-RW,
|
|
||||||
DVD-R, DVD-R/DL, BD-R, BD-RE.
|
|
||||||
|
|
||||||
Our scope is currently Linux 2.4 and 2.6, FreeBSD, OpenSolaris, or NetBSD.
|
|
||||||
For ports to other systems we would need : login on a development machine or
|
|
||||||
an OS that is installable on an AMD 64-bit PC, advise from a system person
|
|
||||||
about the equivalent of Linux sg or FreeBSD CAM, volunteers for testing of
|
|
||||||
realistic use cases.
|
|
||||||
|
|
||||||
libburn is the library by which preformatted data get onto optical media.
|
|
||||||
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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
SONAME:
|
|
||||||
libburn.so.4 (since 0.3.4, March 2007),
|
|
||||||
|
|
||||||
|
|
||||||
@section using Using libburn
|
|
||||||
|
|
||||||
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 companion applications go into its toplevel directory
|
|
||||||
and execute
|
|
||||||
|
|
||||||
- ./bootstrap (needed if you downloaded from SVN)
|
|
||||||
|
|
||||||
- ./configure
|
|
||||||
|
|
||||||
- make
|
|
||||||
|
|
||||||
To make the libraries accessible for running and developing applications
|
|
||||||
|
|
||||||
- make install
|
|
||||||
|
|
||||||
|
|
||||||
@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 burn to recordable CD, DVD, or BD,
|
|
||||||
can blank a CD-RW or DVD-RW, and can format unformatted DVD-RW, BD-R, or BD-RE.
|
|
||||||
|
|
||||||
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 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] [--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, BD-RE or BD-R:
|
|
||||||
test/libburner --drive /dev/hdc --format
|
|
||||||
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
|
|
||||||
*/
|
|
1520
doc/cookbook.txt
1520
doc/cookbook.txt
File diff suppressed because it is too large
Load Diff
388
doc/ddlp.txt
388
doc/ddlp.txt
@ -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 and 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 and 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.
|
|
||||||
|
|
1884
doc/doxygen.conf.in
1884
doc/doxygen.conf.in
File diff suppressed because it is too large
Load Diff
1216
doc/mediainfo.txt
1216
doc/mediainfo.txt
File diff suppressed because it is too large
Load Diff
@ -1,84 +0,0 @@
|
|||||||
|
|
||||||
Sound extraction for CD-DA burning from .WAV audio file format
|
|
||||||
|
|
||||||
Using information and text snippets
|
|
||||||
from https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
|
|
||||||
in may 2013. The link is now dead. An apparent copy of the page
|
|
||||||
is 2017 at: http://soundfile.sapp.org/doc/WaveFormat/
|
|
||||||
from https://en.wikipedia.org/wiki/WAV
|
|
||||||
|
|
||||||
For libburnia-project.org by Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
December 2017
|
|
||||||
|
|
||||||
|
|
||||||
The WAVE file format is an application of the Microsoft RIFF container format
|
|
||||||
for multimedia files. A RIFF file consists of Chunks which contain Subchunks.
|
|
||||||
The Chunks form a linked list within the file, the Subchunks form a linked
|
|
||||||
list inside their Chunk.
|
|
||||||
All numbers are stored in little-endian byte order.
|
|
||||||
|
|
||||||
A .WAV file consists at least of one Chunk with id "RIFF", which contains
|
|
||||||
one Subchunk with id "fmt " and one with id "data":
|
|
||||||
|
|
||||||
Offset Size Name Description
|
|
||||||
|
|
||||||
0 4 ChunkID Contains the letters "RIFF"
|
|
||||||
4 4 ChunkSize The size of the rest of the chunk following
|
|
||||||
this field. I.e. the two fields ChunkID and
|
|
||||||
ChunkSize are not included in this count.
|
|
||||||
8 4 Format Contains the letters "WAVE"
|
|
||||||
|
|
||||||
|
|
||||||
The "fmt " subchunk describes the sound data's format:
|
|
||||||
|
|
||||||
Offset Size Name Description
|
|
||||||
|
|
||||||
0 4 Subchunk1ID Contains the letters "fmt "
|
|
||||||
|
|
||||||
4 4 Subchunk1Size The size of the rest of the Subchunk following
|
|
||||||
this field. I.e. Subchunk1ID and Subchunk1Size
|
|
||||||
are not included in this count.
|
|
||||||
8 2 AudioFormat PCM = 1 (i.e. Linear quantization)
|
|
||||||
Values other than 1 indicate some
|
|
||||||
form of compression.
|
|
||||||
10 2 NumChannels Mono = 1, Stereo = 2, etc.
|
|
||||||
12 4 SampleRate 8000, 44100, etc.
|
|
||||||
16 4 ByteRate == SampleRate * NumChannels * BitsPerSample/8
|
|
||||||
20 2 BlockAlign == NumChannels * BitsPerSample/8
|
|
||||||
The number of bytes for one sample including
|
|
||||||
all channels.
|
|
||||||
22 2 BitsPerSample 8 bits = 8, 16 bits = 16, etc.
|
|
||||||
More data may follow in this Subchunk if AudioFormat is not PCM.
|
|
||||||
|
|
||||||
|
|
||||||
The "data" subchunk contains the size of the data and the actual sound:
|
|
||||||
|
|
||||||
Offset Size Name Description
|
|
||||||
|
|
||||||
0 4 Subchunk2ID Contains the letters "data"
|
|
||||||
|
|
||||||
4 4 Subchunk2Size == NumSamples * NumChannels * BitsPerSample/8
|
|
||||||
The number of audio data bytes.
|
|
||||||
8 * Data The audio data bytes.
|
|
||||||
|
|
||||||
|
|
||||||
CD-DA prescribes these "fmt " parameters:
|
|
||||||
AudioFormat == 1
|
|
||||||
SampleRate == 44100
|
|
||||||
BitsPerSample == 16
|
|
||||||
NumChannels == 2 (stereo)
|
|
||||||
(little-endian byte order)
|
|
||||||
|
|
||||||
If matching parameters are given in the .WAV file, one can directly use the
|
|
||||||
data bytes of Subchunk "data" as payload for burning a CD-DA track.
|
|
||||||
|
|
||||||
|
|
||||||
Above simple form can be expanded by other Chunks or Subchunks of Chunk "RIFF".
|
|
||||||
A .wav file appeared which beared a Subchunk "LIST" inside Chunk "RIFF".
|
|
||||||
Wikipedia mentions Chunks "INFO", "CSET", "JUNK", "PAD ".
|
|
||||||
|
|
||||||
Therefore one should expect such Chunks before Chunk "RIFF" and Subchunks
|
|
||||||
other than "fmt " and "data" inside the "RIFF" Chunk.
|
|
||||||
Multiple Chunks "RIFF" and Subchunks "fmt " or "data" per file have not been
|
|
||||||
seen yet. They would make extraction more cumbersome.
|
|
||||||
|
|
@ -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
|
|
@ -1,4 +0,0 @@
|
|||||||
all clean:
|
|
||||||
$(MAKE) -C .. -$(MAKEFLAGS) $@
|
|
||||||
|
|
||||||
.PHONY: all clean
|
|
@ -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
|
|
||||||
|
|
||||||
## ========================================================================= ##
|
|
@ -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
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
830
libburn/async.c
830
libburn/async.c
@ -1,830 +0,0 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
|
||||||
Copyright (c) 2006 - 2024 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "libburn.h"
|
|
||||||
#include "transport.h"
|
|
||||||
#include "drive.h"
|
|
||||||
#include "write.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "file.h"
|
|
||||||
#include "async.h"
|
|
||||||
#include "init.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 <signal.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <a ssert.h>
|
|
||||||
*/
|
|
||||||
#include "libdax_msgs.h"
|
|
||||||
extern struct libdax_msgs *libdax_messenger;
|
|
||||||
|
|
||||||
/* ts A80714 : introduced type codes for the worker list */
|
|
||||||
#define Burnworker_type_scaN 0
|
|
||||||
#define Burnworker_type_erasE 1
|
|
||||||
#define Burnworker_type_formaT 2
|
|
||||||
#define Burnworker_type_writE 3
|
|
||||||
#define Burnworker_type_fifO 4
|
|
||||||
|
|
||||||
#define SCAN_GOING() (workers != NULL && \
|
|
||||||
workers->w_type == Burnworker_type_scaN)
|
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
union w_list_data
|
|
||||||
{
|
|
||||||
struct scan_opts scan;
|
|
||||||
struct erase_opts erase;
|
|
||||||
struct format_opts format;
|
|
||||||
struct write_opts write;
|
|
||||||
struct fifo_opts fifo;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct w_list
|
|
||||||
{
|
|
||||||
/* ts A80714 */
|
|
||||||
int w_type; /* see above define Burnworker_type_* */
|
|
||||||
|
|
||||||
struct burn_drive *drive;
|
|
||||||
pthread_t thread;
|
|
||||||
|
|
||||||
struct w_list *next;
|
|
||||||
|
|
||||||
union w_list_data u;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct w_list *workers = NULL;
|
|
||||||
|
|
||||||
static void *fifo_worker_func(struct w_list *w);
|
|
||||||
|
|
||||||
|
|
||||||
int burn_async_manage_lock(int mode)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
static pthread_mutex_t access_lock;
|
|
||||||
static int mutex_initialized = 0;
|
|
||||||
static int mutex_locked = 0;
|
|
||||||
|
|
||||||
if (mode == BURN_ASYNC_LOCK_INIT) {
|
|
||||||
if (mutex_initialized)
|
|
||||||
return 2;
|
|
||||||
ret = pthread_mutex_init(&access_lock, NULL);
|
|
||||||
if (ret != 0)
|
|
||||||
return 0;
|
|
||||||
mutex_initialized = 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (!mutex_initialized)
|
|
||||||
return 0;
|
|
||||||
if (mode == BURN_ASYNC_LOCK_OBTAIN) {
|
|
||||||
ret = pthread_mutex_lock(&access_lock);
|
|
||||||
if (ret != 0)
|
|
||||||
return 0;
|
|
||||||
mutex_locked = 1;
|
|
||||||
} else if (mode == BURN_ASYNC_LOCK_RELEASE) {
|
|
||||||
if (!mutex_locked)
|
|
||||||
return 2;
|
|
||||||
ret = pthread_mutex_unlock(&access_lock);
|
|
||||||
if (ret != 0)
|
|
||||||
return 0;
|
|
||||||
mutex_locked = 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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(int w_type, struct burn_drive *d,
|
|
||||||
WorkerFunc f, union w_list_data *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 = calloc(1, sizeof(struct w_list));
|
|
||||||
a->w_type = w_type;
|
|
||||||
a->drive = d;
|
|
||||||
|
|
||||||
a->u = *data;
|
|
||||||
|
|
||||||
burn_async_manage_lock(BURN_ASYNC_LOCK_INIT);
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
#endif /* Libburn_create_detached_threadS */
|
|
||||||
|
|
||||||
/* Worker specific locks are to be released early by the worker */
|
|
||||||
if (f == (WorkerFunc) fifo_worker_func)
|
|
||||||
burn_async_manage_lock(BURN_ASYNC_LOCK_OBTAIN);
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
pthread_detach(th);
|
|
||||||
/*
|
|
||||||
int ret;
|
|
||||||
char msg[80];
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void reset_progress(struct burn_drive *d, int sessions, int tracks,
|
|
||||||
int indices, off_t sectors, int flag)
|
|
||||||
{
|
|
||||||
/* reset the progress indicator */
|
|
||||||
d->progress.session = 0;
|
|
||||||
d->progress.sessions = sessions;
|
|
||||||
d->progress.track = 0;
|
|
||||||
d->progress.tracks = tracks;
|
|
||||||
d->progress.index = 0;
|
|
||||||
d->progress.indices = indices;
|
|
||||||
d->progress.start_sector = 0;
|
|
||||||
d->progress.sectors = sectors;
|
|
||||||
d->progress.sector = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int burn_drive_scan(struct burn_drive_info *drives[], unsigned int *n_drives)
|
|
||||||
{
|
|
||||||
union w_list_data 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cannot 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.scan.drives = drives;
|
|
||||||
o.scan.n_drives = n_drives;
|
|
||||||
o.scan.done = 0;
|
|
||||||
add_worker(Burnworker_type_scaN, 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)
|
|
||||||
{
|
|
||||||
|
|
||||||
#define Libburn_protect_erase_threaD 1
|
|
||||||
|
|
||||||
#ifdef Libburn_protect_erase_threaD
|
|
||||||
sigset_t sigset, oldset;
|
|
||||||
|
|
||||||
/* Protect blank thread from being interrupted by external signals */
|
|
||||||
sigfillset(&sigset);
|
|
||||||
sigdelset(&sigset, SIGSEGV);
|
|
||||||
sigdelset(&sigset, SIGILL);
|
|
||||||
pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
|
|
||||||
#endif /* Libburn_protect_erase_threaD */
|
|
||||||
|
|
||||||
burn_disc_erase_sync(w->u.erase.drive, w->u.erase.fast);
|
|
||||||
remove_worker(pthread_self());
|
|
||||||
|
|
||||||
#ifdef Libburn_protect_erase_threaD
|
|
||||||
/* (just in case it would not end with all signals blocked) */
|
|
||||||
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
|
||||||
#endif /* Libburn_protect_erase_threaD */
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void burn_disc_erase(struct burn_drive *drive, int fast)
|
|
||||||
{
|
|
||||||
union w_list_data o;
|
|
||||||
|
|
||||||
/* ts A61006 */
|
|
||||||
/* a ssert(drive); */
|
|
||||||
/* a ssert(!SCAN_GOING()); */
|
|
||||||
/* a ssert(!find_worker(drive)); */
|
|
||||||
|
|
||||||
if(drive == NULL) {
|
|
||||||
libdax_msgs_submit(libdax_messenger, -1,
|
|
||||||
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) != NULL) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
reset_progress(drive, 1, 1, 1, (off_t) 0x10000, 0);
|
|
||||||
|
|
||||||
/* 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 overwritable 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() */
|
|
||||||
/* ts B10321 : Allowed role 5 to be blanked */
|
|
||||||
if ((drive->drive_role == 1 &&
|
|
||||||
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 && drive->drive_role != 5)
|
|
||||||
) {
|
|
||||||
char msg[160];
|
|
||||||
|
|
||||||
sprintf(msg, "Drive and media state unsuitable for blanking. (role= %d , profile= 0x%x , status= %d)",
|
|
||||||
drive->drive_role,
|
|
||||||
(unsigned int) drive->current_profile,
|
|
||||||
drive->status);
|
|
||||||
libdax_msgs_submit(libdax_messenger, drive->global_index,
|
|
||||||
0x00020130,
|
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, 0, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
o.erase.drive = drive;
|
|
||||||
o.erase.fast = fast;
|
|
||||||
add_worker(Burnworker_type_erasE, drive,
|
|
||||||
(WorkerFunc) erase_worker_func, &o);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61230 */
|
|
||||||
static void *format_worker_func(struct w_list *w)
|
|
||||||
{
|
|
||||||
|
|
||||||
#define Libburn_protect_format_threaD 1
|
|
||||||
|
|
||||||
#ifdef Libburn_protect_format_threaD
|
|
||||||
sigset_t sigset, oldset;
|
|
||||||
|
|
||||||
/* Protect format thread from being interrupted by external signals */
|
|
||||||
sigfillset(&sigset);
|
|
||||||
sigdelset(&sigset, SIGSEGV);
|
|
||||||
sigdelset(&sigset, SIGILL);
|
|
||||||
pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
|
|
||||||
#endif /* Libburn_protect_format_threaD */
|
|
||||||
|
|
||||||
burn_disc_format_sync(w->u.format.drive, w->u.format.size,
|
|
||||||
w->u.format.flag);
|
|
||||||
remove_worker(pthread_self());
|
|
||||||
|
|
||||||
#ifdef Libburn_protect_format_threaD
|
|
||||||
/* (just in case it would not end with all signals blocked) */
|
|
||||||
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
|
||||||
#endif /* Libburn_protect_format_threaD */
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61230 */
|
|
||||||
void burn_disc_format(struct burn_drive *drive, off_t size, int flag)
|
|
||||||
{
|
|
||||||
union w_list_data o;
|
|
||||||
int ok = 0, ret;
|
|
||||||
char msg[40];
|
|
||||||
|
|
||||||
reset_progress(drive, 1, 1, 1, (off_t) 0x10000, 0);
|
|
||||||
|
|
||||||
if ((SCAN_GOING()) || find_worker(drive) != NULL) {
|
|
||||||
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 == 0x41) {
|
|
||||||
/* BD-R SRM */
|
|
||||||
ok= 1;
|
|
||||||
ret = drive->read_format_capacities(drive, 0x00);
|
|
||||||
if (ret > 0 &&
|
|
||||||
drive->format_descr_type == BURN_FORMAT_IS_FORMATTED)
|
|
||||||
ok = 0;
|
|
||||||
if (drive->status != BURN_DISC_BLANK)
|
|
||||||
ok = 0;
|
|
||||||
if (!ok) {
|
|
||||||
libdax_msgs_submit(libdax_messenger,
|
|
||||||
drive->global_index, 0x00020162,
|
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"BD-R not unformatted blank any more. Cannot format.",
|
|
||||||
0, 0);
|
|
||||||
drive->cancel = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (flag & 32) {
|
|
||||||
libdax_msgs_submit(libdax_messenger,
|
|
||||||
drive->global_index, 0x00020163,
|
|
||||||
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"Blank BD-R left unformatted for zero spare capacity.",
|
|
||||||
0, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (drive->current_profile == 0x43) {
|
|
||||||
ok = 1; /* BD-RE */
|
|
||||||
|
|
||||||
if ((flag & 32) && !(drive->current_feat23h_byte4 & 8)) {
|
|
||||||
libdax_msgs_submit(libdax_messenger,
|
|
||||||
drive->global_index, 0x00020164,
|
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"Drive does not format BD-RE without spares.",
|
|
||||||
0, 0);
|
|
||||||
drive->cancel = 1;
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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.format.drive = drive;
|
|
||||||
o.format.size = size;
|
|
||||||
o.format.flag = flag;
|
|
||||||
add_worker(Burnworker_type_formaT, drive,
|
|
||||||
(WorkerFunc) format_worker_func, &o);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void *write_disc_worker_func(struct w_list *w)
|
|
||||||
{
|
|
||||||
struct burn_drive *d = w->u.write.drive;
|
|
||||||
char msg[80];
|
|
||||||
|
|
||||||
#define Libburn_protect_write_threaD 1
|
|
||||||
|
|
||||||
#ifdef Libburn_protect_write_threaD
|
|
||||||
sigset_t sigset, oldset;
|
|
||||||
|
|
||||||
/* Protect write thread from being interrupted by external signals */
|
|
||||||
sigfillset(&sigset);
|
|
||||||
sigdelset(&sigset, SIGSEGV);
|
|
||||||
sigdelset(&sigset, SIGILL);
|
|
||||||
pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
|
|
||||||
#endif /* Libburn_protect_write_threaD */
|
|
||||||
|
|
||||||
d->thread_pid = getpid();
|
|
||||||
d->thread_tid = pthread_self();
|
|
||||||
d->thread_pid_valid= 1;
|
|
||||||
burn_disc_write_sync(w->u.write.opts, w->u.write.disc);
|
|
||||||
d->thread_pid_valid= 0;
|
|
||||||
d->thread_pid = 0;
|
|
||||||
|
|
||||||
/* the options are refcounted, free out ref count which we added below
|
|
||||||
*/
|
|
||||||
burn_write_opts_free(w->u.write.opts);
|
|
||||||
|
|
||||||
sprintf(msg, "Write thread on drive %d ended", d->global_index);
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00020178,
|
|
||||||
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, 0, 0);
|
|
||||||
|
|
||||||
remove_worker(pthread_self());
|
|
||||||
d->busy = BURN_DRIVE_IDLE;
|
|
||||||
|
|
||||||
#ifdef Libburn_protect_write_threaD
|
|
||||||
/* (just in case it would not end with all signals blocked) */
|
|
||||||
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
|
||||||
#endif /* Libburn_protect_write_threaD */
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
|
|
||||||
{
|
|
||||||
union w_list_data o;
|
|
||||||
char *reasons= NULL;
|
|
||||||
struct burn_drive *d;
|
|
||||||
int mvalid;
|
|
||||||
|
|
||||||
d = opts->drive;
|
|
||||||
|
|
||||||
/* ts A61006 */
|
|
||||||
/* a ssert(!SCAN_GOING()); */
|
|
||||||
/* a ssert(!find_worker(opts->drive)); */
|
|
||||||
if ((SCAN_GOING()) || find_worker(opts->drive) != NULL) {
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x00020102,
|
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"A drive operation is still going on (want to write)",
|
|
||||||
0, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
reset_progress(d, disc->sessions, disc->session[0]->tracks,
|
|
||||||
disc->session[0]->track[0]->indices, (off_t) 0, 0);
|
|
||||||
|
|
||||||
/* For the next lines any return indicates failure */
|
|
||||||
d->cancel = 1;
|
|
||||||
|
|
||||||
/* ts A70203 : people have been warned in API specs */
|
|
||||||
if (opts->write_type == BURN_WRITE_NONE) {
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x0002017c,
|
|
||||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"No valid write type selected", 0, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
if (d->drive_role == 4) {
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x00020181,
|
|
||||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"Pseudo-drive is a read-only file. Cannot write.",
|
|
||||||
0, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ts A61007 : obsolete Assert in spc_select_write_params() */
|
|
||||||
if (d->drive_role == 1) {
|
|
||||||
mvalid = 0;
|
|
||||||
if (d->mdata != NULL)
|
|
||||||
mvalid = 1;
|
|
||||||
if (!mvalid) {
|
|
||||||
libdax_msgs_submit(libdax_messenger,
|
|
||||||
d->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()
|
|
||||||
*/
|
|
||||||
|
|
||||||
BURN_ALLOC_MEM_VOID(reasons, char, BURN_REASONS_LEN + 80);
|
|
||||||
strcpy(reasons, "Write job parameters are unsuitable:\n");
|
|
||||||
if (burn_precheck_write(opts, disc, reasons + strlen(reasons), 1)
|
|
||||||
<= 0) {
|
|
||||||
libdax_msgs_submit(libdax_messenger,
|
|
||||||
d->global_index, 0x00020139,
|
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
reasons, 0, 0);
|
|
||||||
goto ex;
|
|
||||||
}
|
|
||||||
BURN_FREE_MEM(reasons); reasons= NULL;
|
|
||||||
|
|
||||||
/* ts A90106 : early catching of unformatted BD-RE */
|
|
||||||
if (d->current_profile == 0x43)
|
|
||||||
if (d->read_format_capacities(d, 0x00) > 0 &&
|
|
||||||
d->format_descr_type != BURN_FORMAT_IS_FORMATTED) {
|
|
||||||
libdax_msgs_submit(libdax_messenger,
|
|
||||||
d->global_index, 0x00020168,
|
|
||||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"Media not properly formatted. Cannot write.",
|
|
||||||
0, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->cancel = 0; /* End of the return = failure area */
|
|
||||||
|
|
||||||
o.write.drive = d;
|
|
||||||
o.write.opts = opts;
|
|
||||||
o.write.disc = disc;
|
|
||||||
|
|
||||||
opts->refcount++;
|
|
||||||
|
|
||||||
add_worker(Burnworker_type_writE, d,
|
|
||||||
(WorkerFunc) write_disc_worker_func, &o);
|
|
||||||
|
|
||||||
ex:;
|
|
||||||
BURN_FREE_MEM(reasons);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void *fifo_worker_func(struct w_list *w)
|
|
||||||
{
|
|
||||||
|
|
||||||
#define Libburn_protect_fifo_threaD 1
|
|
||||||
|
|
||||||
#ifdef Libburn_protect_fifo_threaD
|
|
||||||
sigset_t sigset, oldset;
|
|
||||||
|
|
||||||
/* Protect fifo thread from being interrupted by external signals */
|
|
||||||
sigfillset(&sigset);
|
|
||||||
sigdelset(&sigset, SIGSEGV);
|
|
||||||
sigdelset(&sigset, SIGILL);
|
|
||||||
pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
|
|
||||||
#endif /* Libburn_protect_fifo_threaD */
|
|
||||||
|
|
||||||
burn_fifo_source_shoveller(w->u.fifo.source, w->u.fifo.flag);
|
|
||||||
remove_worker(pthread_self());
|
|
||||||
|
|
||||||
#ifdef Libburn_protect_fifo_threaD
|
|
||||||
/* (just in case it would not end with all signals blocked) */
|
|
||||||
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
|
||||||
#endif /* Libburn_protect_fifo_threaD */
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int burn_fifo_start(struct burn_source *source, int flag)
|
|
||||||
{
|
|
||||||
union w_list_data o;
|
|
||||||
struct burn_source_fifo *fs = source->data;
|
|
||||||
|
|
||||||
fs->is_started = -1;
|
|
||||||
|
|
||||||
/* create and set up ring buffer */;
|
|
||||||
fs->buf = burn_os_alloc_buffer(
|
|
||||||
((size_t) fs->chunksize) * (size_t) fs->chunks, 0);
|
|
||||||
if (fs->buf == NULL) {
|
|
||||||
/* >>> could not start ring buffer */;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
o.fifo.source = source;
|
|
||||||
o.fifo.flag = flag;
|
|
||||||
add_worker(Burnworker_type_fifO, NULL,
|
|
||||||
(WorkerFunc) fifo_worker_func, &o);
|
|
||||||
fs->is_started = 1;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int burn_fifo_abort(struct burn_source_fifo *fs, int flag)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
pthread_t pt;
|
|
||||||
|
|
||||||
burn_async_manage_lock(BURN_ASYNC_LOCK_OBTAIN);
|
|
||||||
|
|
||||||
if (fs->thread_is_valid <= 0 || fs->thread_handle == NULL) {
|
|
||||||
burn_async_manage_lock(BURN_ASYNC_LOCK_RELEASE);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
pt = *((pthread_t *) fs->thread_handle);
|
|
||||||
|
|
||||||
burn_async_manage_lock(BURN_ASYNC_LOCK_RELEASE);
|
|
||||||
|
|
||||||
fs->do_abort = 1;
|
|
||||||
ret = pthread_join(pt, NULL);
|
|
||||||
|
|
||||||
return (ret == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#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 */
|
|
||||||
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
|
||||||
Copyright (c) 2006 - 2017 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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);
|
|
||||||
|
|
||||||
/* ts A81108 */
|
|
||||||
/* To abort a running fifo thread before the fifo object gets deleted */
|
|
||||||
int burn_fifo_abort(struct burn_source_fifo *fs, int flag);
|
|
||||||
|
|
||||||
/* ts B70126 */
|
|
||||||
#define BURN_ASYNC_LOCK_RELEASE 0
|
|
||||||
#define BURN_ASYNC_LOCK_OBTAIN 1
|
|
||||||
#define BURN_ASYNC_LOCK_INIT 2
|
|
||||||
int burn_async_manage_lock(int mode);
|
|
||||||
|
|
||||||
#endif /* BURN__ASYNC_H */
|
|
@ -1,56 +0,0 @@
|
|||||||
/**
|
|
||||||
Copyright (c) 2006 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
|
|
||||||
This file bundles variables which disable changes in libburn which are
|
|
||||||
not yet completely accepted.
|
|
||||||
|
|
||||||
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 */
|
|
||||||
|
|
||||||
|
|
1737
libburn/cdtext.c
1737
libburn/cdtext.c
File diff suppressed because it is too large
Load Diff
@ -1,242 +0,0 @@
|
|||||||
/*
|
|
||||||
cleanup.c , Copyright 2006 - 2011 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
|
|
||||||
A signal handler which cleans up an application and exits.
|
|
||||||
|
|
||||||
Provided under GPLv2+ license within GPL projects, BSD license elsewise.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
cc -g -o cleanup -DCleanup_standalonE cleanup.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#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. GNU/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=%.f, signum=%d\n",
|
|
||||||
(double) 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static char *Cleanup_signo_to_name(int signo)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for(i= 0; i < signal_list_count; i++)
|
|
||||||
if(signal_list[i] == signo)
|
|
||||||
return(signal_name_list[i]);
|
|
||||||
return("");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
bit8= set SIGPIPE to SIGIGN
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
int i,j,max_sig= -1,min_sig= 0x7fffffff;
|
|
||||||
char *sig_name;
|
|
||||||
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) {
|
|
||||||
/* Avoid to use particular SIG macros which might not be defined.
|
|
||||||
If they are defined, then their names are in the name list.
|
|
||||||
*/
|
|
||||||
if(flag & (8 | 256))
|
|
||||||
sig_name= Cleanup_signo_to_name(i);
|
|
||||||
else
|
|
||||||
sig_name= "";
|
|
||||||
if((flag & 8) && strcmp(sig_name, "SIGABRT") == 0)
|
|
||||||
signal(i,Cleanup_handler_generic);
|
|
||||||
else if((flag & 256) && strcmp(sig_name, "SIGPIPE") == 0)
|
|
||||||
signal(i, SIG_IGN);
|
|
||||||
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;
|
|
||||||
printf("Strange: The system ignored a SIGSEGV: c= %u\n", (unsigned int) c);
|
|
||||||
} else {
|
|
||||||
printf("killme: %d\n",getpid());
|
|
||||||
sleep(3600);
|
|
||||||
}
|
|
||||||
|
|
||||||
Cleanup_set_handlers(NULL,NULL,1);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* Cleanup_standalonE */
|
|
@ -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 GPLv2+ 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 */
|
|
||||||
|
|
642
libburn/crc.c
642
libburn/crc.c
@ -1,642 +0,0 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/* Copyright (c) 2012 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
|
|
||||||
Containing disabled code pieces from other GPL programs.
|
|
||||||
They are just quotes for reference.
|
|
||||||
|
|
||||||
The activated code uses plain polynomial division and other primitve
|
|
||||||
algorithms to build tables of pre-computed CRC values. It then computes
|
|
||||||
the CRCs by algorithms which are derived from mathematical considerations
|
|
||||||
and from analysing the mathematical meaning of the disabled code pieces.
|
|
||||||
|
|
||||||
The comments here are quite detailed in order to prove my own understanding
|
|
||||||
of the topic.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "crc.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* Exploration ts B00214 :
|
|
||||||
ECMA-130, 22.3.6 "CRC field"
|
|
||||||
"This field contains the inverted parity bits. The CRC code word must be
|
|
||||||
divisible by the check polynomial. [...]
|
|
||||||
The generating polynomial shall be
|
|
||||||
G(x) = x^16 + x^12 + x^5 + 1
|
|
||||||
"
|
|
||||||
Also known as CRC-16-CCITT, CRC-CCITT
|
|
||||||
|
|
||||||
Used in libburn for raw write modes in sector.c.
|
|
||||||
There is also disabled code in read.c which would use it.
|
|
||||||
|
|
||||||
ts B11222:
|
|
||||||
The same algorithm is prescribed for CD-TEXT in MMC-3 Annex J.
|
|
||||||
"CRC Field consists of 2 bytes. Initiator system may use these bytes
|
|
||||||
to check errors in the Pack. The polynomial is x^16 + x^12 + x^5 + 1.
|
|
||||||
All bits shall be inverted."
|
|
||||||
|
|
||||||
libburn/cdtext.c uses a simple bit shifting function : crc_11021()
|
|
||||||
|
|
||||||
|
|
||||||
ts B20211:
|
|
||||||
Discussion why both are equivalent in respect to their result:
|
|
||||||
|
|
||||||
Both map the bits of the given bytes to a polynomial over the finite field
|
|
||||||
of two elements "GF(2)". If bytes 0 .. M are given, then bit n of byte m
|
|
||||||
is mapped to the coefficient of x exponent (n + ((M - m) * 8) + 16).
|
|
||||||
I.e. they translate the bits into a polynomial with the highest bit
|
|
||||||
becoming the coefficient of the highest power of x. Then this polynomial
|
|
||||||
is multiplied by (x exp 16).
|
|
||||||
|
|
||||||
The set of all such polynomials forms a commutative ring. Its addition
|
|
||||||
corresponds to bitwise exclusive or. Addition and subtraction are identical.
|
|
||||||
Multiplication with polynomials of only one single non-zero coefficient
|
|
||||||
corresponds to leftward bit shifting by the exponent of that coefficient.
|
|
||||||
The same rules apply as with elementary school arithmetics on integer
|
|
||||||
numbers, but with surprising results due to the finite nature of the
|
|
||||||
coefficient number space.
|
|
||||||
Note that multiplication is _not_ an iteration of addition here.
|
|
||||||
|
|
||||||
Function crc_11021() performs a division with residue by the euclidian
|
|
||||||
algorithm. I.e. it splits polynomial d into quotient q(d) and residue r(d)
|
|
||||||
in respect to the polynomial p = x exp 16 + x exp 12 + x exp 5 + x exp 0
|
|
||||||
d = p * q(d) + r(d)
|
|
||||||
where r(d) is of a polynomial degree lower than p, i.e. only x exp 15
|
|
||||||
or lower have non-zero coefficients.
|
|
||||||
The checksum crc(D) is derived by reverse mapping (r(d) * (x exp 16)).
|
|
||||||
I.e. by mapping the coefficient of (x exp n) to bit n of the 16 bit word
|
|
||||||
crc(D).
|
|
||||||
The function result is the bit-wise complement of crc(D).
|
|
||||||
|
|
||||||
Function crc_ccitt uses a table ccitt_table of r(d) values for the
|
|
||||||
polynomials d which represent the single byte values 0x00 to 0xff.
|
|
||||||
It computes r(d) by computing the residues of an iteratively expanded
|
|
||||||
polynomial. The expansion of the processed byte string A by the next byte B
|
|
||||||
from the input byte string happens by shifting the string 8 bits to the
|
|
||||||
left, and by oring B onto bits 0 to 7.
|
|
||||||
In the space of polynomials, the already processed polynomial "a" (image of
|
|
||||||
byte string A) gets expanded by polynomial b (the image of byte B) like this
|
|
||||||
a * X + b
|
|
||||||
where X is (x exp 8), i.e. the single coefficient polynomial of degree 8.
|
|
||||||
|
|
||||||
The following argumentation uses algebra with commutative, associative
|
|
||||||
and distributive laws.
|
|
||||||
Valid especially with polynomials is this rule:
|
|
||||||
(1): r(a + b) = r(a) + r(b)
|
|
||||||
because r(a) and r(b) are of degree lower than degree(p) and
|
|
||||||
degree(a + b) <= max(degree(a), degree(b))
|
|
||||||
Further valid are:
|
|
||||||
(2): r(a) = r(r(a))
|
|
||||||
(3): r(p * a) = 0
|
|
||||||
|
|
||||||
The residue of this expanded polynomial can be expressed by means of the
|
|
||||||
residue r(a) which is known from the previous iteration step, and the
|
|
||||||
residue r(b) which may be looked up in ccitt_table.
|
|
||||||
r(a * X + b)
|
|
||||||
= r(p * q(a) * X + r(a) * X + p * q(b) + r(b))
|
|
||||||
|
|
||||||
Applying rule (1):
|
|
||||||
= r(p * q(a) * X) + r(r(a) * X) + r(p * q(b)) + r(r(b))
|
|
||||||
|
|
||||||
Rule (3) and rule (2):
|
|
||||||
= r(r(a) * X) + r(b)
|
|
||||||
|
|
||||||
Be h(a) and l(a) chosen so that: r(a) = h(a) * X + l(a),
|
|
||||||
and l(a) has zero coefficients above (x exp 7), and h(a) * X has zero
|
|
||||||
coefficients below (x exp 8). (They correspond to the high and low byte
|
|
||||||
of the 16 bit word crc(A).)
|
|
||||||
So the previous statement can be written as:
|
|
||||||
= r(h(a) * X * X) + r(l(a) * X) + r(b)
|
|
||||||
|
|
||||||
Since the degree of l(a) is lower than 8, the degree of l(a) * X is lower
|
|
||||||
than 16. Thus it cannot be divisible by p which has degree 16.
|
|
||||||
So: r(l(a) * X) = l(a) * X
|
|
||||||
This yields
|
|
||||||
= l(a) * X + r(h(a) * X * X + b)
|
|
||||||
|
|
||||||
h(a) * X * X is the polynomial representation of the high byte of 16 bit
|
|
||||||
word crc(A).
|
|
||||||
So in the world of bit patterns the iteration step is:
|
|
||||||
|
|
||||||
crc(byte string A expanded by byte B)
|
|
||||||
= (low_byte(crc(A)) << 8) ^ crc(high_byte(crc(A)) ^ B)
|
|
||||||
|
|
||||||
And this is what function crc_ccitt() does, modulo swapping the exor
|
|
||||||
operants and the final bit inversion which is prescribed by ECMA-130
|
|
||||||
and MMC-3 Annex J.
|
|
||||||
|
|
||||||
The start value of the table driven byte shifting algorithm may be
|
|
||||||
different from the start value of an equivalent bit shifting algorithm.
|
|
||||||
This is because the final flushing by zero bits is already pre-computed
|
|
||||||
in the table. So the start value of the table driven algorithm must be
|
|
||||||
the CRC of the 0-polynomial under the start value of the bit shifting
|
|
||||||
algorithm.
|
|
||||||
This fact is not of much importance here, because the start value of
|
|
||||||
the bit shifter is 0x0000 which leads to CRC 0x0000 and thus to start
|
|
||||||
value 0x0000 with the table driven byte shifter.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* Plain implementation of polynomial division on a Galois field, where
|
|
||||||
addition and subtraction both are binary exor. Euclidian algorithm.
|
|
||||||
Divisor is x^16 + x^12 + x^5 + 1 = 0x11021.
|
|
||||||
|
|
||||||
This is about ten times slower than the table driven algorithm.
|
|
||||||
*/
|
|
||||||
static int crc_11021(unsigned char *data, int count, int flag)
|
|
||||||
{
|
|
||||||
int acc = 0, i;
|
|
||||||
|
|
||||||
for (i = 0; i < count * 8 + 16; i++) {
|
|
||||||
acc = (acc << 1);
|
|
||||||
if (i < count * 8)
|
|
||||||
acc |= ((data[i / 8] >> (7 - (i % 8))) & 1);
|
|
||||||
if (acc & 0x10000)
|
|
||||||
acc ^= 0x11021;
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* This is my own table driven implementation for which i claim copyright.
|
|
||||||
|
|
||||||
Copyright (c) 2012 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
*/
|
|
||||||
unsigned short crc_ccitt(unsigned char *data, int count)
|
|
||||||
{
|
|
||||||
static unsigned short crc_tab[256], tab_initialized = 0;
|
|
||||||
unsigned short acc = 0;
|
|
||||||
unsigned char b[1];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!tab_initialized) {
|
|
||||||
/* Create table of byte residues */
|
|
||||||
for (i = 0; i < 256; i++) {
|
|
||||||
b[0] = i;
|
|
||||||
crc_tab[i] = crc_11021(b, 1, 0);
|
|
||||||
}
|
|
||||||
tab_initialized = 1;
|
|
||||||
}
|
|
||||||
/* There seems to be a speed advantage on amd64 if (acc << 8) is the
|
|
||||||
second operant of exor, and *(data++) seems faster than data[i].
|
|
||||||
*/
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
acc = crc_tab[(acc >> 8) ^ *(data++)] ^ (acc << 8);
|
|
||||||
|
|
||||||
/* ECMA-130 22.3.6 and MMC-3 Annex J (CD-TEXT) want the result with
|
|
||||||
inverted bits
|
|
||||||
*/
|
|
||||||
return ~acc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
This was the function inherited with libburn-0.2.
|
|
||||||
|
|
||||||
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 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* Exploration ts B00214 :
|
|
||||||
ECMA-130, 14.3 "EDC field"
|
|
||||||
"The EDC field shall consist of 4 bytes recorded in positions 2064 to 2067.
|
|
||||||
The error detection code shall be a 32-bit CRC applied on bytes 0 to 2063.
|
|
||||||
The least significant bit of a data byte is used first. The EDC codeword
|
|
||||||
must be divisible by the check polynomial:
|
|
||||||
P(x) = (x^16 + x^15 + x^2 + 1) . (x^16 + x^2 + x + 1)
|
|
||||||
The least significant parity bit (x^0) is stored in the most significant
|
|
||||||
bit position of byte 2067.
|
|
||||||
"
|
|
||||||
|
|
||||||
Used for raw writing in sector.c
|
|
||||||
|
|
||||||
|
|
||||||
ts B20211:
|
|
||||||
Discussion why function crc_32() implements above prescription of ECMA-130.
|
|
||||||
See end of this file for the ofunction inherited with libburn-0.2.
|
|
||||||
|
|
||||||
The mentioned polynomial product
|
|
||||||
(x^16 + x^15 + x^2 + 1) . (x^16 + x^2 + x + 1)
|
|
||||||
yields this sum of x exponents
|
|
||||||
32 31 18 16
|
|
||||||
18 17 4 2
|
|
||||||
17 16 3 1
|
|
||||||
16 15 2 0
|
|
||||||
======================================
|
|
||||||
32 31 16 15 4 3 1 0
|
|
||||||
(The number of x^18 and x^17 is divisible by two and thus 0 in GF(2).)
|
|
||||||
This yields as 33 bit number:
|
|
||||||
0x18001801b
|
|
||||||
|
|
||||||
If above prescription gets implemented straight forward by function
|
|
||||||
crc_18001801b(), then its results match the ones of crc_32() with all test
|
|
||||||
strings which i could invent.
|
|
||||||
|
|
||||||
The function consists of a conventional polynomial division with reverse
|
|
||||||
input order of bits per byte.
|
|
||||||
|
|
||||||
Further it swaps the bits in the resulting 32 bit word. That is because
|
|
||||||
sector.c:sector_headers writes the 4 bytes of crc_32() as little endian.
|
|
||||||
The ECMA-130 prescription rather demands big endianness and bit swapping
|
|
||||||
towards the normal bit order in bytes:
|
|
||||||
"The EDC field shall consist of 4 bytes recorded in positions 2064 to 2067.
|
|
||||||
[...]
|
|
||||||
The least significant parity bit (x^0) is stored in the most
|
|
||||||
significant bit position of byte 2067."
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* Overall bit mirroring of a 32 bit word */
|
|
||||||
unsigned int rfl32(unsigned int acc)
|
|
||||||
{
|
|
||||||
unsigned int inv_acc;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
inv_acc = 0;
|
|
||||||
for (i = 0; i < 32; i++)
|
|
||||||
if (acc & (1 << i))
|
|
||||||
inv_acc |= 1 << (31 - i);
|
|
||||||
return inv_acc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Plain implementation of polynomial division on a Galois field, where
|
|
||||||
addition and subtraction both are binary exor. Euclidian algorithm.
|
|
||||||
Divisor is (x^16 + x^15 + x^2 + 1) * (x^16 + x^2 + x + 1).
|
|
||||||
|
|
||||||
This is about ten times slower than the table driven algorithm.
|
|
||||||
|
|
||||||
@param flag bit0= do not mirror bits in input bytes and result word
|
|
||||||
(Useful for building the byte indexed CRC table)
|
|
||||||
*/
|
|
||||||
static unsigned int crc_18001801b(unsigned char *data, int count, int flag)
|
|
||||||
{
|
|
||||||
unsigned int acc = 0, top;
|
|
||||||
long int i;
|
|
||||||
unsigned int inv_acc;
|
|
||||||
|
|
||||||
for (i = 0; i < count * 8 + 32; i++) {
|
|
||||||
top = acc & 0x80000000;
|
|
||||||
acc = (acc << 1);
|
|
||||||
if (i < count * 8) {
|
|
||||||
if (flag & 1)
|
|
||||||
/* Normal bit sequence of input bytes */
|
|
||||||
acc |= ((data[i / 8] >> (7 - (i % 8))) & 1);
|
|
||||||
else
|
|
||||||
/* Bit sequence of input bytes mirrored */
|
|
||||||
acc |= ((data[i / 8] >> (i % 8)) & 1);
|
|
||||||
}
|
|
||||||
if (top)
|
|
||||||
acc ^= 0x8001801b;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flag & 1)
|
|
||||||
return (unsigned int) (acc & 0xffffffff);
|
|
||||||
|
|
||||||
/* The bits of the whole 32 bit result are mirrored for ECMA-130
|
|
||||||
output compliance and for sector.c habit to store CRC little endian
|
|
||||||
although ECMA-130 prescribes it big endian.
|
|
||||||
*/
|
|
||||||
inv_acc = rfl32((unsigned int) acc);
|
|
||||||
return inv_acc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
|
|
||||||
Above discussion why crc_ccitt() and crc_11021() yield identical results
|
|
||||||
can be changed from 16 bit to 32 bit by chosing h(a) and l(a) so that:
|
|
||||||
r(a) = h(a) * X * X * X + l(a)
|
|
||||||
h(a) corresponds to the highest byte of crc(A), whereas l(a) corresponds
|
|
||||||
to the lower three bytes of crc(A).
|
|
||||||
|
|
||||||
This yields
|
|
||||||
r(a * X + b)
|
|
||||||
= l(a) * X + r(h(a) * X * X * X * X + b)
|
|
||||||
|
|
||||||
h(a) * X * X * X * X is the polynomial representation of the high byte of
|
|
||||||
32 bit word crc(A).
|
|
||||||
So in the world of bit patterns we have:
|
|
||||||
|
|
||||||
crc(byte string A expanded by byte B)
|
|
||||||
= (lowest_three_bytes(crc(A)) << 8) ^ crc(high_byte(crc(A)) ^ B)
|
|
||||||
|
|
||||||
|
|
||||||
Regrettably this does not yet account for the byte-internal mirroring of
|
|
||||||
bits during the conversion from bit pattern to polynomial, and during
|
|
||||||
conversion from polynomial residue to bit pattern.
|
|
||||||
|
|
||||||
Be rfl8(D) the result of byte-internal mirroring of bit pattern D,
|
|
||||||
and mirr8(d) its corresponding polynom.
|
|
||||||
|
|
||||||
Be now h(a) and l(a) chosen so that: r(mirr8(a)) = h(a) * X * X * X + l(a)
|
|
||||||
This corresponds to highest byte and lower three bytes of crc(A).
|
|
||||||
|
|
||||||
r(mirr8(a) * X + mirr8(b))
|
|
||||||
= r(h(a) * X * X * X * X) + r(l(a) * X) + r(mirr8(b))
|
|
||||||
= l(a)) * X + r(h(a) * X * X * X * X + mirr8(b))
|
|
||||||
|
|
||||||
The corresponding bit pattern operation is
|
|
||||||
|
|
||||||
crc(mirrored byte string A expanded by mirrored byte B)
|
|
||||||
= (lowest_three_bytes(crc(A)) << 8) ^ crc(high_byte(crc(A)) ^ rfl8(B))
|
|
||||||
|
|
||||||
This demands a final result mirroring to meet the ECMA-130 prescription.
|
|
||||||
|
|
||||||
rfl8() can be implemented as lookup table.
|
|
||||||
|
|
||||||
The start value of the bit shifting iteration is 0x00000000, which leads
|
|
||||||
to the same start value for the table driven byte shifting.
|
|
||||||
|
|
||||||
The following function crc32_by_tab() yields the same results as functions
|
|
||||||
crc_18001801b() and crc_32():
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* Byte-internal bit mirroring function.
|
|
||||||
*/
|
|
||||||
unsigned int rfl8(unsigned int acc)
|
|
||||||
{
|
|
||||||
unsigned int inv_acc;
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
inv_acc = 0;
|
|
||||||
for (j = 0; j < 4; j++)
|
|
||||||
for (i = 0; i < 8; i++)
|
|
||||||
if (acc & (1 << (i + 8 * j)))
|
|
||||||
inv_acc |= 1 << ((7 - i) + 8 * j);
|
|
||||||
return inv_acc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef Libburn_with_crc_illustratioN
|
|
||||||
/* Not needed for libburn. The new implementation of function crc_32() is the
|
|
||||||
one that is used.
|
|
||||||
*/
|
|
||||||
|
|
||||||
unsigned int crc32_by_tab(unsigned char *data, int count, int flag)
|
|
||||||
{
|
|
||||||
static unsigned int crc_tab[256], tab_initialized = 0;
|
|
||||||
static unsigned char mirr_tab[256];
|
|
||||||
unsigned int acc, inv_acc;
|
|
||||||
unsigned char b[1];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!tab_initialized) {
|
|
||||||
for (i = 0; i < 256; i++) {
|
|
||||||
b[0] = i;
|
|
||||||
/* Create table of non-mirrored 0x18001801b residues */
|
|
||||||
crc_tab[i] = crc_18001801b(b, 1, 1);
|
|
||||||
/* Create table of mirrored byte values */
|
|
||||||
mirr_tab[i] = rfl8(i);
|
|
||||||
}
|
|
||||||
tab_initialized = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
acc = 0;
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
acc = (acc << 8) ^ crc_tab[(acc >> 24) ^ mirr_tab[data[i]]];
|
|
||||||
|
|
||||||
/* The bits of the whole 32 bit result are mirrored for ECMA-130
|
|
||||||
output compliance and for sector.c habit to store CRC little endian
|
|
||||||
although ECMA-130 prescribes it big endian.
|
|
||||||
*/
|
|
||||||
inv_acc = rfl32((unsigned int) acc);
|
|
||||||
return inv_acc;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* Libburn_with_crc_illustratioN */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
|
|
||||||
Above function yields sufficient performance, nevertheless the old function
|
|
||||||
crc_32() (see below) is faster by avoiding the additional mirror table
|
|
||||||
lookup.
|
|
||||||
A test with 10 times 650 MB on 3000 MHz amd64:
|
|
||||||
crc_18001801b : 187 s
|
|
||||||
crc32_by_tab : 27 s
|
|
||||||
crc_32 : 16 s
|
|
||||||
|
|
||||||
So how does crc_32() avoid the application of bit mirroring to B ?.
|
|
||||||
|
|
||||||
Inherited crc_32() performs
|
|
||||||
crc = crc32_table[(crc ^ *data++) & 0xffL] ^ (crc >> 8);
|
|
||||||
|
|
||||||
Above function crc32_by_tab() would be
|
|
||||||
crc = crc_tab[(crc >> 24) ^ mirr_tab[*data++]] ^ (crc << 8);
|
|
||||||
|
|
||||||
The shortcut does not change the polynomial representation of the algorithm
|
|
||||||
or the mapping from and to bit patterns. It only mirrors the bit direction
|
|
||||||
in the bytes and in the 32-bit words which are involved in the bit pattern
|
|
||||||
computation. This affects input (which is desired), intermediate state
|
|
||||||
(which is as good as unmirrored), and final output (which would be slightly
|
|
||||||
undesirable if libburn could not use the mirrored result anyway).
|
|
||||||
|
|
||||||
Instead of the high byte (crc >> 24), the abbreviated algorithm uses
|
|
||||||
the low byte of the mirrored intermediate checksum (crc & 0xffL).
|
|
||||||
Instead of shifting the other three intermediate bytes to the left
|
|
||||||
(crc << 8), the abbreviated algorithm shifts them to the right (crc >> 8).
|
|
||||||
In both cases they overwrite the single byte that was used for computing
|
|
||||||
the table index.
|
|
||||||
|
|
||||||
The byte indexed table of CRC values needs to hold mirrored 32 bit values.
|
|
||||||
The byte index [(crc ^ *data++) & 0xffL] would need to be mirrored, which
|
|
||||||
would eat up the gain of not mirroring the input bytes. But this mirroring
|
|
||||||
can be pre-computed into the table by exchanging each value with the value
|
|
||||||
of its mirrored index.
|
|
||||||
|
|
||||||
So this relation exists between the CRC table crc_tab[] of crc32_by_tab()
|
|
||||||
and the table crc32_table[] of the abbreviated algorithm crc_32():
|
|
||||||
|
|
||||||
crc_tab[i] == rfl32(crc32_table[rfl8(i)])
|
|
||||||
|
|
||||||
for i={0..255}.
|
|
||||||
|
|
||||||
I compared the generated table in crc32_by_tab() by this test
|
|
||||||
for (i = 0; i < 256; i++) {
|
|
||||||
if (rfl32(crc_tab[rfl8(i)]) != crc32_table[i] ||
|
|
||||||
crc_tab[i] != rfl32(crc32_table[rfl8(i)])) {
|
|
||||||
printf("DEVIATION : i = %d\n", i);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
No screaming abort happened.
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This is my own mirrored table implementation for which i claim copyright.
|
|
||||||
With gcc -O2 it shows the same efficiency as the inherited implementation
|
|
||||||
below. With -O3, -O1, or -O0 it is only slightly slower.
|
|
||||||
|
|
||||||
Copyright (c) 2012 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
*/
|
|
||||||
unsigned int crc_32(unsigned char *data, int count)
|
|
||||||
{
|
|
||||||
static unsigned int crc_tab[256], tab_initialized = 0;
|
|
||||||
unsigned int acc = 0;
|
|
||||||
unsigned char b[1];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!tab_initialized) {
|
|
||||||
/* Create table of mirrored 0x18001801b residues in
|
|
||||||
bit-mirrored index positions.
|
|
||||||
*/
|
|
||||||
for (i = 0; i < 256; i++) {
|
|
||||||
b[0] = i;
|
|
||||||
crc_tab[rfl8(i)] = rfl32(crc_18001801b(b, 1, 1));
|
|
||||||
}
|
|
||||||
tab_initialized = 1;
|
|
||||||
}
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
acc = (acc >> 8) ^ crc_tab[(acc & 0xff) ^ data[i]];
|
|
||||||
|
|
||||||
/* The bits of the whole 32 bit result stay mirrored for ECMA-130
|
|
||||||
output 8-bit mirroring and for sector.c habit to store the CRC
|
|
||||||
little endian although ECMA-130 prescribes it big endian.
|
|
||||||
*/
|
|
||||||
return acc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
|
|
||||||
This was the function inherited with libburn-0.2 which implements the
|
|
||||||
abbreviated algorithm. Its obscure existence led me to above insights.
|
|
||||||
My compliments to the (unknown) people who invented this.
|
|
||||||
|
|
||||||
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 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;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
|
||||||
Copyright (c) 2012 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
#ifndef BURN__CRC_H
|
|
||||||
#define BURN__CRC_H
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef Xorriso_standalonE
|
|
||||||
/* Source module crc.c of yet unclear ancestry is excluded from GNU xorriso */
|
|
||||||
/* ts B20219 : The functions have been re-implemented from scratch after
|
|
||||||
studying texts about CRC computation and understanding the
|
|
||||||
meaning of the underlying ECMA-130 specs.
|
|
||||||
Nevertheless, there is no need to include them into xorriso
|
|
||||||
because it does neither CD-TEXT nor raw CD writing.
|
|
||||||
*/
|
|
||||||
#ifndef Libburn_no_crc_C
|
|
||||||
#define Libburn_no_crc_C 1
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef Libburn_no_crc_C
|
|
||||||
|
|
||||||
unsigned short crc_ccitt(unsigned char *, int len);
|
|
||||||
unsigned int crc_32(unsigned char *, int len);
|
|
||||||
|
|
||||||
#endif /* Libburn_no_crc_C */
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* BURN__CRC_H */
|
|
621
libburn/ddlpa.c
621
libburn/ddlpa.c
@ -1,621 +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 explicitly 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
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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
|
|
||||||
#ifndef O_BINARY
|
|
||||||
#define O_BINARY 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 | O_BINARY;
|
|
||||||
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 | O_BINARY;
|
|
||||||
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 | O_BINARY);
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
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 */
|
|
||||||
|
|
107
libburn/ddlpa.h
107
libburn/ddlpa.h
@ -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 */
|
|
@ -1,28 +0,0 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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 */
|
|
3864
libburn/drive.c
3864
libburn/drive.c
File diff suppressed because it is too large
Load Diff
181
libburn/drive.h
181
libburn/drive.h
@ -1,181 +0,0 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
|
||||||
Copyright (c) 2006 - 2024 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __DRIVE
|
|
||||||
#define __DRIVE
|
|
||||||
|
|
||||||
#include "libburn.h"
|
|
||||||
#include "toc.h"
|
|
||||||
#include "structure.h"
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
struct burn_drive;
|
|
||||||
struct command;
|
|
||||||
struct mempage;
|
|
||||||
struct scsi_mode_data;
|
|
||||||
struct burn_speed_descriptor;
|
|
||||||
struct burn_feature_descr;
|
|
||||||
|
|
||||||
#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, int flag);
|
|
||||||
|
|
||||||
|
|
||||||
/* 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 , tid */
|
|
||||||
int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid,
|
|
||||||
pthread_t tid);
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A51221 - A80731 : Whitelist inquiry functions */
|
|
||||||
int burn_drive_is_banned(char *device_address);
|
|
||||||
int burn_drive_whitelist_count(void);
|
|
||||||
char *burn_drive_whitelist_item(int idx, int flag);
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A80801 */
|
|
||||||
int burn_drive_is_listed(char *path, struct burn_drive **found, int flag);
|
|
||||||
|
|
||||||
|
|
||||||
/* ts B00226 : Outsourced backend of burn_abort()
|
|
||||||
@param elapsed to be subtracted from start time
|
|
||||||
@param flag bit0= do not shutdown the library
|
|
||||||
*/
|
|
||||||
int burn_abort_5(int patience,
|
|
||||||
int (*pacifier_func)(void *handle, int patience, int elapsed),
|
|
||||||
void *handle, int elapsed, int flag);
|
|
||||||
|
|
||||||
/* ts B10730 */
|
|
||||||
/* Send a default mode page 05 to CD and DVD-R-oids */
|
|
||||||
int burn_drive_send_default_page_05(struct burn_drive *d, int flag);
|
|
||||||
|
|
||||||
|
|
||||||
/* ts B40106 */
|
|
||||||
int burn_feature_descr_new(struct burn_feature_descr **new,
|
|
||||||
unsigned char *descr, int descr_len, int flag);
|
|
||||||
|
|
||||||
/* ts B40106 */
|
|
||||||
int burn_feature_descr_free(struct burn_feature_descr **new, int flag);
|
|
||||||
|
|
||||||
/* ts B40107 */
|
|
||||||
int burn_drive_has_feature(struct burn_drive *d, int feature_code,
|
|
||||||
struct burn_feature_descr **descr, int flag);
|
|
||||||
|
|
||||||
int burn_drive_grab_stdio(struct burn_drive *d, int flag);
|
|
||||||
|
|
||||||
/* ts C10213 */
|
|
||||||
/* The size of limitless or oversized devices as pseudo drives */
|
|
||||||
/* Do not lightheartedly change this value because of its meaning to
|
|
||||||
burn_drive.media_read_capacity in libburn/transport.h
|
|
||||||
64 TiB = 2 exp 46 = 2 exp 35 blocks
|
|
||||||
*/
|
|
||||||
#define BURN_DRIVE_MAX_BYTES ((off_t) (0x800000000) * (off_t) 2048)
|
|
||||||
|
|
||||||
#endif /* __DRIVE */
|
|
@ -1,855 +0,0 @@
|
|||||||
|
|
||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ts A91016 : libburn/ecma130ab.c is the replacement for old libburn/lec.c
|
|
||||||
|
|
||||||
Copyright 2009, Thomas Schmitt <scdbackup@gmx.net>, libburnia-project.org
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
|
|
||||||
This code module implements the production of RSPC parity bytes (P- and Q-
|
|
||||||
parity) and the scrambling of raw CD-ROM sectors as specified in ECMA-130:
|
|
||||||
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-130.pdf
|
|
||||||
|
|
||||||
The following statements about Galois Fields have been learned mostly from
|
|
||||||
http://www.cs.utk.edu/~plank/plank/papers/CS-96-332.pdf
|
|
||||||
by James S. Plank after an e-mail exchange with Norbert Preining.
|
|
||||||
|
|
||||||
The output has been compared with the output of the old code of libburn
|
|
||||||
which was labeled "borrowed HEAVILY from cdrdao" and claimed by Joerg
|
|
||||||
Schilling to stem from code by Heiko Eissfeldt.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
|
||||||
Note: In this text, "^" denotes exponentiation and not the binary exor
|
|
||||||
operation. Confusingly in the C code "^" is said exor.
|
|
||||||
Note: This is not C1, C2 which is rather mentioned in ECMA-130 Annex C and
|
|
||||||
always performed inside the drive.
|
|
||||||
-------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
RSPC , P- and Q-Parity
|
|
||||||
|
|
||||||
ECMA-130 Annex A prescribes to compute the parity bytes for P-columns and
|
|
||||||
Q-diagonals by RSPC based on a Galois Field GF(2^8) with enumerating
|
|
||||||
polynomials x^8+x^4+x^3+x^2+1 (i.e. 0x11d) and x^1 (i.e. 0x02).
|
|
||||||
Bytes 12 to 2075 of a audio-sized sector get ordered in two byte words
|
|
||||||
as 24 rows and 43 columns. Then this matrix is split into a LSB matrix
|
|
||||||
and a MSB matrix of the same layout. Parity bytes are to be computed
|
|
||||||
from these 8-bit values.
|
|
||||||
2 P-bytes cover each column of 24 bytes. They get appended to the matrix
|
|
||||||
as rows 24 and 25.
|
|
||||||
2 Q-bytes cover each the 26 diagonals of the extended matrix.
|
|
||||||
|
|
||||||
Both parity byte pairs have to be computed so that extended rows or
|
|
||||||
diagonals match this linear equation:
|
|
||||||
H x V = (0,0)
|
|
||||||
H is a 2-row matrix of size n matching the length of the V ectors
|
|
||||||
[ 1 1 ... 1 1 ]
|
|
||||||
[ x^(n-1) x^(n-2) x^1 1 ]
|
|
||||||
Vp represents a P-row. It is a byte vector consisting of row bytes at
|
|
||||||
position 0 to 23 and the two parity bytes which shall be determined
|
|
||||||
at position 24 and 25. So Hp has 26 columns.
|
|
||||||
Vq represents a Q-diagonal. It is a byte vector consisting of diagonal
|
|
||||||
bytes at position 0 to 42 and the two parity bytes at position 43 and 44.
|
|
||||||
So Hq has 45 columns. The Q-diagonals cover P-parity bytes.
|
|
||||||
|
|
||||||
By applying some high school algebra one gets the parity bytes b0, b1 of
|
|
||||||
vector V = (n_payload_bytes, b0 , b1) as
|
|
||||||
|
|
||||||
b0 = ( H[n] * SUM(n_payload_bytes) - H[0..(n-1)] x n_payload_bytes )
|
|
||||||
/ (H[n+1] - H[n])
|
|
||||||
b1 = - SUM(n_payload_bytes) - b0
|
|
||||||
|
|
||||||
H[i] is the i-the element of the second row of matrix H. E.g. H[0] = x^(n-1)
|
|
||||||
The result has to be computed by Galois field arithmetics. See below.
|
|
||||||
|
|
||||||
The P-parity bytes of each column get reunited as LSB and MSB of two words.
|
|
||||||
word1 gets written to positions 1032 to 1074, word0 to 1075 to 1117.
|
|
||||||
The Q-parity bytes of each diagonal get reunited too. word1 goes to 1118
|
|
||||||
to 1143, word0 to 1144 to 1169.
|
|
||||||
>>> I do not read this swap of word1 and word0 from ECMA-130 Annex A.
|
|
||||||
>>> But the new output matches the old output only if it is done that way.
|
|
||||||
>>> See correctness reservation below.
|
|
||||||
|
|
||||||
Algebra on Galois fields is the same as on Rational Numbers.
|
|
||||||
But arithmetics on its polynomials differ from usual integer arithmetics
|
|
||||||
on binary numbers.
|
|
||||||
Addition and subtraction are identical with the binary exor operator.
|
|
||||||
Multiplication and division would demand polynomial division, e.g. by the
|
|
||||||
euclidean algorithm. The computing path over logarithms and powers follows
|
|
||||||
algebra and reduces the arithmetic task to table lookups, additions
|
|
||||||
modulo 255, and exor operations. Note that the logarithms are natural
|
|
||||||
numbers, not polynomials. They get added or subtracted by the usual addition
|
|
||||||
(not by exor) and their polynomial power depends on their value modulo 255.
|
|
||||||
|
|
||||||
Needed are a logarithm table and a power table (or inverse logarithm table)
|
|
||||||
for Galois Field GF(2^8) which will serve to perform the peculiar
|
|
||||||
multiplication and division operation of Galois fields.
|
|
||||||
|
|
||||||
The power table is simply an enumeration of x^n accorting to
|
|
||||||
GF-multiplication. It also serves as second line of matrix H for the parity
|
|
||||||
equations:
|
|
||||||
Hp[i] = gfpow[25-i] , i out of {0,..,25}
|
|
||||||
Hq[i] = gfpow[44-i] , i out of {0,..,44}
|
|
||||||
|
|
||||||
The logarithm table is the inverse permutation of the power table.
|
|
||||||
|
|
||||||
Some simplifications apply to the implementation:
|
|
||||||
In the world of Galois fields there is no difference between - and +.
|
|
||||||
The term (H[n+1] - H[n]) is constant: 3.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
Scrambling
|
|
||||||
|
|
||||||
ECMA-130 Annex B prescribes to exor the byte stream of an audio-sized sector
|
|
||||||
with a sequence of pseudo random bytes. It mentions polynomial x^15+x+1 and
|
|
||||||
a 15-bit register.
|
|
||||||
It shows a diagram of a Feedback Shift Register with 16 bit boxes, though.
|
|
||||||
|
|
||||||
Comparing this with explanations in
|
|
||||||
http://www.newwaveinstruments.com/resources/articles/m_sequence_linear_feedback_shift_register_lfsr.htm
|
|
||||||
one can recognize the diagram as a Fibonacci Implementation. But there seems
|
|
||||||
really to be one bit box too many.
|
|
||||||
|
|
||||||
The difference of both lengths is expressed in function next_bit() by
|
|
||||||
the constants 0x3fff,0x4000 for 15 bit versus 0x7fff,0x8000 for 16 bits.
|
|
||||||
Comparing the output of both alternatives with the old scrambler output
|
|
||||||
lets 15 bit win for now.
|
|
||||||
|
|
||||||
So the prescription is to start with 15 bit value 1, to use the lowest bit
|
|
||||||
as output, to shift the bits down by one, to exor the output bit with the
|
|
||||||
next lowest bit, and to put that exor result into bit 14 of the register.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
Correctness Reservation
|
|
||||||
|
|
||||||
In both cases, parity and scrambling, the goal for now is to replicate the
|
|
||||||
output of the dismissed old lec.c by output which is based on published
|
|
||||||
specs and own implementation code. Whether they comply to ECMA-130 is a
|
|
||||||
different question which can only be answered by real test cases for
|
|
||||||
raw CD recording.
|
|
||||||
|
|
||||||
Of course this implementation will be corrected so that it really complies
|
|
||||||
to ECMA-130 as soon as evidence emerges that it does not yet.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
|
|
||||||
/* Power and logarithm tables for GF(2^8), parity matrices for ECMA-130.
|
|
||||||
Generated by burn_rspc_setup_tables() and burn_rspc_print_tables().
|
|
||||||
|
|
||||||
The highest possible sum of gflog[] values is is 508. So the table gfpow[]
|
|
||||||
with period 255 was manually unrolled to 509 elements to avoid one modulo
|
|
||||||
255 operation in burn_rspc_mult().
|
|
||||||
Proposed by D. Hugh Redelmeier.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
static unsigned char gfpow[509] = {
|
|
||||||
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,
|
|
||||||
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,
|
|
||||||
};
|
|
||||||
|
|
||||||
static unsigned char gflog[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
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#define Libburn_use_h_matriceS 1
|
|
||||||
|
|
||||||
#ifdef Libburn_use_h_matriceS
|
|
||||||
|
|
||||||
/* On my AMD 2x64 bit 3000 MHz processor h[i] costs about 7 % more time
|
|
||||||
than using gfpow[25-i] and gfpow[44-1]. I blame this on the more
|
|
||||||
condensed data representation which slightly increases the rate of cache
|
|
||||||
hits.
|
|
||||||
Nevertheless this effect is very likely depending on the exact cache
|
|
||||||
size and architecture. In general, using h[] saves more than 8000
|
|
||||||
subtractions per sector.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Parity matrices H as prescribed by ECMA-130 Annex A.
|
|
||||||
Actually just reverted order start pieces of gfpow[].
|
|
||||||
*/
|
|
||||||
static unsigned char h26[26] = {
|
|
||||||
3, 143, 201, 234, 117, 180, 90, 45, 152, 76,
|
|
||||||
38, 19, 135, 205, 232, 116, 58, 29, 128, 64,
|
|
||||||
32, 16, 8, 4, 2, 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
static unsigned char h45[45] = {
|
|
||||||
238, 119, 181, 212, 106, 53, 148, 74, 37, 156,
|
|
||||||
78, 39, 157, 192, 96, 48, 24, 12, 6, 3,
|
|
||||||
143, 201, 234, 117, 180, 90, 45, 152, 76, 38,
|
|
||||||
19, 135, 205, 232, 116, 58, 29, 128, 64, 32,
|
|
||||||
16, 8, 4, 2, 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* Libburn_use_h_matriceS */
|
|
||||||
|
|
||||||
|
|
||||||
/* Pseudo-random bytes which of course are exactly the same as with the
|
|
||||||
previously used code.
|
|
||||||
Generated by function print_ecma_130_scrambler().
|
|
||||||
*/
|
|
||||||
static unsigned char ecma_130_annex_b[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
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
|
|
||||||
/* This is the new implementation of P- and Q-parity generation.
|
|
||||||
It needs about the same computing time as the old implementation (both
|
|
||||||
with gcc -O2 on AMD 64 bit). Measurements indicate that about 280 MIPS
|
|
||||||
are needed for 48x CD speed (7.1 MB/s).
|
|
||||||
*/
|
|
||||||
|
|
||||||
static unsigned char burn_rspc_mult(unsigned char a, unsigned char b)
|
|
||||||
{
|
|
||||||
if (a == 0 || b == 0)
|
|
||||||
return 0;
|
|
||||||
/* Optimization of (a == 0 || b == 0) by D. Hugh Redelmeier
|
|
||||||
if((((int)a - 1) | ((int)b - 1)) < 0)
|
|
||||||
return 0;
|
|
||||||
*/
|
|
||||||
|
|
||||||
return gfpow[gflog[a] + gflog[b]];
|
|
||||||
/* % 255 not necessary because gfpow is unrolled up to index 510 */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Divide by polynomial 0x03. Derived from burn_rspc_div() and using the
|
|
||||||
unrolled size of the gfpow[] array.
|
|
||||||
*/
|
|
||||||
static unsigned char burn_rspc_div_3(unsigned char a)
|
|
||||||
{
|
|
||||||
if (a == 0)
|
|
||||||
return 0;
|
|
||||||
return gfpow[230 + gflog[a]];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void burn_rspc_p0p1(unsigned char *sector, int col,
|
|
||||||
unsigned char *p0_lsb, unsigned char *p0_msb,
|
|
||||||
unsigned char *p1_lsb, unsigned char *p1_msb)
|
|
||||||
{
|
|
||||||
unsigned char *start, b;
|
|
||||||
unsigned int i, sum_v_lsb = 0, sum_v_msb = 0;
|
|
||||||
unsigned int hxv_lsb = 0, hxv_msb = 0;
|
|
||||||
|
|
||||||
start = sector + 12 + 2 * col;
|
|
||||||
for(i = 0; i < 24; i++) {
|
|
||||||
b = *start;
|
|
||||||
sum_v_lsb ^= b;
|
|
||||||
|
|
||||||
#ifdef Libburn_use_h_matriceS
|
|
||||||
hxv_lsb ^= burn_rspc_mult(b, h26[i]);
|
|
||||||
#else
|
|
||||||
hxv_lsb ^= burn_rspc_mult(b, gfpow[25 - i]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
b = *(start + 1);
|
|
||||||
sum_v_msb ^= b;
|
|
||||||
|
|
||||||
#ifdef Libburn_use_h_matriceS
|
|
||||||
hxv_msb ^= burn_rspc_mult(b, h26[i]);
|
|
||||||
#else
|
|
||||||
hxv_msb ^= burn_rspc_mult(b, gfpow[25 - i]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
start += 86;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 3 = gfpow[1] ^ gfpow[0] , 2 = gfpow[1] */
|
|
||||||
*p0_lsb = burn_rspc_div_3(burn_rspc_mult(2, sum_v_lsb) ^ hxv_lsb);
|
|
||||||
*p0_msb = burn_rspc_div_3(burn_rspc_mult(2, sum_v_msb) ^ hxv_msb);
|
|
||||||
*p1_lsb = sum_v_lsb ^ *p0_lsb;
|
|
||||||
*p1_msb = sum_v_msb ^ *p0_msb;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void burn_rspc_parity_p(unsigned char *sector)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
unsigned char p0_lsb, p0_msb, p1_lsb, p1_msb;
|
|
||||||
|
|
||||||
/* Loop over P columns */
|
|
||||||
for(i = 0; i < 43; i++) {
|
|
||||||
burn_rspc_p0p1(sector, i, &p0_lsb, &p0_msb, &p1_lsb, &p1_msb);
|
|
||||||
sector[2162 + 2 * i] = p0_lsb;
|
|
||||||
sector[2162 + 2 * i + 1] = p0_msb;
|
|
||||||
sector[2076 + 2 * i] = p1_lsb;
|
|
||||||
sector[2076 + 2 * i + 1] = p1_msb;
|
|
||||||
|
|
||||||
#ifdef Libburn_with_lec_generatoR
|
|
||||||
if(verbous) {
|
|
||||||
printf("p %2d : %2.2X %2.2X ", i,
|
|
||||||
(unsigned int) p0_lsb, (unsigned int) p0_msb);
|
|
||||||
printf("%2.2X %2.2X ",
|
|
||||||
(unsigned int) p1_lsb, (unsigned int) p1_msb);
|
|
||||||
printf("-> %d,%d\n", 2162 + 2 * i, 2076 + 2 * i);
|
|
||||||
}
|
|
||||||
#endif /* Libburn_with_lec_generatoR */
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void burn_rspc_q0q1(unsigned char *sector, int diag,
|
|
||||||
unsigned char *q0_lsb, unsigned char *q0_msb,
|
|
||||||
unsigned char *q1_lsb, unsigned char *q1_msb)
|
|
||||||
{
|
|
||||||
unsigned char *start, b;
|
|
||||||
unsigned int i, idx, sum_v_lsb = 0, sum_v_msb = 0;
|
|
||||||
unsigned int hxv_lsb = 0, hxv_msb = 0;
|
|
||||||
|
|
||||||
start = sector + 12;
|
|
||||||
idx = 2 * 43 * diag;
|
|
||||||
for(i = 0; i < 43; i++) {
|
|
||||||
if (idx >= 2236)
|
|
||||||
idx -= 2236;
|
|
||||||
b = start[idx];
|
|
||||||
sum_v_lsb ^= b;
|
|
||||||
|
|
||||||
#ifdef Libburn_use_h_matriceS
|
|
||||||
hxv_lsb ^= burn_rspc_mult(b, h45[i]);
|
|
||||||
#else
|
|
||||||
hxv_lsb ^= burn_rspc_mult(b, gfpow[44 - i]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
b = start[idx + 1];
|
|
||||||
sum_v_msb ^= b;
|
|
||||||
|
|
||||||
#ifdef Libburn_use_h_matriceS
|
|
||||||
hxv_msb ^= burn_rspc_mult(b, h45[i]);
|
|
||||||
#else
|
|
||||||
hxv_msb ^= burn_rspc_mult(b, gfpow[44 - i]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
idx += 88;
|
|
||||||
}
|
|
||||||
/* 3 = gfpow[1] ^ gfpow[0] , 2 = gfpow[1] */
|
|
||||||
*q0_lsb = burn_rspc_div_3(burn_rspc_mult(2, sum_v_lsb) ^ hxv_lsb);
|
|
||||||
*q0_msb = burn_rspc_div_3(burn_rspc_mult(2, sum_v_msb) ^ hxv_msb);
|
|
||||||
*q1_lsb = sum_v_lsb ^ *q0_lsb;
|
|
||||||
*q1_msb = sum_v_msb ^ *q0_msb;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void burn_rspc_parity_q(unsigned char *sector)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
unsigned char q0_lsb, q0_msb, q1_lsb, q1_msb;
|
|
||||||
|
|
||||||
/* Loop over Q diagonals */
|
|
||||||
for(i = 0; i < 26; i++) {
|
|
||||||
burn_rspc_q0q1(sector, i, &q0_lsb, &q0_msb, &q1_lsb, &q1_msb);
|
|
||||||
sector[2300 + 2 * i] = q0_lsb;
|
|
||||||
sector[2300 + 2 * i + 1] = q0_msb;
|
|
||||||
sector[2248 + 2 * i] = q1_lsb;
|
|
||||||
sector[2248 + 2 * i + 1] = q1_msb;
|
|
||||||
|
|
||||||
#ifdef Libburn_with_lec_generatoR
|
|
||||||
if(verbous) {
|
|
||||||
printf("q %2d : %2.2X %2.2X ", i,
|
|
||||||
(unsigned int) q0_lsb, (unsigned int) q0_msb);
|
|
||||||
printf("%2.2X %2.2X ",
|
|
||||||
(unsigned int) q1_lsb, (unsigned int) q1_msb);
|
|
||||||
printf("-> %d,%d\n", 2300 + 2 * i, 2248 + 2 * i);
|
|
||||||
}
|
|
||||||
#endif /* Libburn_with_lec_generatoR */
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
|
|
||||||
/* The new implementation of the ECMA-130 Annex B scrambler.
|
|
||||||
It is totally unoptimized. One should make use of larger word operations.
|
|
||||||
Measurements indicate that about 50 MIPS are needed for 48x CD speed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void burn_ecma130_scramble(unsigned char *sector)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
unsigned char *s;
|
|
||||||
|
|
||||||
s = sector + 12;
|
|
||||||
for (i = 0; i < 2340; i++)
|
|
||||||
s[i] ^= ecma_130_annex_b[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
|
|
||||||
/* The following code is not needed for libburn but rather documents the
|
|
||||||
origin of the tables above. In libburn it will not be compiled.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef Libburn_with_lec_generatoR
|
|
||||||
|
|
||||||
|
|
||||||
/* This function produced the content of gflog[] and gfpow[]
|
|
||||||
*/
|
|
||||||
static int burn_rspc_setup_tables(void)
|
|
||||||
{
|
|
||||||
unsigned int b, l;
|
|
||||||
|
|
||||||
memset(gflog, 0, sizeof(gflog));
|
|
||||||
memset(gfpow, 0, sizeof(gfpow));
|
|
||||||
b = 1;
|
|
||||||
for (l = 0; l < 255; l++) {
|
|
||||||
gfpow[l] = (unsigned char) b;
|
|
||||||
gflog[b] = (unsigned char) l;
|
|
||||||
b = b << 1;
|
|
||||||
if (b & 256)
|
|
||||||
b = b ^ 0x11d;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* This function printed the content of gflog[] and gfpow[] as C code
|
|
||||||
and compared the content with the tables of the old implementation.
|
|
||||||
h26[] and h45[] are reverted order copies of gfpow[]
|
|
||||||
*/
|
|
||||||
static int burn_rspc_print_tables(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
printf("static unsigned char gfpow[255] = {");
|
|
||||||
printf("\n\t");
|
|
||||||
for(i= 0; i < 255; i++) {
|
|
||||||
printf("%3u, ", gfpow[i]);
|
|
||||||
|
|
||||||
#ifdef Libburn_with_old_lec_comparisoN
|
|
||||||
if(gfpow[i] != gf8_ilog[i])
|
|
||||||
fprintf(stderr, "*** ILOG %d : %d != %d ***\n", i, gfpow[i], gf8_ilog[i]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if((i % 10) == 9)
|
|
||||||
printf("\n\t");
|
|
||||||
}
|
|
||||||
printf("\n};\n\n");
|
|
||||||
|
|
||||||
printf("static unsigned char gflog[256] = {");
|
|
||||||
printf("\n\t");
|
|
||||||
for(i= 0; i < 256; i++) {
|
|
||||||
printf(" %3u,", gflog[i]);
|
|
||||||
|
|
||||||
#ifdef Libburn_with_old_lec_comparisoN
|
|
||||||
if(gflog[i] != gf8_log[i])
|
|
||||||
fprintf(stderr, "*** LOG %d : %d != %d ***\n", i, gflog[i], gf8_log[i]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if((i % 10) == 9)
|
|
||||||
printf("\n\t");
|
|
||||||
}
|
|
||||||
printf("\n};\n\n");
|
|
||||||
|
|
||||||
printf("static unsigned char h26[26] = {");
|
|
||||||
printf("\n\t");
|
|
||||||
for(i= 0; i < 26; i++) {
|
|
||||||
printf(" %3u,", gfpow[25 - i]);
|
|
||||||
if((i % 10) == 9)
|
|
||||||
printf("\n\t");
|
|
||||||
}
|
|
||||||
printf("\n};\n\n");
|
|
||||||
|
|
||||||
printf("static unsigned char h45[45] = {");
|
|
||||||
printf("\n\t");
|
|
||||||
for(i= 0; i < 45; i++) {
|
|
||||||
printf(" %3u,",gfpow[44 - i]);
|
|
||||||
if((i % 10) == 9)
|
|
||||||
printf("\n\t");
|
|
||||||
}
|
|
||||||
printf("\n};\n\n");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* This code was used to generate the content of array ecma_130_annex_b[].
|
|
||||||
*/
|
|
||||||
static unsigned short ecma_130_fsr = 1;
|
|
||||||
|
|
||||||
static int next_bit(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = ecma_130_fsr & 1;
|
|
||||||
ecma_130_fsr = (ecma_130_fsr >> 1) & 0x3fff;
|
|
||||||
if (ret ^ (ecma_130_fsr & 1))
|
|
||||||
ecma_130_fsr |= 0x4000;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int print_ecma_130_scrambler(void)
|
|
||||||
{
|
|
||||||
int i, j, b;
|
|
||||||
|
|
||||||
ecma_130_fsr = 1;
|
|
||||||
printf("static unsigned char ecma_130_annex_b[2340] = {");
|
|
||||||
printf("\n\t");
|
|
||||||
for (i = 0; i < 2340; i++) {
|
|
||||||
b = 0;
|
|
||||||
for (j = 0; j < 8; j++)
|
|
||||||
b |= next_bit() << j;
|
|
||||||
|
|
||||||
printf("%3u, ", b);
|
|
||||||
if ((i % 10) == 9)
|
|
||||||
printf("\n\t");
|
|
||||||
}
|
|
||||||
printf("\n};\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef Libburn_with_general_rspc_diV
|
|
||||||
|
|
||||||
/* This is a general polynomial division function.
|
|
||||||
burn_rspc_div_3() has been derived from this by setting b to constant 3.
|
|
||||||
*/
|
|
||||||
static unsigned char burn_rspc_div(unsigned char a, unsigned char b)
|
|
||||||
{
|
|
||||||
int d;
|
|
||||||
|
|
||||||
if (a == 0)
|
|
||||||
return 0;
|
|
||||||
if (b == 0)
|
|
||||||
return -1;
|
|
||||||
d = gflog[a] - gflog[b];
|
|
||||||
if (d < 0)
|
|
||||||
d += 255;
|
|
||||||
return gfpow[d];
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* Libburn_with_general_rspc_diV */
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* Libburn_with_lec_generatoR */
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
|||||||
|
|
||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/* ts A91016 : libburn/ecma130ab.h is the replacement for old libburn/lec.h
|
|
||||||
|
|
||||||
Copyright 2009, Thomas Schmitt <scdbackup@gmx.net>, libburnia-project.org
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
|
|
||||||
This code module implements the computations prescribed in ECMA-130 Annex A
|
|
||||||
and B. For explanations of the underlying mathematics see ecma130ab.c .
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef Libburn_ecma130ab_includeD
|
|
||||||
#define Libburn_ecma130ab_includeD 1
|
|
||||||
|
|
||||||
void burn_rspc_parity_p(unsigned char *sector);
|
|
||||||
|
|
||||||
void burn_rspc_parity_q(unsigned char *sector);
|
|
||||||
|
|
||||||
void burn_ecma130_scramble(unsigned char *sector);
|
|
||||||
|
|
||||||
#endif /* ! Libburn_ecma130ab_includeD */
|
|
||||||
|
|
@ -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 */
|
|
1124
libburn/file.c
1124
libburn/file.c
File diff suppressed because it is too large
Load Diff
102
libburn/file.h
102
libburn/file.h
@ -1,102 +0,0 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
|
||||||
Copyright (c) 2006 - 2017 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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_shoveller()
|
|
||||||
which shovels data and finally destroys the resources.
|
|
||||||
This late start is to stay modest in case of multiple tracks
|
|
||||||
in one disc.
|
|
||||||
*/
|
|
||||||
int is_started;
|
|
||||||
|
|
||||||
void *thread_handle; /* actually a pointer to a thread_t */
|
|
||||||
int thread_pid;
|
|
||||||
int thread_is_valid;
|
|
||||||
|
|
||||||
/* The shoveller aborts if this is 1. Resource leaks are possible. */
|
|
||||||
volatile int do_abort;
|
|
||||||
|
|
||||||
/* the burn_source for which this fifo is acting as proxy */
|
|
||||||
struct burn_source *inp;
|
|
||||||
int inp_read_size;
|
|
||||||
|
|
||||||
/* <<< 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;
|
|
||||||
|
|
||||||
int total_min_fill;
|
|
||||||
int interval_min_fill;
|
|
||||||
int put_counter;
|
|
||||||
int get_counter;
|
|
||||||
int empty_counter;
|
|
||||||
int full_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);
|
|
||||||
|
|
||||||
|
|
||||||
/* ts B00922 */
|
|
||||||
struct burn_source_offst {
|
|
||||||
|
|
||||||
/* See burn_offst_source_new() */
|
|
||||||
struct burn_source *inp;
|
|
||||||
struct burn_source *prev;
|
|
||||||
off_t start;
|
|
||||||
off_t size;
|
|
||||||
int size_adjustable;
|
|
||||||
|
|
||||||
/* for set_size/get_size */
|
|
||||||
off_t nominal_size;
|
|
||||||
|
|
||||||
/* To help offst_free() */
|
|
||||||
struct burn_source *next;
|
|
||||||
|
|
||||||
/* The current reading position */
|
|
||||||
int running;
|
|
||||||
off_t pos;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* LIBBURN__FILE_H */
|
|
664
libburn/init.c
664
libburn/init.c
@ -1,664 +0,0 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
|
||||||
Copyright (c) 2006 - 2013 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
/* ts A61007 */
|
|
||||||
/* #include <a ssert.h> */
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
/* ts A70928 : init.h is for others, not for init .c
|
|
||||||
#include "init.h"
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "sg.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "libburn.h"
|
|
||||||
#include "drive.h"
|
|
||||||
#include "transport.h"
|
|
||||||
#include "util.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;
|
|
||||||
|
|
||||||
double lib_start_time;
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A60813 : GNU/Linux: whether to use O_EXCL on open() of device files
|
|
||||||
ts B00212 : FreeBSD: whether to use flock(LOCK_EX) after open()
|
|
||||||
*/
|
|
||||||
int burn_sg_open_o_excl = 1;
|
|
||||||
|
|
||||||
/* ts A70403 : GNU/Linux: whether to use fcntl(,F_SETLK,)
|
|
||||||
after open() of device files */
|
|
||||||
int burn_sg_fcntl_f_setlk = 1;
|
|
||||||
|
|
||||||
/* ts A70314 : GNU/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;
|
|
||||||
|
|
||||||
/* whether 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;
|
|
||||||
|
|
||||||
|
|
||||||
/* The message returned from sg_id_string() and/or sg_initialize()
|
|
||||||
*/
|
|
||||||
static char sg_initialize_msg[1024] = {""};
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61002 */
|
|
||||||
|
|
||||||
#include "cleanup.h"
|
|
||||||
|
|
||||||
/* Parameters for builtin abort handler */
|
|
||||||
static char abort_message_prefix[81] = {"libburn : "};
|
|
||||||
static pid_t abort_control_pid= 0;
|
|
||||||
static pthread_t abort_control_thread;
|
|
||||||
volatile int burn_global_abort_level= 0;
|
|
||||||
int burn_global_abort_signum= 0;
|
|
||||||
void *burn_global_signal_handle = NULL;
|
|
||||||
burn_abort_handler_t burn_global_signal_handler = NULL;
|
|
||||||
int burn_builtin_signal_action = 0; /* burn_set_signal_handling() */
|
|
||||||
volatile int burn_builtin_triggered_action = 0; /* burn_is_aborting() */
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A70223 : whether implemented untested profiles are supported */
|
|
||||||
int burn_support_untested_profiles = 0;
|
|
||||||
|
|
||||||
/* ts A91111 :
|
|
||||||
whether to log SCSI commands (to be implemented in sg-*.c)
|
|
||||||
bit0= log in /tmp/libburn_sg_command_log
|
|
||||||
bit1= log to stderr
|
|
||||||
bit2= flush every line
|
|
||||||
*/
|
|
||||||
int burn_sg_log_scsi = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/* ts B10312 :
|
|
||||||
Whether to map random-access readonly files to drive role 4.
|
|
||||||
Else it is role 2 overwritable drive
|
|
||||||
*/
|
|
||||||
int burn_drive_role_4_allowed = 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;
|
|
||||||
|
|
||||||
lib_start_time = burn_get_time(0);
|
|
||||||
burn_support_untested_profiles = 0;
|
|
||||||
ret = burn_msgs_initialize();
|
|
||||||
if (ret <= 0)
|
|
||||||
return 0;
|
|
||||||
ret = sg_initialize(sg_initialize_msg, 0);
|
|
||||||
if (ret <= 0) {
|
|
||||||
libdax_msgs_submit(libdax_messenger, -1,
|
|
||||||
0x00020175,
|
|
||||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
sg_initialize_msg, 0, 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
burn_running = 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
sg_shutdown(0);
|
|
||||||
|
|
||||||
burn_drive_clear_whitelist();
|
|
||||||
|
|
||||||
burn_running = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A91226 */
|
|
||||||
/** API function. See libburn.h */
|
|
||||||
char *burn_scsi_transport_id(int flag)
|
|
||||||
{
|
|
||||||
if (!burn_running)
|
|
||||||
sg_id_string(sg_initialize_msg, 0);
|
|
||||||
return sg_initialize_msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A60813 */
|
|
||||||
/** API function. See libburn.h */
|
|
||||||
void burn_preset_device_open(int exclusive, int blocking, int abort_on_busy)
|
|
||||||
{
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts B21214 API */
|
|
||||||
char *burn_list_sev_texts(int flag)
|
|
||||||
{
|
|
||||||
char *sev_list;
|
|
||||||
|
|
||||||
libdax_msgs__sev_to_text(0, &sev_list, 1);
|
|
||||||
return sev_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts B00224 */
|
|
||||||
char *burn_util_thread_id(pid_t pid, pthread_t tid, char text[80])
|
|
||||||
{
|
|
||||||
int i, l;
|
|
||||||
|
|
||||||
sprintf(text, "[%lu,", (unsigned long int) getpid());
|
|
||||||
l= strlen(text);
|
|
||||||
for(i= 0; i < ((int) sizeof(pthread_t)) && 2 * i < 80 - l - 3; i++)
|
|
||||||
sprintf(text + l + 2 * i,
|
|
||||||
"%2.2X", ((unsigned char *) &tid)[i]);
|
|
||||||
|
|
||||||
sprintf(text + l + 2 * i, "]");
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts B20122 */
|
|
||||||
/* @param value 0=return rather than exit(value)
|
|
||||||
*/
|
|
||||||
int burn_abort_exit(int value)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
if (value)
|
|
||||||
exit(value);
|
|
||||||
burn_global_abort_level = -2;
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
char text[80];
|
|
||||||
|
|
||||||
fprintf(stderr, "libburn_ABORT: in = %s\n",
|
|
||||||
burn_util_thread_id(getpid(), pthread_self(), text));
|
|
||||||
fprintf(stderr, "libburn_ABORT: ctrl = %s\n",
|
|
||||||
burn_util_thread_id(abort_control_pid, abort_control_thread,
|
|
||||||
text));
|
|
||||||
if (burn_global_signal_handler == burn_builtin_abort_handler)
|
|
||||||
fprintf(stderr, "libburn_ABORT: signal action = %d\n",
|
|
||||||
burn_builtin_signal_action);
|
|
||||||
|
|
||||||
/* >>> find writing drives and report their tid
|
|
||||||
fprintf(stderr, "libburn_ABORT: wrt = %s\n",
|
|
||||||
burn_util_thread_id(0, burn_write_thread_id, text));
|
|
||||||
fprintf(stderr, "libburn_ABORT: sig= %d\n", signum);
|
|
||||||
*/
|
|
||||||
#endif
|
|
||||||
|
|
||||||
burn_builtin_triggered_action = burn_builtin_signal_action;
|
|
||||||
burn_global_abort_level = -1;
|
|
||||||
|
|
||||||
if (burn_builtin_signal_action > 1) {
|
|
||||||
Cleanup_set_handlers(NULL, NULL, 2);
|
|
||||||
if (burn_builtin_signal_action == 4)
|
|
||||||
return -2;
|
|
||||||
fprintf(stderr,"%sABORT : Trying to shut down busy drives\n",
|
|
||||||
abort_message_prefix);
|
|
||||||
fprintf(stderr,
|
|
||||||
"%sABORT : Wait the normal burning time before any kill -9\n",
|
|
||||||
abort_message_prefix);
|
|
||||||
burn_abort_5(0, burn_abort_pacifier, abort_message_prefix,
|
|
||||||
0, 1);
|
|
||||||
libdax_msgs_submit(libdax_messenger, -1, 0x00020177,
|
|
||||||
LIBDAX_MSGS_SEV_ABORT, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"Urged drive worker threads to do emergency halt",
|
|
||||||
0, 0);
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ---- old deprecated stuck-in-abort-handler loop ---- */
|
|
||||||
|
|
||||||
/* ts A70928:
|
|
||||||
Must be quick. Allowed to coincide with other thread and to share
|
|
||||||
the increment with that one. It must not decrease, though, and
|
|
||||||
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(),
|
|
||||||
pthread_self());
|
|
||||||
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_exit(0);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61002 : API */
|
|
||||||
void burn_set_signal_handling(void *handle, burn_abort_handler_t handler,
|
|
||||||
int mode)
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
fprintf(stderr, "libburn_experimental: burn_set_signal_handling, handler==%lx mode=%d\n", (unsigned long) handler, mode);
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(handler == NULL) {
|
|
||||||
handler = burn_builtin_abort_handler;
|
|
||||||
/*
|
|
||||||
if ((mode & ~4) == 0)
|
|
||||||
fprintf(stderr, "libburn_experimental: activated burn_builtin_abort_handler() with handle '%s'\n",(handle==NULL ? "libburn : " : (char *) handle));
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
|
||||||
strcpy(abort_message_prefix, "libburn : ");
|
|
||||||
abort_message_prefix[0] = 0;
|
|
||||||
if(handle != NULL && handler == burn_builtin_abort_handler)
|
|
||||||
strncpy(abort_message_prefix, (char *) handle,
|
|
||||||
sizeof(abort_message_prefix)-1);
|
|
||||||
abort_message_prefix[sizeof(abort_message_prefix)-1] = 0;
|
|
||||||
abort_control_pid = getpid();
|
|
||||||
abort_control_thread = pthread_self();
|
|
||||||
burn_builtin_signal_action = (mode >> 4) & 15;
|
|
||||||
if((mode & 11) != 0)
|
|
||||||
burn_builtin_signal_action = 0;
|
|
||||||
if(burn_builtin_signal_action > 1)
|
|
||||||
burn_builtin_triggered_action = 0;
|
|
||||||
if(burn_builtin_signal_action == 0)
|
|
||||||
burn_builtin_signal_action = 1;
|
|
||||||
Cleanup_set_handlers(handle, (Cleanup_app_handler_T) handler,
|
|
||||||
(mode & 15) | 4 | (mode & 256));
|
|
||||||
burn_global_signal_handle = handle;
|
|
||||||
burn_global_signal_handler = handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts B00304 : API */
|
|
||||||
int burn_is_aborting(int flag)
|
|
||||||
{
|
|
||||||
return burn_builtin_triggered_action;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts B00225 */
|
|
||||||
/* @return 0= no abort action 2 pending , 1= not control thread
|
|
||||||
*/
|
|
||||||
int burn_init_catch_on_abort(int flag)
|
|
||||||
{
|
|
||||||
if (burn_builtin_triggered_action != 2)
|
|
||||||
return 0;
|
|
||||||
if (abort_control_pid != getpid() ||
|
|
||||||
abort_control_thread != pthread_self())
|
|
||||||
return 1;
|
|
||||||
burn_abort(4440, burn_abort_pacifier, abort_message_prefix);
|
|
||||||
fprintf(stderr,
|
|
||||||
"\n%sABORT : Program done. Even if you do not see a shell prompt.\n\n",
|
|
||||||
abort_message_prefix);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* B20122 */
|
|
||||||
/* Temporarily disable builtin actions 0,1,2 to avoid that burn_abort()
|
|
||||||
waits for its own thread to end grabbing.
|
|
||||||
*/
|
|
||||||
int burn_grab_prepare_sig_action(int *signal_action_mem, int flag)
|
|
||||||
{
|
|
||||||
*signal_action_mem = -1;
|
|
||||||
if (burn_global_signal_handler == burn_builtin_abort_handler &&
|
|
||||||
burn_builtin_signal_action >= 0 &&
|
|
||||||
burn_builtin_signal_action <= 2) {
|
|
||||||
*signal_action_mem = burn_builtin_signal_action;
|
|
||||||
burn_builtin_signal_action = 3;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* B20122 */
|
|
||||||
/* Re-enable builtin actions 0,1,2 and perform delayed signal reactions
|
|
||||||
*/
|
|
||||||
int burn_grab_restore_sig_action(int signal_action_mem, int flag)
|
|
||||||
{
|
|
||||||
if (signal_action_mem >= 0)
|
|
||||||
burn_builtin_signal_action = signal_action_mem;
|
|
||||||
if (burn_is_aborting(0) && signal_action_mem >= 0) {
|
|
||||||
if (signal_action_mem == 0 || signal_action_mem == 1) {
|
|
||||||
burn_abort_exit(1); /* Never comes back */
|
|
||||||
} else if (signal_action_mem == 2) {
|
|
||||||
burn_builtin_triggered_action = signal_action_mem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A91111 API */
|
|
||||||
void burn_set_scsi_logging(int flag)
|
|
||||||
{
|
|
||||||
burn_sg_log_scsi = flag & 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts B10312 API */
|
|
||||||
void burn_allow_drive_role_4(int allowed)
|
|
||||||
{
|
|
||||||
burn_drive_role_4_allowed = (allowed & 0xf);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts B10606 */
|
|
||||||
void *burn_alloc_mem(size_t size, size_t count, int flag)
|
|
||||||
{
|
|
||||||
void *pt;
|
|
||||||
|
|
||||||
pt = calloc(count, size);
|
|
||||||
if(pt == NULL)
|
|
||||||
libdax_msgs_submit(libdax_messenger, -1, 0x00000003,
|
|
||||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"Out of virtual memory", 0, 0);
|
|
||||||
return pt;
|
|
||||||
}
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
|
||||||
Copyright (c) 2006 - 2013 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BURN__INIT_H
|
|
||||||
#define BURN__INIT_H
|
|
||||||
|
|
||||||
extern int burn_running;
|
|
||||||
|
|
||||||
extern double lib_start_time;
|
|
||||||
|
|
||||||
/** Indicator for burn_drive_get_status() whether 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;
|
|
||||||
|
|
||||||
extern int burn_builtin_signal_action; /* burn_set_signal_handling() */
|
|
||||||
extern volatile int burn_builtin_triggered_action; /* burn_is_aborting() */
|
|
||||||
|
|
||||||
|
|
||||||
/* ts B00225 */
|
|
||||||
/* @return 0= no abort pending , 1= not control thread ,
|
|
||||||
-1= surprisingly burn_abort returned
|
|
||||||
*/
|
|
||||||
int burn_init_catch_on_abort(int flag);
|
|
||||||
|
|
||||||
/* ts B10606 */
|
|
||||||
void *burn_alloc_mem(size_t size, size_t count, int flag);
|
|
||||||
|
|
||||||
#define BURN_ALLOC_MEM(pt, typ, count) { \
|
|
||||||
pt= (typ *) burn_alloc_mem(sizeof(typ), (size_t) (count), 0); \
|
|
||||||
if(pt == NULL) { \
|
|
||||||
ret= -1; goto ex; \
|
|
||||||
} }
|
|
||||||
|
|
||||||
#define BURN_ALLOC_MEM_VOID(pt, typ, count) { \
|
|
||||||
pt= (typ *) burn_alloc_mem(sizeof(typ), (size_t) (count), 0); \
|
|
||||||
if(pt == NULL) { \
|
|
||||||
goto ex; \
|
|
||||||
} }
|
|
||||||
|
|
||||||
#define BURN_FREE_MEM(pt) { \
|
|
||||||
if(pt != NULL) \
|
|
||||||
free((char *) pt); \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* B20122 */
|
|
||||||
int burn_grab_prepare_sig_action(int *signal_action_mem, int flag);
|
|
||||||
int burn_grab_restore_sig_action(int signal_action_mem, int flag);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* BURN__INIT_H */
|
|
4655
libburn/libburn.h
4655
libburn/libburn.h
File diff suppressed because it is too large
Load Diff
@ -1,226 +0,0 @@
|
|||||||
LIBBURN4 {
|
|
||||||
global:
|
|
||||||
burn_abort;
|
|
||||||
burn_abort_pacifier;
|
|
||||||
burn_allow_drive_role_4;
|
|
||||||
burn_allow_untested_profiles;
|
|
||||||
burn_cdtext_from_session;
|
|
||||||
burn_cdtext_from_packfile;
|
|
||||||
burn_disc_add_session;
|
|
||||||
burn_disc_available_space;
|
|
||||||
burn_disc_close_damaged;
|
|
||||||
burn_disc_create;
|
|
||||||
burn_disc_erasable;
|
|
||||||
burn_disc_erase;
|
|
||||||
burn_disc_format;
|
|
||||||
burn_disc_free;
|
|
||||||
burn_disc_free_multi_caps;
|
|
||||||
burn_disc_get_bd_spare_info;
|
|
||||||
burn_disc_get_cd_info;
|
|
||||||
burn_disc_get_format_descr;
|
|
||||||
burn_disc_get_formats;
|
|
||||||
burn_disc_get_incomplete_sessions;
|
|
||||||
burn_disc_get_leadin_text;
|
|
||||||
burn_disc_get_media_id;
|
|
||||||
burn_disc_get_msc1;
|
|
||||||
burn_disc_get_multi_caps;
|
|
||||||
burn_disc_get_phys_format_info;
|
|
||||||
burn_disc_get_profile;
|
|
||||||
burn_disc_get_sectors;
|
|
||||||
burn_disc_get_sessions;
|
|
||||||
burn_disc_get_status;
|
|
||||||
burn_disc_next_track_is_damaged;
|
|
||||||
burn_disc_pretend_blank;
|
|
||||||
burn_disc_pretend_full;
|
|
||||||
burn_disc_pretend_full_uncond;
|
|
||||||
burn_disc_read;
|
|
||||||
burn_disc_read_atip;
|
|
||||||
burn_disc_remove_session;
|
|
||||||
burn_disc_track_lba_nwa;
|
|
||||||
burn_disc_write;
|
|
||||||
burn_drive_add_whitelist;
|
|
||||||
burn_drive_cancel;
|
|
||||||
burn_drive_clear_whitelist;
|
|
||||||
burn_drive_convert_fs_adr;
|
|
||||||
burn_drive_convert_scsi_adr;
|
|
||||||
burn_drive_d_get_adr;
|
|
||||||
burn_drive_equals_adr;
|
|
||||||
burn_drive_extract_audio;
|
|
||||||
burn_drive_extract_audio_track;
|
|
||||||
burn_drive_free_speedlist;
|
|
||||||
burn_drive_get_adr;
|
|
||||||
burn_drive_get_all_profiles;
|
|
||||||
burn_drive_get_bd_r_pow;
|
|
||||||
burn_drive_get_best_speed;
|
|
||||||
burn_drive_get_disc;
|
|
||||||
burn_drive_get_drive_role;
|
|
||||||
burn_drive_get_feature;
|
|
||||||
burn_drive_get_feature_codes;
|
|
||||||
burn_drive_get_immed;
|
|
||||||
burn_drive_get_media_sno;
|
|
||||||
burn_drive_get_min_write_speed;
|
|
||||||
burn_drive_get_read_speed;
|
|
||||||
burn_drive_get_serial_no;
|
|
||||||
burn_drive_get_speedlist;
|
|
||||||
burn_drive_get_start_end_lba;
|
|
||||||
burn_drive_get_status;
|
|
||||||
burn_drive_get_write_speed;
|
|
||||||
burn_drive_grab;
|
|
||||||
burn_drive_info_forget;
|
|
||||||
burn_drive_info_free;
|
|
||||||
burn_drive_is_enumerable_adr;
|
|
||||||
burn_drive_leave_locked;
|
|
||||||
burn_drive_obtain_scsi_adr;
|
|
||||||
burn_drive_probe_cd_write_modes;
|
|
||||||
burn_drive_re_assess;
|
|
||||||
burn_drive_release;
|
|
||||||
burn_drive_reset_simulate;
|
|
||||||
burn_drive_scan;
|
|
||||||
burn_drive_scan_and_grab;
|
|
||||||
burn_drive_set_buffer_waiting;
|
|
||||||
burn_drive_set_immed;
|
|
||||||
burn_drive_set_speed;
|
|
||||||
burn_drive_set_speed_exact;
|
|
||||||
burn_drive_set_stream_recording;
|
|
||||||
burn_drive_snooze;
|
|
||||||
burn_drive_was_feat21_failure;
|
|
||||||
burn_drive_wrote_well;
|
|
||||||
burn_fd_source_new;
|
|
||||||
burn_fifo_fill;
|
|
||||||
burn_fifo_get_statistics;
|
|
||||||
burn_fifo_inquire_status;
|
|
||||||
burn_fifo_next_interval;
|
|
||||||
burn_fifo_peek_data;
|
|
||||||
burn_fifo_source_new;
|
|
||||||
burn_file_source_new;
|
|
||||||
burn_finish;
|
|
||||||
burn_get_read_capacity;
|
|
||||||
burn_guess_cd_manufacturer;
|
|
||||||
burn_guess_manufacturer;
|
|
||||||
burn_initialize;
|
|
||||||
burn_is_aborting;
|
|
||||||
burn_lba_to_msf;
|
|
||||||
burn_list_sev_texts;
|
|
||||||
burn_lookup_device_link;
|
|
||||||
burn_make_input_sheet_v07t;
|
|
||||||
burn_msf_to_lba;
|
|
||||||
burn_msf_to_sectors;
|
|
||||||
burn_msgs_obtain;
|
|
||||||
burn_msgs_set_severities;
|
|
||||||
burn_msgs_submit;
|
|
||||||
burn_nominal_slowdown;
|
|
||||||
burn_obtain_profile_name;
|
|
||||||
burn_offst_source_new;
|
|
||||||
burn_os_alloc_buffer;
|
|
||||||
burn_os_free_buffer;
|
|
||||||
burn_os_open_track_src;
|
|
||||||
burn_precheck_write;
|
|
||||||
burn_preset_device_open;
|
|
||||||
burn_random_access_write;
|
|
||||||
burn_read_audio;
|
|
||||||
burn_read_data;
|
|
||||||
burn_read_opts_free;
|
|
||||||
burn_read_opts_new;
|
|
||||||
burn_read_opts_read_subcodes_audio;
|
|
||||||
burn_read_opts_read_subcodes_data;
|
|
||||||
burn_read_opts_report_recovered_errors;
|
|
||||||
burn_read_opts_set_c2errors;
|
|
||||||
burn_read_opts_set_hardware_error_recovery;
|
|
||||||
burn_read_opts_set_hardware_error_retries;
|
|
||||||
burn_read_opts_set_raw;
|
|
||||||
burn_read_opts_transfer_damaged_blocks;
|
|
||||||
burn_scsi_transport_id;
|
|
||||||
burn_sectors_to_msf;
|
|
||||||
burn_session_add_track;
|
|
||||||
burn_session_by_cue_file;
|
|
||||||
burn_session_create;
|
|
||||||
burn_session_dispose_cdtext;
|
|
||||||
burn_session_free;
|
|
||||||
burn_session_get_cdtext;
|
|
||||||
burn_session_get_cdtext_par;
|
|
||||||
burn_session_get_hidefirst;
|
|
||||||
burn_session_get_leadout_entry;
|
|
||||||
burn_session_get_sectors;
|
|
||||||
burn_session_get_start_tno;
|
|
||||||
burn_session_get_tracks;
|
|
||||||
burn_session_hide_first_track;
|
|
||||||
burn_session_input_sheet_v07t;
|
|
||||||
burn_session_remove_track;
|
|
||||||
burn_session_set_cdtext;
|
|
||||||
burn_session_set_cdtext_par;
|
|
||||||
burn_session_set_start_tno;
|
|
||||||
burn_set_messenger;
|
|
||||||
burn_set_scsi_logging;
|
|
||||||
burn_set_signal_handling;
|
|
||||||
burn_set_verbosity;
|
|
||||||
burn_sev_to_text;
|
|
||||||
burn_source_free;
|
|
||||||
burn_structure_print_disc;
|
|
||||||
burn_structure_print_session;
|
|
||||||
burn_structure_print_track;
|
|
||||||
burn_text_to_sev;
|
|
||||||
burn_track_clear_indice;
|
|
||||||
burn_track_clear_isrc;
|
|
||||||
burn_track_create;
|
|
||||||
burn_track_define_data;
|
|
||||||
burn_track_dispose_cdtext;
|
|
||||||
burn_track_free;
|
|
||||||
burn_track_get_cdtext;
|
|
||||||
burn_track_get_counters;
|
|
||||||
burn_track_get_entry;
|
|
||||||
burn_track_get_mode;
|
|
||||||
burn_track_get_sectors;
|
|
||||||
burn_track_set_byte_swap;
|
|
||||||
burn_track_set_cdxa_conv;
|
|
||||||
burn_track_set_cdtext;
|
|
||||||
burn_track_set_default_size;
|
|
||||||
burn_track_set_index;
|
|
||||||
burn_track_set_isrc;
|
|
||||||
burn_track_set_isrc_string;
|
|
||||||
burn_track_set_postgap_size;
|
|
||||||
burn_track_set_pregap_size;
|
|
||||||
burn_track_set_size;
|
|
||||||
burn_track_set_source;
|
|
||||||
burn_version;
|
|
||||||
burn_write_opts_auto_write_type;
|
|
||||||
burn_write_opts_free;
|
|
||||||
burn_write_opts_get_drive;
|
|
||||||
burn_write_opts_new;
|
|
||||||
burn_write_opts_set_bdr_obs_exempt;
|
|
||||||
burn_write_opts_set_dvd_obs;
|
|
||||||
burn_write_opts_set_fail21h_sev;
|
|
||||||
burn_write_opts_set_fillup;
|
|
||||||
burn_write_opts_set_force;
|
|
||||||
burn_write_opts_set_format;
|
|
||||||
burn_write_opts_set_has_mediacatalog;
|
|
||||||
burn_write_opts_set_leadin_text;
|
|
||||||
burn_write_opts_set_mediacatalog;
|
|
||||||
burn_write_opts_set_multi;
|
|
||||||
burn_write_opts_set_obs_pad;
|
|
||||||
burn_write_opts_set_perform_opc;
|
|
||||||
burn_write_opts_set_simulate;
|
|
||||||
burn_write_opts_set_start_byte;
|
|
||||||
burn_write_opts_set_stdio_fsync;
|
|
||||||
burn_write_opts_set_stream_recording;
|
|
||||||
burn_write_opts_set_toc_entries;
|
|
||||||
burn_write_opts_set_underrun_proof;
|
|
||||||
burn_write_opts_set_write_type;
|
|
||||||
libdax_audioxtr_destroy;
|
|
||||||
libdax_audioxtr_detach_fd;
|
|
||||||
libdax_audioxtr_get_id;
|
|
||||||
libdax_audioxtr_get_size;
|
|
||||||
libdax_audioxtr_new;
|
|
||||||
libdax_audioxtr_read;
|
|
||||||
local: *;
|
|
||||||
};
|
|
||||||
|
|
||||||
LIBBURN4_1.5.8 {
|
|
||||||
burn_disc_get_sectors_v2;
|
|
||||||
burn_disc_track_lba_nwa_v2;
|
|
||||||
burn_drive_get_status_v2;
|
|
||||||
burn_drive_release_v2;
|
|
||||||
burn_get_read_capacity_v2;
|
|
||||||
burn_session_get_sectors_v2;
|
|
||||||
burn_track_get_sectors_v2;
|
|
||||||
} LIBBURN4;
|
|
||||||
|
|
@ -1,408 +0,0 @@
|
|||||||
|
|
||||||
/* libdax_audioxtr
|
|
||||||
Audio track data extraction facility of libdax and libburn.
|
|
||||||
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
/* ts B41126 : O_BINARY is needed for Cygwin but undefined elsewhere */
|
|
||||||
#ifndef O_BINARY
|
|
||||||
#define O_BINARY 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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 or include libburn.h */
|
|
||||||
#define LIBDAX_AUDIOXTR_H_PUBLIC 1
|
|
||||||
#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 *) calloc(1, 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_data_location= 44;
|
|
||||||
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 | O_BINARY);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* @param flag: bit0= sequential file, skip by reading data
|
|
||||||
*/
|
|
||||||
static int libdax_audioxtr_skip(struct libdax_audioxtr *o,
|
|
||||||
off_t *old_pos,
|
|
||||||
off_t pos, int flag)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
size_t to_read;
|
|
||||||
static char buf[256]; /* Thread safe because the content does not matter */
|
|
||||||
|
|
||||||
if((flag & 1) || o->fd == 0) { /* stdin */
|
|
||||||
while(pos - *old_pos > 0) {
|
|
||||||
to_read= pos - *old_pos;
|
|
||||||
if(to_read > sizeof(buf))
|
|
||||||
to_read= sizeof(buf);
|
|
||||||
ret= read(o->fd, buf, to_read);
|
|
||||||
if(ret < (int) to_read)
|
|
||||||
return(0);
|
|
||||||
*old_pos+= to_read;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ret= lseek(o->fd, pos, SEEK_SET);
|
|
||||||
if(ret == -1)
|
|
||||||
return(0);
|
|
||||||
*old_pos= pos;
|
|
||||||
}
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int libdax_audioxtr_identify_wav(struct libdax_audioxtr *o, int flag)
|
|
||||||
{
|
|
||||||
int ret, fmt_seen= 0, data_seen= 0;
|
|
||||||
off_t pos= 0, old_pos= 0, riff_end= 0;
|
|
||||||
char buf[16];
|
|
||||||
unsigned char *ubuf;
|
|
||||||
|
|
||||||
/* check whether this is a MS WAVE file .wav */
|
|
||||||
/* info used: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/
|
|
||||||
https://en.wikipedia.org/wiki/WAV
|
|
||||||
see summary in: doc/waveformat.txt
|
|
||||||
*/
|
|
||||||
ubuf= (unsigned char *) buf;
|
|
||||||
|
|
||||||
/* Look for ChunkID "RIFF" , tolerate other known chunks */
|
|
||||||
while(1) {
|
|
||||||
ret= libdax_audioxtr_skip(o, &old_pos, pos, 0);
|
|
||||||
if(ret <= 0)
|
|
||||||
return(0);
|
|
||||||
ret= read(o->fd, buf, 8);
|
|
||||||
if(ret < 8)
|
|
||||||
return(0);
|
|
||||||
old_pos+= 8;
|
|
||||||
pos= old_pos + libdax_audioxtr_to_int(o, ubuf + 4, 4, 0);
|
|
||||||
if(pos > 0xffffffff || pos - old_pos < 4) /* Too large or no Format word */
|
|
||||||
return(0);
|
|
||||||
if(strncmp(buf, "RIFF", 4) == 0)
|
|
||||||
break;
|
|
||||||
/* Wikipedia mentions these known ChunkId values */
|
|
||||||
if(strncmp(buf, "INFO", 4) == 0 ||
|
|
||||||
strncmp(buf, "CSET", 4) == 0 ||
|
|
||||||
strncmp(buf, "JUNK", 4) == 0 ||
|
|
||||||
strncmp(buf, "PAD ", 4) == 0)
|
|
||||||
continue;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read RIFF Format header */
|
|
||||||
ret= read(o->fd, buf, 4);
|
|
||||||
if(ret < 4)
|
|
||||||
return(0);
|
|
||||||
old_pos+= 4;
|
|
||||||
if(strncmp(buf, "WAVE", 4) != 0) /* Format */
|
|
||||||
return(0);
|
|
||||||
riff_end= pos;
|
|
||||||
|
|
||||||
/* Look for SubchunkID "fmt " and "data" */
|
|
||||||
pos= old_pos;
|
|
||||||
while(old_pos < riff_end) {
|
|
||||||
ret= libdax_audioxtr_skip(o, &old_pos, pos, 0);
|
|
||||||
if(ret <= 0)
|
|
||||||
return(0);
|
|
||||||
ret= read(o->fd, buf, 8);
|
|
||||||
if(ret < 8)
|
|
||||||
return(0);
|
|
||||||
old_pos= pos + 8;
|
|
||||||
pos= old_pos + libdax_audioxtr_to_int(o, ubuf + 4, 4, 0); /* SubchunkSize */
|
|
||||||
|
|
||||||
if(strncmp(buf,"fmt ", 4) == 0) {
|
|
||||||
if(pos - old_pos < 16)
|
|
||||||
return(0);
|
|
||||||
ret= read(o->fd, buf, 16);
|
|
||||||
if(ret < 16)
|
|
||||||
return(0);
|
|
||||||
old_pos+= 16;
|
|
||||||
if(buf[0]!=1 || buf[1]!=0) /* AudioFormat (1 = Linear quantization) */
|
|
||||||
return(0);
|
|
||||||
o->msb_first= 0;
|
|
||||||
o->num_channels= libdax_audioxtr_to_int(o, ubuf + 2 , 2, 0);
|
|
||||||
o->sample_rate= libdax_audioxtr_to_int(o, ubuf + 4, 4, 0);
|
|
||||||
o->bits_per_sample= libdax_audioxtr_to_int(o, ubuf + 14, 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);
|
|
||||||
fmt_seen= 1;
|
|
||||||
|
|
||||||
} else if(strncmp(buf,"data", 4) == 0) {
|
|
||||||
o->wav_data_location= old_pos;
|
|
||||||
o->wav_subchunk2_size= pos - old_pos;
|
|
||||||
o->data_size= o->wav_subchunk2_size;
|
|
||||||
data_seen= 1;
|
|
||||||
}
|
|
||||||
if(fmt_seen && data_seen) {
|
|
||||||
strcpy(o->fmt,".wav");
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int libdax_audioxtr_identify_au(struct libdax_audioxtr *o, int flag)
|
|
||||||
{
|
|
||||||
int ret,encoding;
|
|
||||||
char buf[24];
|
|
||||||
|
|
||||||
/* Check whether 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);
|
|
||||||
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, o->wav_data_location, 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);
|
|
||||||
}
|
|
||||||
|
|
@ -1,240 +0,0 @@
|
|||||||
|
|
||||||
/* libdax_audioxtr
|
|
||||||
Audio track data extraction facility of libdax and libburn.
|
|
||||||
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LIBDAX_AUDIOXTR_H_INCLUDED
|
|
||||||
#define LIBDAX_AUDIOXTR_H_INCLUDED 1
|
|
||||||
|
|
||||||
|
|
||||||
/* Normally this public API is defined in <libburn/libburn.h>
|
|
||||||
Macro LIBDAX_AUDIOXTR_H_PUBLIC enables the definition for programs
|
|
||||||
which only include this file.
|
|
||||||
*/
|
|
||||||
#ifdef LIBDAX_AUDIOXTR_H_PUBLIC
|
|
||||||
|
|
||||||
/* 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 whether 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);
|
|
||||||
|
|
||||||
#endif /* LIBDAX_AUDIOXTR_H_PUBLIC */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef LIBDAX_AUDIOXTR________________
|
|
||||||
|
|
||||||
|
|
||||||
-- place documentation text here ---
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* LIBDAX_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 */
|
|
||||||
/* see description in: doc/waveformat.txt */
|
|
||||||
|
|
||||||
/* Offset to "data" subchunk */
|
|
||||||
unsigned int wav_data_location;
|
|
||||||
|
|
||||||
/* == 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 */
|
|
||||||
|
|
@ -1,449 +0,0 @@
|
|||||||
|
|
||||||
/* libdax_msgs
|
|
||||||
Message handling facility of libdax.
|
|
||||||
Copyright (C) 2006 - 2016 Thomas Schmitt <scdbackup@gmx.net>,
|
|
||||||
provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
/* Only this single source module is entitled to do this */
|
|
||||||
#define LIBDAX_MSGS_H_INTERNAL 1
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
(*item)= o=
|
|
||||||
(struct libdax_msgs_item *) calloc(1, sizeof(struct libdax_msgs_item));
|
|
||||||
if(o==NULL)
|
|
||||||
return(-1);
|
|
||||||
o->timestamp= 0.0;
|
|
||||||
ret= gettimeofday(&tv, NULL);
|
|
||||||
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 *) calloc(1, 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= "ALL ERRFILE DEBUG UPDATE NOTE HINT WARNING SORRY MISHAP FAILURE FATAL ABORT NEVER";
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
@param flag Bitfield for control purposes
|
|
||||||
bit0= If direct output to stderr:
|
|
||||||
CarriageReturn rather than LineFeed
|
|
||||||
*/
|
|
||||||
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%c", m->print_id, sev_text, textpt,
|
|
||||||
(flag & 1) ? '\r' : '\n');
|
|
||||||
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= calloc(1, 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);
|
|
||||||
}
|
|
||||||
|
|
@ -1,776 +0,0 @@
|
|||||||
|
|
||||||
/* libdax_msgs
|
|
||||||
Message handling facility of libburn and libisofs.
|
|
||||||
Copyright (C) 2006-2021 Thomas Schmitt <scdbackup@gmx.net>,
|
|
||||||
provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
*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 official 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
|
|
||||||
bit0= If direct output to stderr:
|
|
||||||
CarriageReturn rather than LineFeed
|
|
||||||
@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 blank 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 LIBDAX_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
|
|
||||||
0x00000004 (FATAL,HIGH) = Generic fatal error
|
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Range "elmom" : 0x00010000 to 0x0001ffff
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Range "scdbackup" : 0x00020000 to 0x0002ffff
|
|
||||||
|
|
||||||
Accessing 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
|
|
||||||
0x0002000a (FAILURE,HIGH) = Cannot accept '...' as SG_IO CDROM drive
|
|
||||||
0x0002000b (FAILURE,HIGH) = File object '...' not found
|
|
||||||
0x0002000c (FAILURE,HIGH) = Cannot start device file enumeration
|
|
||||||
0x0002000d (FAILURE,HIGH) = Cannot enumerate next device
|
|
||||||
0x0002000e (NOTE,HIGH) = Failed to open device during
|
|
||||||
|
|
||||||
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 (FAILURE,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) = Asynchronous SCSI error
|
|
||||||
0x0002014f (SORRY,HIGH) = Timeout with asynchronous SCSI command
|
|
||||||
0x00020150 (DEBUG,LOW) = Reporting asynchronous waiting time
|
|
||||||
0x00020151 (FAILURE,HIGH) = Read attempt on write-only drive
|
|
||||||
0x00020152 (FATAL,HIGH) = Cannot start fifo thread
|
|
||||||
0x00020153 (SORRY,HIGH) = Read error on fifo input
|
|
||||||
0x00020154 (NOTE,HIGH) = Forwarded input error ends output
|
|
||||||
0x00020155 (SORRY,HIGH) = Desired fifo buffer too large
|
|
||||||
0x00020156 (SORRY,HIGH) = Desired fifo buffer too small
|
|
||||||
0x00020157 (FATAL,HIGH) = burn_source is not a fifo object
|
|
||||||
0x00020158 (DEBUG,LOW) = Reporting thread disposal precautions
|
|
||||||
0x00020159 (DEBUG,HIGH) = TOC Format 0 returns inconsistent data
|
|
||||||
0x0002015a (NOTE,HIGH) = Could not examine busy device
|
|
||||||
0x0002015b (HINT,HIGH) = Busy '...' seems to be a hard disk, as '...1' exists
|
|
||||||
0x0002015c (FAILURE,HIGH) = Fifo size too small for desired peek buffer
|
|
||||||
0x0002015d (FAILURE,HIGH) = Fifo input ended short of desired peek buffer size
|
|
||||||
0x0002015e (FATAL,HIGH) = Fifo is already under consumption when peeking
|
|
||||||
0x0002015f (MISHAP,HIGH) = Damaged CD table-of-content detected and truncated
|
|
||||||
0x00020160 (WARNING,HIGH) = Session without leadout encountered
|
|
||||||
0x00020161 (WARNING,HIGH) = Empty session deleted
|
|
||||||
0x00020162 (SORRY,HIGH) = BD-R not unformatted blank any more. Cannot format
|
|
||||||
0x00020163 (NOTE,HIGH) = Blank BD-R left unformatted for zero spare capacity
|
|
||||||
0x00020164 (SORRY,HIGH) = Drive does not format BD-RE without spares
|
|
||||||
0x00020165 (WARNING,HIGH) = Drive does not support fast formatting
|
|
||||||
0x00020166 (WARNING,HIGH) = Drive does not support full formatting
|
|
||||||
0x00020167 (SORRY,HIGH) = Drive does not support non-default formatting
|
|
||||||
0x00020168 (FAILURE,HIGH) = Media not properly formatted. Cannot write.
|
|
||||||
0x00020169 (WARNING,HIGH) = Last session on media is still open
|
|
||||||
0x0002016a (FAILURE,HIGH) = No MMC transport adapter is present
|
|
||||||
0x0002016b (WARNING,HIGH) = No MMC transport adapter is present
|
|
||||||
0x0002016c (DEBUG,HIGH) = No MMC transport adapter is present
|
|
||||||
0x0002016e (DEBUG,HIGH) = MODE SENSE page 2A too short
|
|
||||||
0x0002016f (DEBUG,HIGH) = Unable to grab scanned drive
|
|
||||||
0x00020170 (NOTE,HIGH) = Closing open session before writing new one
|
|
||||||
0x00020171 (NOTE,HIGH) = Closing BD-R with accidentally open session
|
|
||||||
0x00020172 (SORRY,HIGH) = Read start address larger than number of readable blocks
|
|
||||||
0x00020173 (FAILURE,HIGH) = Drive tells NWA smaller than last written address
|
|
||||||
0x00020174 (SORRY,HIGH) = Fifo alignment does not allow desired read size
|
|
||||||
0x00020175 (FATAL,HIGH) = Supporting library is too old
|
|
||||||
0x00020176 (NOTE,HIGH) = Stream recording disabled because of small OS buffer
|
|
||||||
0x00020177 (ABORT,HIGH) = Urged drive worker threads to do emergency halt
|
|
||||||
0x00020178 (DEBUG,HIGH) = Write thread ended
|
|
||||||
0x00020179 (FAILURE,HIGH) = Offset source start address is before end of previous source
|
|
||||||
0x0002017a (FAILURE,HIGH) = Expected offset source object as parameter
|
|
||||||
0x0002017b (WARNING,HIGH) = Sequential BD-R media likely to soon fail writing
|
|
||||||
0x0002017c (FAILURE,HIGH) = No valid write type selected
|
|
||||||
0x0002017d (FATAL,HIGH) = Invalid file descriptor with stdio pseudo-drive
|
|
||||||
0x0002017e (FAILURE,HIGH) = Failed to close track, session, or disc
|
|
||||||
0x0002017f (FAILURE,HIGH) = Failed to synchronize drive cache
|
|
||||||
0x00020180 (FAILURE,HIGH) = Premature end of input encountered
|
|
||||||
0x00020181 (FAILURE,HIGH) = Pseudo-drive is a read-only file. Cannot write.
|
|
||||||
0x00020182 (FAILURE,HIGH) = Cannot truncate disk file for pseudo blanking
|
|
||||||
0x00020183 (WARNING,HIGH) = Failed to open device (a pseudo-drive) for reading
|
|
||||||
0x00020184 (WARNING,HIGH) = No Next-Writable-Address
|
|
||||||
0x00020185 (WARNING,HIGH) = Track damaged, not closed and not writable
|
|
||||||
0x00020186 (WARNING,HIGH) = Track damaged and not closed
|
|
||||||
0x00020187 (NOTE,HIGH) = Track not marked as damaged. No action taken.
|
|
||||||
0x00020188 (FAILURE,HIGH) = Cannot close damaged track on given media type
|
|
||||||
0x00020189 (FATAL,HIGH) = Drive is already grabbed by libburn
|
|
||||||
0x0002018a (SORRY,HIGH) = Timeout exceeded. Retry canceled.
|
|
||||||
0x0002018b (FAILURE,HIGH) = Too many CD-TEXT packs
|
|
||||||
0x0002018c (FAILURE,HIGH) = CD-TEXT pack type out of range
|
|
||||||
0x0002018d (FAILURE,HIGH) = CD-TEXT block number out of range
|
|
||||||
0x0002018e (FAILURE,HIGH) = Too many CD-TEXT packs in block
|
|
||||||
0x0002018f (FAILURE,HIGH) = CD-TEXT pack CRC mismatch
|
|
||||||
0x00020190 (WARNING,HIGH) = CD-TEXT pack CRC mismatch had to be corrected
|
|
||||||
0x00020191 (FAILURE,HIGH) = Unknown parameter in text input file
|
|
||||||
0x00020192 (FAILURE,HIGH) = Text input file sequence error
|
|
||||||
0x00020193 (FAILURE,HIGH) = Text input file readability problem
|
|
||||||
0x00020194 (FAILURE,HIGH) = Text input file syntax error or specs violation
|
|
||||||
0x00020195 (WARNING,HIGH) = Text input file warning
|
|
||||||
0x00020196 (FAILURE,HIGH) = Session has already defined tracks
|
|
||||||
0x00020197 (FAILURE,HIGH) = Unsupported text input file feature
|
|
||||||
0x00020198 (FAILURE,HIGH) = CD-TEXT pack file readability problem
|
|
||||||
0x00020199 (SORRY,HIGH) = Text input file reading aborted
|
|
||||||
0x0002019a (SORRY,HIGH) = Bad track index number
|
|
||||||
0x0002019b (SORRY,HIGH) = CD track number exceeds range of 1 to 99
|
|
||||||
0x0002019c (SORRY,HIGH) = Session has no defined tracks
|
|
||||||
0x0002019d (SORRY,HIGH) = Audio read size not properly aligned
|
|
||||||
0x0002019e (NOTE,HIGH) = Drive does not support media certification
|
|
||||||
0x0002019f (FAILURE,HIGH) = CD-TEXT binary pack array faulty
|
|
||||||
0x000201a0 (WARNING,HIGH) = Maximum number of CD-TEXT blocks exceeded
|
|
||||||
0x000201a1 (FAILURE,HIGH) = Cannot open disk file for writing
|
|
||||||
0x000201a2 (FAILURE,HIGH) = Error while writing to disk file
|
|
||||||
0x000201a3 (UPDATE,HIGH) = Progress message of burn_drive_extract_audio()
|
|
||||||
0x000201a4 (FAILURE,HIGH) = Failure to read audio sectors
|
|
||||||
0x000201a5 (FAILURE,HIGH) = Asynchronous SCSI error
|
|
||||||
0x000201a6 (FATAL,HIGH) = Lost connection to drive
|
|
||||||
0x000201a7 (FAILURE,HIGH) = SCSI command yielded host problem
|
|
||||||
0x000201a8 (FAILURE,HIGH) = SCSI command yielded driver problem
|
|
||||||
0x000201a9 (FAILURE,HIGH) = Implausible length from GET CONFIGURATION
|
|
||||||
0x000201aa (FAILURE,HIGH) = No CD-TEXT packs in file
|
|
||||||
0x000201ab (WARN,HIGH) = Leaving burn_source_fifo object undisposed
|
|
||||||
0x000201ac (NOTE,HIGH) = Drive currently does not offer Stream Recording
|
|
||||||
0x000201ad (NOTE,HIGH) = WRITE commands have been repeated
|
|
||||||
0x000201ae (FAILURE,HIGH) = Track size exceeds 4 TiB - 32 KiB
|
|
||||||
|
|
||||||
|
|
||||||
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 opened 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 opened
|
|
||||||
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 enough 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 /* LIBDAX_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 */
|
|
@ -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
|
|
||||||
|
|
6002
libburn/mmc.c
6002
libburn/mmc.c
File diff suppressed because it is too large
Load Diff
149
libburn/mmc.h
149
libburn/mmc.h
@ -1,149 +0,0 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
|
||||||
Copyright (c) 2006 - 2024 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#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 *, off_t 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 *);
|
|
||||||
int mmc_read_cd(struct burn_drive *d, int start, int len,
|
|
||||||
int sec_type, int main_ch,
|
|
||||||
const struct burn_read_opts *o, struct buffer *buf, int flag);
|
|
||||||
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);
|
|
||||||
|
|
||||||
/* ts B11228 : changed from void to int */
|
|
||||||
int 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,
|
|
||||||
struct burn_session *s, int tno,
|
|
||||||
const struct burn_write_opts *o,
|
|
||||||
unsigned char *pd);
|
|
||||||
|
|
||||||
/* ts A70201 */
|
|
||||||
int mmc_four_char_to_int(unsigned char *data);
|
|
||||||
/* ts C40226 */
|
|
||||||
unsigned int mmc_four_char_to_uint(unsigned char *data);
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
/* ts A70812 : return 0 = ok , return BE_CANCELLED = error occurred */
|
|
||||||
int mmc_read_10(struct burn_drive *d, int start, int amount,
|
|
||||||
struct buffer *buf);
|
|
||||||
|
|
||||||
/* ts A81210 : Determine the upper limit of readable data size */
|
|
||||||
int mmc_read_capacity(struct burn_drive *d);
|
|
||||||
|
|
||||||
/* ts A61201 */
|
|
||||||
char *mmc_obtain_profile_name(int profile_number);
|
|
||||||
|
|
||||||
|
|
||||||
/* mmc5r03c.pdf 4.3.4.4.1 d) "The maximum number of RZones is 2 302." */
|
|
||||||
#define BURN_MMC_FAKE_TOC_MAX_SIZE 2302
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A90903 */
|
|
||||||
/* MMC backend of API call burn_get_media_product_id()
|
|
||||||
*/
|
|
||||||
int mmc_get_media_product_id(struct burn_drive *d,
|
|
||||||
char **product_id, char **media_code1, char **media_code2,
|
|
||||||
char **book_type, int flag);
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A60910 (estimated) */
|
|
||||||
int mmc_function_spy(struct burn_drive *d, char * text);
|
|
||||||
|
|
||||||
/* ts A91118 */
|
|
||||||
int mmc_start_if_needed(struct burn_drive *d, int flag);
|
|
||||||
|
|
||||||
/* ts B00924 */
|
|
||||||
int mmc_get_bd_spare_info(struct burn_drive *d,
|
|
||||||
int *alloc_blocks, int *free_blocks, int flag);
|
|
||||||
|
|
||||||
/* ts B10801 */
|
|
||||||
int mmc_get_phys_format_info(struct burn_drive *d, int *disk_category,
|
|
||||||
char **book_name, int *part_version, int *num_layers,
|
|
||||||
int *num_blocks, int flag);
|
|
||||||
|
|
||||||
/* ts B11201 */
|
|
||||||
int mmc_get_leadin_text(struct burn_drive *d,
|
|
||||||
unsigned char **text_packs, int *num_packs, int flag);
|
|
||||||
|
|
||||||
/* ts B40107 */
|
|
||||||
int mmc_get_performance(struct burn_drive *d, int descr_type, int flag);
|
|
||||||
|
|
||||||
/* ts B90414 */
|
|
||||||
int burn_make_feature_text(struct burn_drive *d, unsigned int feature_code,
|
|
||||||
unsigned char flags,
|
|
||||||
unsigned char additional_length,
|
|
||||||
unsigned char *feature_data,
|
|
||||||
char **text, int flag);
|
|
||||||
|
|
||||||
#ifdef Libburn_develop_quality_scaN
|
|
||||||
/* B21108 ts */
|
|
||||||
int mmc_nec_optiarc_f3(struct burn_drive *d, int sub_op,
|
|
||||||
int start_lba, int rate_period,
|
|
||||||
int *eba, int *error_rate1, int *error_rate2);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /*__MMC*/
|
|
@ -1,40 +0,0 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "null.h"
|
|
||||||
#include "libburn.h"
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#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 = calloc(1, 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;
|
|
||||||
}
|
|
@ -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 */
|
|
@ -1,614 +0,0 @@
|
|||||||
|
|
||||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
|
||||||
Copyright (c) 2006 - 2017 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "libburn.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "drive.h"
|
|
||||||
#include "transport.h"
|
|
||||||
#include "init.h"
|
|
||||||
#include "write.h"
|
|
||||||
|
|
||||||
/* ts A61007 */
|
|
||||||
/* #include <a ssert.h> */
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.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 = calloc(1, 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->p2a_valid > 0 &&
|
|
||||||
drive->mdata->underrun_proof;
|
|
||||||
opts->perform_opc = 1;
|
|
||||||
opts->obs = -1;
|
|
||||||
|
|
||||||
#ifdef Libburn_dvd_always_obs_paD
|
|
||||||
opts->obs_pad = 1;
|
|
||||||
#else
|
|
||||||
opts->obs_pad = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
opts->bdr_obs_exempt = 0;
|
|
||||||
opts->start_byte = -1;
|
|
||||||
opts->fill_up_media = 0;
|
|
||||||
opts->force_is_set = 0;
|
|
||||||
opts->do_stream_recording = 0;
|
|
||||||
opts->dvd_obs_override = 0;
|
|
||||||
opts->stdio_fsync_size = Libburn_stdio_fsync_limiT;
|
|
||||||
opts->text_packs = NULL;
|
|
||||||
opts->num_text_packs = 0;
|
|
||||||
opts->no_text_pack_crc_check = 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)
|
|
||||||
return;
|
|
||||||
if (opts->text_packs != NULL)
|
|
||||||
free(opts->text_packs);
|
|
||||||
free(opts);
|
|
||||||
}
|
|
||||||
|
|
||||||
int burn_write_opts_clone(struct burn_write_opts *from,
|
|
||||||
struct burn_write_opts **to, int flag)
|
|
||||||
{
|
|
||||||
if (*to != NULL)
|
|
||||||
burn_write_opts_free(*to);
|
|
||||||
if (from == NULL)
|
|
||||||
return 1;
|
|
||||||
*to = calloc(1, sizeof(struct burn_write_opts));
|
|
||||||
if (*to == NULL) {
|
|
||||||
out_of_mem:;
|
|
||||||
libdax_msgs_submit(libdax_messenger, -1, 0x00000003,
|
|
||||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"Out of virtual memory", 0, 0);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memcpy(*to, from, sizeof(struct burn_write_opts));
|
|
||||||
(*to)->text_packs = NULL;
|
|
||||||
(*to)->num_text_packs = 0;
|
|
||||||
if (from->text_packs != NULL && from->num_text_packs > 0) {
|
|
||||||
(*to)->text_packs = calloc(1, from->num_text_packs * 18);
|
|
||||||
if ((*to)->text_packs == NULL)
|
|
||||||
goto out_of_mem;
|
|
||||||
memcpy((*to)->text_packs, from->text_packs,
|
|
||||||
from->num_text_packs * 18);
|
|
||||||
}
|
|
||||||
(*to)->refcount= 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct burn_read_opts *burn_read_opts_new(struct burn_drive *drive)
|
|
||||||
{
|
|
||||||
struct burn_read_opts *opts;
|
|
||||||
|
|
||||||
opts = calloc(1, 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;
|
|
||||||
opts->dap_bit = 0;
|
|
||||||
|
|
||||||
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 = calloc(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)
|
|
||||||
{
|
|
||||||
opts->simulate = !!sim;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int burn_write_opts_set_underrun_proof(struct burn_write_opts *opts,
|
|
||||||
int underrun_proof)
|
|
||||||
{
|
|
||||||
if (opts->drive->mdata->p2a_valid <= 0 ||
|
|
||||||
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 B31024 */
|
|
||||||
/* API */
|
|
||||||
void burn_write_opts_set_fail21h_sev(struct burn_write_opts *opts,
|
|
||||||
char *severity)
|
|
||||||
{
|
|
||||||
int ret, sevno;
|
|
||||||
|
|
||||||
ret = libdax_msgs__text_to_sev(severity, &sevno, 0);
|
|
||||||
if (ret <= 0)
|
|
||||||
opts->feat21h_fail_sev = 0;
|
|
||||||
else
|
|
||||||
opts->feat21h_fail_sev = sevno;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts B11204 */
|
|
||||||
/* @param flag bit0=do not verify checksums
|
|
||||||
bit1= repair mismatching checksums
|
|
||||||
bit2= repair checksums if they are 00 00 with each pack
|
|
||||||
*/
|
|
||||||
int burn_write_opts_set_leadin_text(struct burn_write_opts *opts,
|
|
||||||
unsigned char *text_packs,
|
|
||||||
int num_packs, int flag)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
unsigned char *pack_buffer = NULL;
|
|
||||||
|
|
||||||
if (num_packs > Libburn_leadin_cdtext_packs_maX ) {
|
|
||||||
libdax_msgs_submit(libdax_messenger, opts->drive->global_index,
|
|
||||||
0x0002018b,
|
|
||||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"Too many CD-TEXT packs", 0, 0);
|
|
||||||
ret= 0; goto ex;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num_packs > 0)
|
|
||||||
BURN_ALLOC_MEM(pack_buffer, unsigned char, num_packs * 18);
|
|
||||||
|
|
||||||
if (opts->text_packs != NULL) {
|
|
||||||
free(opts->text_packs);
|
|
||||||
opts->text_packs = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flag & 1) {
|
|
||||||
opts->no_text_pack_crc_check = 1;
|
|
||||||
} else {
|
|
||||||
opts->no_text_pack_crc_check = 0;
|
|
||||||
ret = burn_cdtext_crc_mismatches(text_packs, num_packs,
|
|
||||||
(flag >> 1) & 3);
|
|
||||||
if (ret > 0) {
|
|
||||||
libdax_msgs_submit(libdax_messenger, -1, 0x0002018f,
|
|
||||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"CD-TEXT pack CRC mismatch", 0, 0);
|
|
||||||
ret = 0; goto ex;
|
|
||||||
} else if (ret < 0) {
|
|
||||||
libdax_msgs_submit(libdax_messenger, -1, 0x00020190,
|
|
||||||
LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"CD-TEXT pack CRC mismatch had to be corrected",
|
|
||||||
0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num_packs > 0) {
|
|
||||||
memcpy(pack_buffer, text_packs, num_packs * 18);
|
|
||||||
opts->text_packs = pack_buffer;
|
|
||||||
pack_buffer = NULL;
|
|
||||||
}
|
|
||||||
opts->num_text_packs = num_packs;
|
|
||||||
ret = 1;
|
|
||||||
ex:;
|
|
||||||
BURN_FREE_MEM(pack_buffer);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* 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 (burn_drive_get_bd_r_pow(d)) {
|
|
||||||
strcat(reasons,
|
|
||||||
"MEDIA: unsuitable BD-R Pseudo Overwrite formatting, ");
|
|
||||||
return BURN_WRITE_NONE;
|
|
||||||
}
|
|
||||||
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 (opts->num_text_packs > 0) {
|
|
||||||
strcat(reasons, "CD-TEXT: write type SAO required, ");
|
|
||||||
{wt = BURN_WRITE_NONE; goto ex;}
|
|
||||||
}
|
|
||||||
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 A91115: API */
|
|
||||||
void burn_write_opts_set_dvd_obs(struct burn_write_opts *opts, int obs)
|
|
||||||
{
|
|
||||||
if (obs != 0 && obs != 32 * 1024 && obs != 64 * 1024)
|
|
||||||
return;
|
|
||||||
opts->dvd_obs_override = obs;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts B20406: API */
|
|
||||||
void burn_write_opts_set_obs_pad(struct burn_write_opts *opts, int pad)
|
|
||||||
{
|
|
||||||
opts->obs_pad = 2 * !!pad;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts C10909: API */
|
|
||||||
void burn_write_opts_set_bdr_obs_exempt(struct burn_write_opts *opts,
|
|
||||||
int value)
|
|
||||||
{
|
|
||||||
opts->bdr_obs_exempt = !!value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A91115: API */
|
|
||||||
void burn_write_opts_set_stdio_fsync(struct burn_write_opts *opts, int rhythm)
|
|
||||||
{
|
|
||||||
if (rhythm == -1)
|
|
||||||
opts->stdio_fsync_size = -1; /* never */
|
|
||||||
else if (rhythm == 0)
|
|
||||||
opts->stdio_fsync_size = Libburn_stdio_fsync_limiT;
|
|
||||||
else if (rhythm == 1)
|
|
||||||
opts->stdio_fsync_size = 0; /* only at end of writing */
|
|
||||||
else if (rhythm >= 32)
|
|
||||||
opts->stdio_fsync_size = rhythm;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,160 +0,0 @@
|
|||||||
|
|
||||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
|
||||||
Copyright (c) 2006 - 2013 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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; /* >0 pad up last block to obs, 0 do not
|
|
||||||
2 indicates burn_write_opts_set_obs_pad(,1)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* 1= do not apply obs_pad=1 to BD-R if not stream recording. */
|
|
||||||
int bdr_obs_exempt;
|
|
||||||
|
|
||||||
/* ts A61222 : Start address for media which offer a choice */
|
|
||||||
off_t start_byte;
|
|
||||||
|
|
||||||
/* ts A70213 : Whether to fill up the available space on media */
|
|
||||||
int fill_up_media;
|
|
||||||
|
|
||||||
/* ts A70303 : Whether to override conformance checks:
|
|
||||||
- the check whether 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;
|
|
||||||
|
|
||||||
/* ts A91115 : override value for .obs on DVD media.
|
|
||||||
Only values 0, 32K and 64K are allowed for now. */
|
|
||||||
int dvd_obs_override;
|
|
||||||
|
|
||||||
/* ts A91115 : size of the fsync() interval for stdio writing.
|
|
||||||
Values 0 or >= 32 counted in 2 KB blocks. */
|
|
||||||
int stdio_fsync_size;
|
|
||||||
|
|
||||||
/* ts B11203 : CD-TEXT */
|
|
||||||
unsigned char *text_packs;
|
|
||||||
int num_text_packs;
|
|
||||||
int no_text_pack_crc_check;
|
|
||||||
|
|
||||||
/** 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;
|
|
||||||
|
|
||||||
/* Whether to keep medium appendable */
|
|
||||||
unsigned char multi;
|
|
||||||
|
|
||||||
/* ts B31024 */
|
|
||||||
/* The severity to be attributed to error messages about failed
|
|
||||||
write attempt with blank DVD-RW, possibly due to falsely reported
|
|
||||||
feature 21h Incremental Streaming Writable
|
|
||||||
*/
|
|
||||||
int feat21h_fail_sev;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Default value for burn_write_opts.stdio_flush_size
|
|
||||||
*/
|
|
||||||
#define Libburn_stdio_fsync_limiT 8192
|
|
||||||
|
|
||||||
/* Maximum number of Lead-in text packs.
|
|
||||||
READ TOC/PMA/ATIP can at most return 3640.7 packs.
|
|
||||||
The sequence counters of the packs have 8 bits. There are 8 blocks at most.
|
|
||||||
Thus max 2048 packs.
|
|
||||||
*/
|
|
||||||
#define Libburn_leadin_cdtext_packs_maX 2048
|
|
||||||
|
|
||||||
|
|
||||||
/** 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;
|
|
||||||
|
|
||||||
/* ts B21119 */
|
|
||||||
/* >>> Needs API access */
|
|
||||||
/** Whether to set DAP bit which allows the drive to apply
|
|
||||||
"flaw obscuring mechanisms like audio data mute and interpolate"
|
|
||||||
*/
|
|
||||||
unsigned int dap_bit;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int burn_write_opts_clone(struct burn_write_opts *from,
|
|
||||||
struct burn_write_opts **to, int flag);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* BURN__OPTIONS_H */
|
|
@ -1,88 +0,0 @@
|
|||||||
|
|
||||||
/* os-dummy.h
|
|
||||||
Operating system specific libburn definitions and declarations. Included
|
|
||||||
by os.h in case of compilation for
|
|
||||||
Unknown POSIX like systems
|
|
||||||
with the dummy MMC transport adapter sg-dummy.c
|
|
||||||
|
|
||||||
Copyright (C) 2009 - 2013 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPLv2+
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/** List of all signals which shall be caught by signal handlers and trigger
|
|
||||||
a graceful abort of libburn. (See man 7 signal.)
|
|
||||||
*/
|
|
||||||
/* Once as system defined macros */
|
|
||||||
#define BURN_OS_SIGNAL_MACRO_LIST \
|
|
||||||
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, \
|
|
||||||
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, \
|
|
||||||
SIGUSR1, SIGUSR2, SIGXCPU
|
|
||||||
|
|
||||||
/* 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"
|
|
||||||
|
|
||||||
/* The number of above list items */
|
|
||||||
#define BURN_OS_SIGNAL_COUNT 13
|
|
||||||
|
|
||||||
/** The list of all signals which shall surely not be caught.
|
|
||||||
It depends on the particular signal whether it can be ignored or whether
|
|
||||||
it will lead to sudden death of the process.
|
|
||||||
Some signals are not POSIX,
|
|
||||||
but nevertheless ought to be ignored if they are defined.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef SIGWINCH
|
|
||||||
#define BURN_OS_SIG_WINCH ,SIGWINCH
|
|
||||||
#define BURN_OS_SIG_WINCH_CNT 1
|
|
||||||
#else
|
|
||||||
#define BURN_OS_SIG_WINCH
|
|
||||||
#define BURN_OS_SIG_WINCH_CNT 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SIGURG
|
|
||||||
#define BURN_OS_SIG_URG ,SIGURG
|
|
||||||
#define BURN_OS_SIG_URG_CNT 1
|
|
||||||
#else
|
|
||||||
#define BURN_OS_SIG_URG
|
|
||||||
#define BURN_OS_SIG_URG_CNT 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** The combined list of all signals which shall not be caught.
|
|
||||||
*/
|
|
||||||
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
|
|
||||||
SIGKILL, SIGCHLD, SIGSTOP, SIGTSTP, SIGCONT, SIGTTIN, SIGTTOU \
|
|
||||||
BURN_OS_SIG_WINCH BURN_OS_SIG_URG
|
|
||||||
|
|
||||||
/* The number of above list items */
|
|
||||||
#define BURN_OS_NON_SIGNAL_COUNT \
|
|
||||||
( 7 + BURN_OS_SIG_WINCH_CNT + BURN_OS_SIG_URG_CNT )
|
|
||||||
|
|
||||||
|
|
||||||
/* The maximum size for a (SCSI) i/o transaction */
|
|
||||||
/* Important : MUST be at least 32768 ! */
|
|
||||||
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
|
|
||||||
|
|
||||||
|
|
||||||
/* To hold the position of the most recently delivered address from
|
|
||||||
device enumeration.
|
|
||||||
*/
|
|
||||||
struct burn_drive_enumerator_struct {
|
|
||||||
int pos;
|
|
||||||
int info_count;
|
|
||||||
char **info_list;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
|
|
||||||
typedef struct burn_drive_enumerator_struct burn_drive_enumerator_t;
|
|
||||||
|
|
||||||
|
|
||||||
/* 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 just_a_dummy;
|
|
||||||
|
|
@ -1,65 +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 - 2013 Thomas Schmitt <scdbackup@gmx.net>,
|
|
||||||
Provided under GPLv2+
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** List of all signals which shall be caught by signal handlers and trigger
|
|
||||||
a graceful abort of libburn. (See man 7 signal.)
|
|
||||||
*/
|
|
||||||
/* Once as system defined macros */
|
|
||||||
#define BURN_OS_SIGNAL_MACRO_LIST \
|
|
||||||
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, \
|
|
||||||
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, \
|
|
||||||
SIGUSR1, SIGUSR2, SIGXCPU, 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", "SIGBUS", "SIGPROF", \
|
|
||||||
"SIGSYS", "SIGTRAP", "SIGVTALRM", "SIGXCPU", "SIGXFSZ"
|
|
||||||
|
|
||||||
/* The number of above list items */
|
|
||||||
#define BURN_OS_SIGNAL_COUNT 20
|
|
||||||
|
|
||||||
/** To list all signals which shall surely not be caught */
|
|
||||||
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
|
|
||||||
SIGKILL, SIGCHLD, SIGSTOP, SIGTSTP, SIGCONT, SIGTTIN, SIGTTOU, SIGURG, SIGWINCH
|
|
||||||
|
|
||||||
/* The number of above list items */
|
|
||||||
#define BURN_OS_NON_SIGNAL_COUNT 9
|
|
||||||
|
|
||||||
|
|
||||||
/* The maximum size for a (SCSI) i/o transaction */
|
|
||||||
/* Important : MUST be at least 32768 ! */
|
|
||||||
/* Older BSD info says that 32 kB is maximum. But 64 kB seems to work well
|
|
||||||
on 8-STABLE. It is by default only used with BD in streaming mode.
|
|
||||||
So older systems should still be quite safe with this buffer max size.
|
|
||||||
*/
|
|
||||||
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
|
|
||||||
|
|
||||||
|
|
||||||
/** 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; \
|
|
||||||
int lock_fd; \
|
|
||||||
int is_ahci; \
|
|
||||||
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
|||||||
|
|
||||||
/* os-libcdio.h
|
|
||||||
Operating system specific libburn definitions and declarations. Included
|
|
||||||
by os.h in case of compilation for
|
|
||||||
Unknown X/Open-like systems
|
|
||||||
with GNU libcdio MMC transport adapter sg-libcdio.c
|
|
||||||
|
|
||||||
Copyright (C) 2009 - 2013 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPLv2+
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/** List of all signals which shall be caught by signal handlers and trigger
|
|
||||||
a graceful abort of libburn. (See man 7 signal.)
|
|
||||||
*/
|
|
||||||
/* Once as system defined macros */
|
|
||||||
#define BURN_OS_SIGNAL_MACRO_LIST \
|
|
||||||
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, \
|
|
||||||
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, \
|
|
||||||
SIGUSR1, SIGUSR2, SIGXCPU
|
|
||||||
|
|
||||||
/* 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"
|
|
||||||
|
|
||||||
/* The number of above list items */
|
|
||||||
#define BURN_OS_SIGNAL_COUNT 13
|
|
||||||
|
|
||||||
|
|
||||||
/** The list of all signals which shall surely not be caught.
|
|
||||||
It depends on the particular signal whether it can be ignored or whether
|
|
||||||
it will lead to sudden death of the process.
|
|
||||||
Some signals are not POSIX,
|
|
||||||
but nevertheless ought to be ignored if they are defined.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef SIGWINCH
|
|
||||||
#define BURN_OS_SIG_WINCH ,SIGWINCH
|
|
||||||
#define BURN_OS_SIG_WINCH_CNT 1
|
|
||||||
#else
|
|
||||||
#define BURN_OS_SIG_WINCH
|
|
||||||
#define BURN_OS_SIG_WINCH_CNT 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SIGURG
|
|
||||||
#define BURN_OS_SIG_URG ,SIGURG
|
|
||||||
#define BURN_OS_SIG_URG_CNT 1
|
|
||||||
#else
|
|
||||||
#define BURN_OS_SIG_URG
|
|
||||||
#define BURN_OS_SIG_URG_CNT 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** The combined list of all signals which shall not be caught.
|
|
||||||
*/
|
|
||||||
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
|
|
||||||
SIGKILL, SIGCHLD, SIGSTOP, SIGTSTP, SIGCONT, SIGTTIN, SIGTTOU \
|
|
||||||
BURN_OS_SIG_WINCH BURN_OS_SIG_URG
|
|
||||||
|
|
||||||
/* The number of above list items */
|
|
||||||
#define BURN_OS_NON_SIGNAL_COUNT \
|
|
||||||
( 7 + BURN_OS_SIG_WINCH_CNT + BURN_OS_SIG_URG_CNT )
|
|
||||||
|
|
||||||
|
|
||||||
/* The maximum size for a (SCSI) i/o transaction */
|
|
||||||
/* My Blu-ray burner LG GGW-H20 writes junk if stream recording is combined
|
|
||||||
with buffer size 32 kB. So stream recording is allowed only with size 64k.
|
|
||||||
Older BSD info says that 32 kB is maximum. But 64 kB seems to work well
|
|
||||||
on 8-STABLE. It is by default only used with BD in streaming mode.
|
|
||||||
So older systems should still be quite safe with this buffer max size.
|
|
||||||
*/
|
|
||||||
/* Important : MUST be at least 32768 ! */
|
|
||||||
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
|
|
||||||
|
|
||||||
|
|
||||||
/* To hold the position of the most recently delivered address from
|
|
||||||
device enumeration.
|
|
||||||
*/
|
|
||||||
struct burn_drive_enumerator_struct {
|
|
||||||
char **ppsz_cd_drives;
|
|
||||||
char **pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
|
|
||||||
typedef struct burn_drive_enumerator_struct burn_drive_enumerator_t;
|
|
||||||
|
|
||||||
|
|
||||||
/* The list of operating system dependent elements in struct burn_drive.
|
|
||||||
Usually they are initialized in sg-*.c:enumerate_common().
|
|
||||||
*/
|
|
||||||
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
|
|
||||||
void *p_cdio; /* actually a pointer to CdIo_t */ \
|
|
||||||
char libcdio_name[4096]; /* The drive path as used by libcdio */ \
|
|
||||||
|
|
@ -1,81 +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, GNU/Linux SCSI Generic (sg)
|
|
||||||
|
|
||||||
Copyright (C) 2006 - 2013 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/** 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, 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", "SIGBUS", "SIGPOLL", \
|
|
||||||
"SIGPROF", "SIGSYS", "SIGTRAP", "SIGVTALRM", "SIGXCPU", \
|
|
||||||
"SIGXFSZ"
|
|
||||||
|
|
||||||
/* The number of above list items */
|
|
||||||
#define BURN_OS_SIGNAL_COUNT 21
|
|
||||||
|
|
||||||
/** To list all signals which shall surely not be caught */
|
|
||||||
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
|
|
||||||
SIGKILL, SIGCHLD, SIGSTOP, SIGTSTP, SIGCONT, SIGURG, SIGWINCH, SIGTTIN, SIGTTOU
|
|
||||||
|
|
||||||
/* The number of above list items */
|
|
||||||
#define BURN_OS_NON_SIGNAL_COUNT 9
|
|
||||||
|
|
||||||
|
|
||||||
/* 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 position of the most recently delivered address from
|
|
||||||
device enumeration.
|
|
||||||
*/
|
|
||||||
struct burn_drive_enumerator_struct {
|
|
||||||
int pos;
|
|
||||||
int info_count;
|
|
||||||
char **info_list;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
|
|
||||||
typedef struct burn_drive_enumerator_struct burn_drive_enumerator_t;
|
|
||||||
|
|
||||||
|
|
||||||
/* 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];
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
|||||||
|
|
||||||
/* os-netbsd.h
|
|
||||||
Operating system specific libburn definitions and declarations. Included
|
|
||||||
by os.h in case of compilation for
|
|
||||||
NetBSD 6 or OpenBSD 5.9
|
|
||||||
with MMC transport adapter sg-netbsd.c
|
|
||||||
|
|
||||||
Copyright (C) 2010 - 2016 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
provided under GPLv2+
|
|
||||||
|
|
||||||
Derived 2014 from libburn/os-solaris.c
|
|
||||||
Adapted 2016 to OpenBSD by help of SASANO Takayoshi <uaa@mx5.nisiq.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/** List of all signals which shall be caught by signal handlers and trigger
|
|
||||||
a graceful abort of libburn. (See man signal.h)
|
|
||||||
*/
|
|
||||||
/* Once as system defined macros */
|
|
||||||
#define BURN_OS_SIGNAL_MACRO_LIST \
|
|
||||||
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, \
|
|
||||||
SIGABRT, SIGEMT, SIGFPE, SIGBUS, SIGSEGV, \
|
|
||||||
SIGSYS, SIGPIPE, SIGALRM, SIGTERM, SIGXCPU, \
|
|
||||||
SIGXFSZ, SIGVTALRM, SIGPROF, SIGUSR1, SIGUSR2
|
|
||||||
|
|
||||||
/* Once as text 1:1 list of strings for messages and interpreters */
|
|
||||||
#define BURN_OS_SIGNAL_NAME_LIST \
|
|
||||||
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGTRAP", \
|
|
||||||
"SIGABRT", "SIGEMT", "SIGFPE", "SIGBUS", "SIGSEGV", \
|
|
||||||
"SIGSYS", "SIGPIPE", "SIGALRM", "SIGTERM", "SIGXCPU", \
|
|
||||||
"SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGUSR1", "SIGUSR2"
|
|
||||||
|
|
||||||
/* The number of above list items */
|
|
||||||
#define BURN_OS_SIGNAL_COUNT 20
|
|
||||||
|
|
||||||
#ifdef __OpenBSD__
|
|
||||||
|
|
||||||
/** To list all signals which shall surely not be caught */
|
|
||||||
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
|
|
||||||
SIGKILL, SIGURG, SIGSTOP, SIGTSTP, SIGCONT, \
|
|
||||||
SIGCHLD, SIGTTIN, SIGTTOU, SIGIO, SIGWINCH, \
|
|
||||||
SIGINFO
|
|
||||||
|
|
||||||
/* The number of above list items */
|
|
||||||
#define BURN_OS_NON_SIGNAL_COUNT 11
|
|
||||||
|
|
||||||
/* ts B60730 */
|
|
||||||
/* Either OpenBSD or SASANO Takayoshi's LG BH14NS48 throw 2,0,0
|
|
||||||
on Immed bit with BLANK and SYNCHRONIZE CACHE.
|
|
||||||
Until it is clear that the drive is to blame, the OpenBSD default is
|
|
||||||
not to use Immed.
|
|
||||||
|
|
||||||
This may be overridden at ./configure time by
|
|
||||||
export CFLAGS
|
|
||||||
CFLAGS="$CFLAGS -DLibburn_do_no_immed_defaulT=0"
|
|
||||||
*/
|
|
||||||
#ifndef Libburn_do_no_immed_defaulT
|
|
||||||
#define Libburn_do_no_immed_defaulT 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else /* __OpenBSD__ */
|
|
||||||
|
|
||||||
/** To list all signals which shall surely not be caught */
|
|
||||||
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
|
|
||||||
SIGKILL, SIGURG, SIGSTOP, SIGTSTP, SIGCONT, \
|
|
||||||
SIGCHLD, SIGTTIN, SIGTTOU, SIGIO, SIGWINCH, \
|
|
||||||
SIGINFO, SIGPWR
|
|
||||||
|
|
||||||
/* The number of above list items */
|
|
||||||
#define BURN_OS_NON_SIGNAL_COUNT 12
|
|
||||||
|
|
||||||
#endif /* ! __OpenBSD__ */
|
|
||||||
|
|
||||||
/* The maximum size for a (SCSI) i/o transaction */
|
|
||||||
/* Important : MUST be at least 32768 ! */
|
|
||||||
/* My Blu-ray burner LG GGW-H20 writes junk if stream recording is combined
|
|
||||||
with buffer size 32 kB. So stream recording is allowed only with size 64k.
|
|
||||||
*/
|
|
||||||
/* >>> ??? Does it do 64 kB ? */
|
|
||||||
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
|
|
||||||
|
|
||||||
|
|
||||||
/* To hold the position of the most recently delivered address from
|
|
||||||
device enumeration.
|
|
||||||
*/
|
|
||||||
struct burn_drive_enumerator_struct {
|
|
||||||
int cdno;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
|
|
||||||
typedef struct burn_drive_enumerator_struct burn_drive_enumerator_t;
|
|
||||||
|
|
||||||
|
|
||||||
/* The list of operating system dependent elements in struct burn_drive.
|
|
||||||
Usually they are initialized in sg-*.c:enumerate_common().
|
|
||||||
*/
|
|
||||||
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
|
|
||||||
int fd;
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
|||||||
|
|
||||||
/* os-solaris.h
|
|
||||||
Operating system specific libburn definitions and declarations. Included
|
|
||||||
by os.h in case of compilation for
|
|
||||||
Solaris based systems, e.g. SunOS 5.11
|
|
||||||
with Solaris uscsi MMC transport adapter sg-solaris.c
|
|
||||||
|
|
||||||
Copyright (C) 2010 - 2013 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
provided under GPLv2+
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/** List of all signals which shall be caught by signal handlers and trigger
|
|
||||||
a graceful abort of libburn. (See man signal.h)
|
|
||||||
*/
|
|
||||||
/* Once as system defined macros */
|
|
||||||
#define BURN_OS_SIGNAL_MACRO_LIST \
|
|
||||||
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, \
|
|
||||||
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, \
|
|
||||||
SIGUSR1, SIGUSR2, SIGXCPU
|
|
||||||
|
|
||||||
/* 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"
|
|
||||||
|
|
||||||
/* The number of above list items */
|
|
||||||
#define BURN_OS_SIGNAL_COUNT 13
|
|
||||||
|
|
||||||
/** To list all signals which shall surely not be caught */
|
|
||||||
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
|
|
||||||
SIGKILL, SIGCHLD, SIGSTOP, SIGTSTP, SIGCONT, SIGTTIN, SIGTTOU, SIGURG, SIGWINCH
|
|
||||||
|
|
||||||
/* The number of above list items */
|
|
||||||
#define BURN_OS_NON_SIGNAL_COUNT 9
|
|
||||||
|
|
||||||
|
|
||||||
/* The maximum size for a (SCSI) i/o transaction */
|
|
||||||
/* Important : MUST be at least 32768 ! */
|
|
||||||
/* My Blu-ray burner LG GGW-H20 writes junk if stream recording is combined
|
|
||||||
with buffer size 32 kB. So stream recording is allowed only with size 64k.
|
|
||||||
*/
|
|
||||||
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
|
|
||||||
|
|
||||||
|
|
||||||
/* >>> */
|
|
||||||
|
|
||||||
/* To hold the position of the most recently delivered address from
|
|
||||||
device enumeration.
|
|
||||||
*/
|
|
||||||
struct burn_drive_enumerator_struct {
|
|
||||||
void *dir;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
|
|
||||||
typedef struct burn_drive_enumerator_struct burn_drive_enumerator_t;
|
|
||||||
|
|
||||||
|
|
||||||
/* The list of operating system dependent elements in struct burn_drive.
|
|
||||||
Usually they are initialized in sg-*.c:enumerate_common().
|
|
||||||
*/
|
|
||||||
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
|
|
||||||
int fd;
|
|
||||||
|
|
98
libburn/os.h
98
libburn/os.h
@ -1,98 +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) 2009 - 2016 Thomas Schmitt <scdbackup@gmx.net>,
|
|
||||||
provided under GPLv2+
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BURN_OS_H_INCLUDED
|
|
||||||
#define BURN_OS_H_INCLUDED 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
Operating system case distinction
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef Libburn_use_sg_dummY
|
|
||||||
|
|
||||||
|
|
||||||
/* --------- Any other system. With dummy MMC transport sg-dummy.c --------- */
|
|
||||||
#include "os-dummy.h"
|
|
||||||
|
|
||||||
|
|
||||||
#else
|
|
||||||
#ifdef Libburn_use_libcdiO
|
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------- X/Open with GNU libcdio ---------------------- */
|
|
||||||
#include "os-libcdio.h"
|
|
||||||
|
|
||||||
|
|
||||||
#else
|
|
||||||
#ifdef __NetBSD__
|
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------- NetBSD with SCIOCCOMMAND --------------------- */
|
|
||||||
#include "os-netbsd.h"
|
|
||||||
|
|
||||||
|
|
||||||
#else
|
|
||||||
#ifdef __OpenBSD__
|
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------- OpenBSD with SCIOCCOMMAND -------------------- */
|
|
||||||
#include "os-netbsd.h"
|
|
||||||
|
|
||||||
|
|
||||||
#else
|
|
||||||
#ifdef __FreeBSD__
|
|
||||||
|
|
||||||
|
|
||||||
/* ----------------------------- FreeBSD with CAM -------------------------- */
|
|
||||||
#include "os-freebsd.h"
|
|
||||||
|
|
||||||
|
|
||||||
#else
|
|
||||||
#ifdef __FreeBSD_kernel__
|
|
||||||
|
|
||||||
|
|
||||||
/* ----------------------- FreeBSD with CAM under Debian ------------------- */
|
|
||||||
#include "os-freebsd.h"
|
|
||||||
|
|
||||||
|
|
||||||
#else
|
|
||||||
#ifdef __linux
|
|
||||||
|
|
||||||
|
|
||||||
/* ------- Linux kernels 2.4 and 2.6 with GNU/Linux SCSI Generic (sg) ------ */
|
|
||||||
#include "os-linux.h"
|
|
||||||
|
|
||||||
|
|
||||||
#else
|
|
||||||
#ifdef __sun
|
|
||||||
|
|
||||||
|
|
||||||
/* ------- Solaris (e.g. SunOS 5.11) with uscsi ------ */
|
|
||||||
#include "os-solaris.h"
|
|
||||||
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
|
|
||||||
/* --------- Any other system. With dummy MMC transport sg-dummy.c --------- */
|
|
||||||
#include "os-dummy.h"
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* ! __sun*/
|
|
||||||
#endif /* ! __linux */
|
|
||||||
#endif /* ! __FreeBSD__kernel__ */
|
|
||||||
#endif /* ! __FreeBSD__ */
|
|
||||||
#endif /* ! __OpenBSD__ */
|
|
||||||
#endif /* ! __NetBSD__ */
|
|
||||||
#endif /* ! Libburn_use_libcdiO */
|
|
||||||
#endif /* ! Libburn_use_sg_dummY */
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* ! BURN_OS_H_INCLUDED */
|
|
||||||
|
|
778
libburn/read.c
778
libburn/read.c
@ -1,778 +0,0 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
|
||||||
Copyright (c) 2006 - 2024 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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>
|
|
||||||
|
|
||||||
/* ts B41126 : O_BINARY is needed for Cygwin but undefined elsewhere */
|
|
||||||
#ifndef O_BINARY
|
|
||||||
#define O_BINARY 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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 "toc.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "mmc.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; <- needs to become dynamic memory
|
|
||||||
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;
|
|
||||||
|
|
||||||
#ifdef Libburn_no_crc_C
|
|
||||||
crc = 0; /* dummy */
|
|
||||||
#else
|
|
||||||
crc = crc_ccitt(fakesub + 12, 10);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fakesub[22] = crc >> 8;
|
|
||||||
fakesub[23] = crc & 0xFF;
|
|
||||||
write(o->subfd, fakesub, 96);
|
|
||||||
}
|
|
||||||
while (1) {
|
|
||||||
seclen = burn_sector_length_read(d, o);
|
|
||||||
|
|
||||||
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))) {
|
|
||||||
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++;
|
|
||||||
/* session switch to d->currsession */
|
|
||||||
/* skipping a lead out */
|
|
||||||
drive_lba = CURRENT_SESSION_START(d);
|
|
||||||
/* XXX more of the same
|
|
||||||
end = burn_track_end(d, d->currsession,
|
|
||||||
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 */
|
|
||||||
/* >>> ts B21123 : Would now be d->read_cd() with
|
|
||||||
with sectype = 0 , mainch = 0xf8 */
|
|
||||||
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];
|
|
||||||
int ptr = 2352, i, j, code, fb;
|
|
||||||
int audio = 1;
|
|
||||||
#ifndef Libburn_no_crc_C
|
|
||||||
unsigned short crc;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (o->c2errors) {
|
|
||||||
fb = bitcount(data + ptr, 294);
|
|
||||||
if (fb) {
|
|
||||||
/* bitcount(data + ptr, 294) damaged bits */;
|
|
||||||
}
|
|
||||||
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]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef Libburn_no_crc_C
|
|
||||||
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");
|
|
||||||
*/;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 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 instead of crap
|
|
||||||
static void write_empty_sector(int fd)
|
|
||||||
{
|
|
||||||
static char sec[2352], initialized = 0;
|
|
||||||
|
|
||||||
if (!initialized) {
|
|
||||||
memset(sec, 0, 2352);
|
|
||||||
initialized = 1;
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/** @param flag bit1= be silent on failure
|
|
||||||
bit5= report failure with severity DEBUG
|
|
||||||
*/
|
|
||||||
static int burn_stdio_seek(int fd, off_t byte_address, struct burn_drive *d,
|
|
||||||
int flag)
|
|
||||||
{
|
|
||||||
char msg[80];
|
|
||||||
|
|
||||||
if (lseek(fd, byte_address, SEEK_SET) != -1)
|
|
||||||
return 1;
|
|
||||||
if (!(flag & 2)) {
|
|
||||||
sprintf(msg, "Cannot address start byte %.f",
|
|
||||||
(double) byte_address);
|
|
||||||
libdax_msgs_submit(libdax_messenger,
|
|
||||||
d->global_index, 0x00020147,
|
|
||||||
(flag & 32) ?
|
|
||||||
LIBDAX_MSGS_SEV_DEBUG : LIBDAX_MSGS_SEV_SORRY,
|
|
||||||
LIBDAX_MSGS_PRIO_HIGH, msg, errno, 0);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A70904 */
|
|
||||||
/** @param flag bit0= be silent on data shortage
|
|
||||||
bit5= report data shortage with severity DEBUG
|
|
||||||
*/
|
|
||||||
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,
|
|
||||||
(flag & 32) ?
|
|
||||||
LIBDAX_MSGS_SEV_DEBUG : LIBDAX_MSGS_SEV_SORRY,
|
|
||||||
LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"Cannot read desired amount of data", errno, 0);
|
|
||||||
}
|
|
||||||
if (count < 0)
|
|
||||||
return -1;
|
|
||||||
return (bufsize - todo);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* With DVD and BD media, the minimum ECC entity is read instead of single
|
|
||||||
blocks.
|
|
||||||
@param flag see burn_read_data() in libburn.h
|
|
||||||
*/
|
|
||||||
static int retry_mmc_read(struct burn_drive *d, int chunksize, int sose_mem,
|
|
||||||
int start, char **wpt, off_t *data_count,
|
|
||||||
int flag)
|
|
||||||
{
|
|
||||||
int i, err, todo;
|
|
||||||
int retry_at, retry_size;
|
|
||||||
|
|
||||||
retry_at = start;
|
|
||||||
retry_size = chunksize;
|
|
||||||
todo = chunksize;
|
|
||||||
retry_size = 16; /* DVD ECC block size */
|
|
||||||
if (d->current_is_cd_profile) {
|
|
||||||
retry_size = 1; /* CD block size */
|
|
||||||
} else if (d->current_profile >= 0x40 && d->current_profile <= 0x43) {
|
|
||||||
retry_size = 32; /* BD cluster size */
|
|
||||||
}
|
|
||||||
for (i = 0; todo > 0; i++) {
|
|
||||||
if (flag & 2)
|
|
||||||
d->silent_on_scsi_error = 1;
|
|
||||||
else if (flag & 32)
|
|
||||||
d->silent_on_scsi_error = 3;
|
|
||||||
retry_at = start + i * retry_size;
|
|
||||||
if (retry_size > todo)
|
|
||||||
retry_size = todo;
|
|
||||||
err = d->read_10(d, retry_at, retry_size, d->buffer);
|
|
||||||
if (flag & (2 | 32))
|
|
||||||
d->silent_on_scsi_error = sose_mem;
|
|
||||||
if (err == BE_CANCELLED)
|
|
||||||
return 0;
|
|
||||||
memcpy(*wpt, d->buffer->data, retry_size * 2048);
|
|
||||||
*wpt += retry_size * 2048;
|
|
||||||
*data_count += retry_size * 2048;
|
|
||||||
todo -= retry_size;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* @param flag see burn_read_data() in libburn.h
|
|
||||||
*/
|
|
||||||
static int retry_stdio_read(struct burn_drive *d, int fd, int chunksize,
|
|
||||||
int start, char **wpt, off_t *data_count,
|
|
||||||
int flag)
|
|
||||||
{
|
|
||||||
int i, ret, to_read, todo;
|
|
||||||
|
|
||||||
ret = burn_stdio_seek(fd, ((off_t) start) * 2048, d, flag & 2);
|
|
||||||
if (ret <= 0)
|
|
||||||
return ret;
|
|
||||||
todo = chunksize * 2048;
|
|
||||||
for (i = 0; todo > 0; i += 2048) {
|
|
||||||
to_read = todo;
|
|
||||||
if (to_read > 2048)
|
|
||||||
to_read = 2048;
|
|
||||||
ret = burn_stdio_read(fd, (char *) d->buffer->data, to_read,
|
|
||||||
d, 1);
|
|
||||||
if (ret <= 0)
|
|
||||||
return 0;
|
|
||||||
memcpy(*wpt, d->buffer->data, to_read);
|
|
||||||
*wpt += to_read;
|
|
||||||
*data_count += to_read;
|
|
||||||
todo -= to_read;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
int sose_mem = 0, fd = -1, ret;
|
|
||||||
char msg[81], *wpt;
|
|
||||||
struct buffer *buf = NULL, *buffer_mem = d->buffer;
|
|
||||||
|
|
||||||
/*
|
|
||||||
#define Libburn_read_data_adr_logginG 1
|
|
||||||
*/
|
|
||||||
#ifdef Libburn_read_data_adr_logginG
|
|
||||||
static FILE *log_fp= NULL;
|
|
||||||
|
|
||||||
if(log_fp == NULL)
|
|
||||||
log_fp = fopen("/tmp/burn_read_data_log", "a");
|
|
||||||
if(log_fp!=NULL)
|
|
||||||
fprintf(log_fp, "%d\n", (int) (byte_address / 2048));
|
|
||||||
#endif /* Libburn_read_data_logginG */
|
|
||||||
|
|
||||||
BURN_ALLOC_MEM(buf, struct buffer, 1);
|
|
||||||
*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);
|
|
||||||
{ret = 0; goto ex;}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
{ret = 0; goto ex;}
|
|
||||||
} else if (d->drive_role == 3) {
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x00020151,
|
|
||||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"Read attempt on write-only drive", 0, 0);
|
|
||||||
{ret = 0; goto ex;}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
{ret = 0; goto ex;}
|
|
||||||
}
|
|
||||||
if (d->media_read_capacity != 0x7fffffffffffffff &&
|
|
||||||
byte_address >= (d->media_read_capacity + 1) * (off_t) 2048) {
|
|
||||||
if (!(flag & 2)) {
|
|
||||||
sprintf(msg,
|
|
||||||
"Read start address %.fs larger than number of readable blocks %.f",
|
|
||||||
(double) (byte_address / 2048 + !!(byte_address % 2048)),
|
|
||||||
(double) (d->media_read_capacity + 1));
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x00020172, (flag & 32) ?
|
|
||||||
LIBDAX_MSGS_SEV_DEBUG : LIBDAX_MSGS_SEV_SORRY,
|
|
||||||
LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
|
|
||||||
}
|
|
||||||
{ret = 0; goto ex;}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
{ret = 0; goto ex;}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 | O_BINARY);
|
|
||||||
if (fd == -1) {
|
|
||||||
if (errno == EACCES && (flag & 2)) {
|
|
||||||
if (!(flag & 8))
|
|
||||||
libdax_msgs_submit(libdax_messenger,
|
|
||||||
d->global_index, 0x00020183,
|
|
||||||
LIBDAX_MSGS_SEV_WARNING,
|
|
||||||
LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"Failed to open device (a pseudo-drive) for reading",
|
|
||||||
errno, 0);
|
|
||||||
} else if (errno != ENOENT || !(flag & 2))
|
|
||||||
libdax_msgs_submit(libdax_messenger,
|
|
||||||
d->global_index, 0x00020005,
|
|
||||||
(flag & 32) && errno == ENOENT ?
|
|
||||||
LIBDAX_MSGS_SEV_DEBUG :
|
|
||||||
LIBDAX_MSGS_SEV_SORRY,
|
|
||||||
LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"Failed to open device (a pseudo-drive) for reading",
|
|
||||||
errno, 0);
|
|
||||||
ret = 0;
|
|
||||||
if (errno == EACCES && (flag & 8))
|
|
||||||
ret= -2;
|
|
||||||
goto ex;
|
|
||||||
}
|
|
||||||
ret = burn_stdio_seek(fd, byte_address, d, flag & (2 | 32));
|
|
||||||
if (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 > (BUFFER_SIZE / 2048)) {
|
|
||||||
chunksize = (BUFFER_SIZE / 2048);
|
|
||||||
cpy_size = BUFFER_SIZE;
|
|
||||||
} else
|
|
||||||
cpy_size = data_size - *data_count;
|
|
||||||
if (flag & 2)
|
|
||||||
d->silent_on_scsi_error = 1;
|
|
||||||
else if (flag & 32)
|
|
||||||
d->silent_on_scsi_error = 3;
|
|
||||||
if (flag & 16) {
|
|
||||||
d->had_particular_error &= ~1;
|
|
||||||
if (!d->silent_on_scsi_error)
|
|
||||||
d->silent_on_scsi_error = 2;
|
|
||||||
}
|
|
||||||
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 & 32) | !!(flag & 2));
|
|
||||||
err = 0;
|
|
||||||
if (ret <= 0)
|
|
||||||
err = BE_CANCELLED;
|
|
||||||
}
|
|
||||||
if (flag & (2 | 16 | 32))
|
|
||||||
d->silent_on_scsi_error = sose_mem;
|
|
||||||
if (err == BE_CANCELLED) {
|
|
||||||
if ((flag & 16) && (d->had_particular_error & 1))
|
|
||||||
{ret = -3; goto ex;}
|
|
||||||
/* Retry: with CD read by single blocks
|
|
||||||
with other media: retry in full chunks
|
|
||||||
*/
|
|
||||||
if(flag & 4)
|
|
||||||
goto bad_read;
|
|
||||||
if (d->drive_role == 1) {
|
|
||||||
ret = retry_mmc_read(d, chunksize, sose_mem,
|
|
||||||
start, &wpt, data_count, flag);
|
|
||||||
} else {
|
|
||||||
ret = retry_stdio_read(d, fd, chunksize,
|
|
||||||
start, &wpt, data_count, flag);
|
|
||||||
}
|
|
||||||
if (ret <= 0)
|
|
||||||
goto bad_read;
|
|
||||||
} else {
|
|
||||||
memcpy(wpt, d->buffer->data, cpy_size);
|
|
||||||
wpt += cpy_size;
|
|
||||||
*data_count += cpy_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = 1;
|
|
||||||
ex:;
|
|
||||||
BURN_FREE_MEM(buf);
|
|
||||||
d->buffer = buffer_mem;
|
|
||||||
d->busy = BURN_DRIVE_IDLE;
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
bad_read:;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts B21119 : API function*/
|
|
||||||
int burn_read_audio(struct burn_drive *d, int sector_no,
|
|
||||||
char data[], off_t data_size, off_t *data_count, int flag)
|
|
||||||
{
|
|
||||||
int alignment = 2352, start, upto, chunksize = 1, err, cpy_size, i;
|
|
||||||
int sose_mem = 0, ret;
|
|
||||||
char msg[81], *wpt;
|
|
||||||
struct buffer *buf = NULL, *buffer_mem = d->buffer;
|
|
||||||
|
|
||||||
BURN_ALLOC_MEM(buf, struct buffer, 1);
|
|
||||||
*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);
|
|
||||||
{ret = 0; goto ex;}
|
|
||||||
}
|
|
||||||
if (d->drive_role != 1) {
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x00020146,
|
|
||||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"Drive is a virtual placeholder (stdio-drive or null-drive)",
|
|
||||||
0, 0);
|
|
||||||
{ret = 0; goto ex;}
|
|
||||||
}
|
|
||||||
if ((data_size % alignment) != 0) {
|
|
||||||
sprintf(msg,
|
|
||||||
"Audio read size not properly aligned (%d bytes)",
|
|
||||||
alignment);
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x0002019d,
|
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, 0, 0);
|
|
||||||
{ret = 0; goto ex;}
|
|
||||||
}
|
|
||||||
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 audio", 0, 0);
|
|
||||||
{ret = 0; goto ex;}
|
|
||||||
}
|
|
||||||
|
|
||||||
d->busy = BURN_DRIVE_READING_SYNC;
|
|
||||||
d->buffer = buf;
|
|
||||||
|
|
||||||
start = sector_no;
|
|
||||||
upto = start + data_size / alignment;
|
|
||||||
wpt = data;
|
|
||||||
for (; start < upto; start += chunksize) {
|
|
||||||
chunksize = upto - start;
|
|
||||||
if (chunksize > (BUFFER_SIZE / alignment))
|
|
||||||
chunksize = (BUFFER_SIZE / alignment);
|
|
||||||
cpy_size = chunksize * alignment;
|
|
||||||
if (flag & 2)
|
|
||||||
d->silent_on_scsi_error = 1;
|
|
||||||
else if (flag & 32)
|
|
||||||
d->silent_on_scsi_error = 3;
|
|
||||||
if (flag & 16) {
|
|
||||||
d->had_particular_error &= ~1;
|
|
||||||
if (!d->silent_on_scsi_error)
|
|
||||||
d->silent_on_scsi_error = 2;
|
|
||||||
}
|
|
||||||
err = d->read_cd(d, start, chunksize, 1, 0x10, NULL, d->buffer,
|
|
||||||
(flag & 8) >> 3);
|
|
||||||
if (flag & (2 | 16 | 32))
|
|
||||||
d->silent_on_scsi_error = sose_mem;
|
|
||||||
if (err == BE_CANCELLED) {
|
|
||||||
if ((flag & 16) && (d->had_particular_error & 1))
|
|
||||||
{ret = -3; goto ex;}
|
|
||||||
if(!(flag & 4))
|
|
||||||
for (i = 0; i < chunksize - 1; i++) {
|
|
||||||
if (flag & 2)
|
|
||||||
d->silent_on_scsi_error = 1;
|
|
||||||
else if (flag & 32)
|
|
||||||
d->silent_on_scsi_error = 3;
|
|
||||||
err = d->read_cd(d, start + i, 1, 1, 0x10,
|
|
||||||
NULL, d->buffer, (flag & 8) >> 3);
|
|
||||||
if (flag & (2 | 32))
|
|
||||||
d->silent_on_scsi_error = sose_mem;
|
|
||||||
if (err == BE_CANCELLED)
|
|
||||||
break;
|
|
||||||
memcpy(wpt, d->buffer->data, alignment);
|
|
||||||
wpt += alignment;
|
|
||||||
*data_count += alignment;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = 0; goto ex;
|
|
||||||
}
|
|
||||||
memcpy(wpt, d->buffer->data, cpy_size);
|
|
||||||
wpt += cpy_size;
|
|
||||||
*data_count += cpy_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = 1;
|
|
||||||
ex:
|
|
||||||
BURN_FREE_MEM(buf);
|
|
||||||
d->buffer = buffer_mem;
|
|
||||||
d->busy = BURN_DRIVE_IDLE;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef Libburn_develop_quality_scaN
|
|
||||||
|
|
||||||
/* B21108 ts */
|
|
||||||
int burn_nec_optiarc_rep_err_rate(struct burn_drive *d,
|
|
||||||
int start_lba, int rate_period, int flag)
|
|
||||||
{
|
|
||||||
int ret, lba = 0, error_rate1 = 0, error_rate2 = 0, enabled = 0, dret;
|
|
||||||
|
|
||||||
/* Sub Operation Code 1 : Enable Error Rate reporting function */
|
|
||||||
ret = mmc_nec_optiarc_f3(d, 1, start_lba, rate_period,
|
|
||||||
&lba, &error_rate1, &error_rate2);
|
|
||||||
if (ret <= 0)
|
|
||||||
goto ex;
|
|
||||||
enabled = 1;
|
|
||||||
|
|
||||||
/* >>> Sub Operation Code 2 : Seek to starting address
|
|
||||||
start_lba , rate_period
|
|
||||||
*/;
|
|
||||||
|
|
||||||
/* >>> Loop with Sub Operation Code 3 : Send Error Rate information
|
|
||||||
reply: 4-byte LBA , 2-byte C1/PIE , 2-byte C2/PIF
|
|
||||||
*/;
|
|
||||||
|
|
||||||
ret = 1;
|
|
||||||
ex:;
|
|
||||||
if (enabled) {
|
|
||||||
/* Code F : Disable Error Rate reporting function */
|
|
||||||
dret = mmc_nec_optiarc_f3(d, 0xf, 0, 0,
|
|
||||||
&lba, &error_rate1, &error_rate2);
|
|
||||||
if (dret < ret)
|
|
||||||
ret = dret;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* Libburn_develop_quality_scaN */
|
|
||||||
|
|
@ -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 */
|
|
186
libburn/sbc.c
186
libburn/sbc.c
@ -1,186 +0,0 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/* scsi block commands */
|
|
||||||
|
|
||||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
|
||||||
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#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);
|
|
||||||
|
|
||||||
|
|
||||||
/* START STOP UNIT as of SBC-1 and SBC-2
|
|
||||||
0: Opcode 0x1B
|
|
||||||
1: bit0= Immed
|
|
||||||
bit1-7= reserved
|
|
||||||
2: reserved
|
|
||||||
3: reserved
|
|
||||||
4: bit0= Start (else Stop unit)
|
|
||||||
bit1= Load/Eject (according to Start resp. Stop)
|
|
||||||
bit2-3= reserved
|
|
||||||
bit4-7= Power Condition
|
|
||||||
0= Start Valid: process Start and Load/Eject bits
|
|
||||||
1= assume Active state
|
|
||||||
2= assume Idle state
|
|
||||||
3= assume Stanby state
|
|
||||||
(5= SBC-1 only: assume Sleep state)
|
|
||||||
7= transfer control of power conditions to logical unit
|
|
||||||
10= force idle condition timer to 0
|
|
||||||
11= force standby condition timer to 0
|
|
||||||
All others are reserved.
|
|
||||||
5: Control (set to 0)
|
|
||||||
*/
|
|
||||||
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 };
|
|
||||||
static unsigned char SBC_STOP_UNIT[] = { 0x1b, 0, 0, 0, 0, 0 };
|
|
||||||
|
|
||||||
void sbc_load(struct burn_drive *d)
|
|
||||||
{
|
|
||||||
struct command *c;
|
|
||||||
|
|
||||||
c = &(d->casual_command);
|
|
||||||
if (mmc_function_spy(d, "load") <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
scsi_init_command(c, SBC_LOAD, sizeof(SBC_LOAD));
|
|
||||||
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;
|
|
||||||
c->timeout = Libburn_mmc_load_timeouT;
|
|
||||||
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;
|
|
||||||
|
|
||||||
c = &(d->casual_command);
|
|
||||||
if (mmc_function_spy(d, "eject") <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
scsi_init_command(c, SBC_UNLOAD, sizeof(SBC_UNLOAD));
|
|
||||||
/* c->opcode[1] |= 1; / * ts A70918 : Immed , ts B00109 : revoked */
|
|
||||||
c->page = NULL;
|
|
||||||
c->dir = NO_TRANSFER;
|
|
||||||
d->issue_command(d, c);
|
|
||||||
/* ts A70918 : Wait long. A late eject could surprise or hurt user.
|
|
||||||
ts B00109 : Asynchronous eject revoked, as one cannot reliably
|
|
||||||
distinguish out from unready.
|
|
||||||
if (c->error)
|
|
||||||
return;
|
|
||||||
spc_wait_unit_attention(d, 1800, "STOP UNIT (+ EJECT)", 0);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A91112 : Now with flag */
|
|
||||||
/* @param flag bit0= asynchronous waiting
|
|
||||||
*/
|
|
||||||
int sbc_start_unit_flag(struct burn_drive *d, int flag)
|
|
||||||
{
|
|
||||||
struct command *c;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
c = &(d->casual_command);
|
|
||||||
if (mmc_function_spy(d, "start_unit") <= 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
scsi_init_command(c, SBC_START_UNIT, sizeof(SBC_START_UNIT));
|
|
||||||
c->retry = 1;
|
|
||||||
if (d->do_no_immed && (flag & 1))
|
|
||||||
c->timeout = 1800 * 1000;
|
|
||||||
else
|
|
||||||
c->opcode[1] |= (flag & 1); /* ts A70918 : Immed */
|
|
||||||
c->dir = NO_TRANSFER;
|
|
||||||
d->issue_command(d, c);
|
|
||||||
if (c->error)
|
|
||||||
return 0;
|
|
||||||
if (d->do_no_immed || !(flag & 1))
|
|
||||||
return 1;
|
|
||||||
/* ts A70918 : asynchronous */
|
|
||||||
ret = spc_wait_unit_attention(d, 1800, "START UNIT", 0);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int sbc_start_unit(struct burn_drive *d)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
d->is_stopped = 0; /* no endless starting attempts */
|
|
||||||
|
|
||||||
/* Asynchronous, not to block controller by waiting */
|
|
||||||
ret = sbc_start_unit_flag(d, 1);
|
|
||||||
if (ret <= 0)
|
|
||||||
return ret;
|
|
||||||
/* Synchronous to catch Pioneer DVR-216D which is ready too early.
|
|
||||||
A pending START UNIT can prevent ejecting of the tray.
|
|
||||||
*/
|
|
||||||
ret = sbc_start_unit_flag(d, 0);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A90824 : Trying to reduce drive noise */
|
|
||||||
int sbc_stop_unit(struct burn_drive *d)
|
|
||||||
{
|
|
||||||
struct command *c;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
c = &(d->casual_command);
|
|
||||||
if (mmc_function_spy(d, "stop_unit") <= 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
scsi_init_command(c, SBC_STOP_UNIT, sizeof(SBC_STOP_UNIT));
|
|
||||||
c->retry = 0;
|
|
||||||
c->opcode[1] |= 1; /* Immed */
|
|
||||||
c->dir = NO_TRANSFER;
|
|
||||||
d->issue_command(d, c);
|
|
||||||
if (c->error)
|
|
||||||
return 0;
|
|
||||||
ret = spc_wait_unit_attention(d, 1800, "STOP UNIT", 0);
|
|
||||||
d->is_stopped = 1;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
d->stop_unit = sbc_stop_unit;
|
|
||||||
d->is_stopped = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
|
||||||
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __SBC
|
|
||||||
#define __SBC
|
|
||||||
|
|
||||||
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 */
|
|
955
libburn/sector.c
955
libburn/sector.c
@ -1,955 +0,0 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
|
||||||
Copyright (c) 2006 - 2021 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
/* ts A61010 */
|
|
||||||
/* #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 "toc.h"
|
|
||||||
#include "write.h"
|
|
||||||
|
|
||||||
#include "libdax_msgs.h"
|
|
||||||
extern struct libdax_msgs *libdax_messenger;
|
|
||||||
|
|
||||||
#include "ecma130ab.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 */
|
|
||||||
|
|
||||||
/* ts B41126 : O_BINARY is needed for Cygwin but undefined elsewhere */
|
|
||||||
#ifndef O_BINARY
|
|
||||||
#define O_BINARY 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*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 | O_BINARY,
|
|
||||||
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 - B10103 */
|
|
||||||
if (shortage >= count)
|
|
||||||
track->track_data_done = 1;
|
|
||||||
if (track->end_on_premature_eoi && shortage >= count &&
|
|
||||||
!track->open_ended) {
|
|
||||||
char msg[80];
|
|
||||||
off_t missing, inp_block_size, track_blocks;
|
|
||||||
|
|
||||||
inp_block_size = burn_sector_length(track->mode);
|
|
||||||
track_blocks = burn_track_get_sectors_2_v2(track, 1);
|
|
||||||
if (track_blocks < 0)
|
|
||||||
track_blocks = 0;
|
|
||||||
missing = track_blocks * inp_block_size - track->sourcecount;
|
|
||||||
sprintf(msg,
|
|
||||||
"Premature end of input encountered. Missing: %.f bytes",
|
|
||||||
(double) missing);
|
|
||||||
libdax_msgs_submit(libdax_messenger, -1, 0x00020180,
|
|
||||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, 0,0);
|
|
||||||
/* Memorize that premature end of input happened */
|
|
||||||
track->end_on_premature_eoi = 2;
|
|
||||||
}
|
|
||||||
if (track->open_ended || track->end_on_premature_eoi)
|
|
||||||
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 B20113 : outsourced from get_sector() */
|
|
||||||
int sector_write_buffer(struct burn_drive *d,
|
|
||||||
struct burn_track *track, int flag)
|
|
||||||
{
|
|
||||||
int err, i;
|
|
||||||
struct buffer *out;
|
|
||||||
|
|
||||||
out = d->buffer;
|
|
||||||
if (out->sectors <= 0)
|
|
||||||
return 2;
|
|
||||||
err = d->write(d, d->nwa, out);
|
|
||||||
if (err == BE_CANCELLED)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* ts A61101 */
|
|
||||||
if(track != NULL) {
|
|
||||||
track->writecount += out->bytes;
|
|
||||||
track->written_sectors += out->sectors;
|
|
||||||
|
|
||||||
/* Determine current index */
|
|
||||||
for (i = d->progress.index; i + 1 < track->indices; i++) {
|
|
||||||
if (track->index[i + 1] > d->nwa + out->sectors)
|
|
||||||
break;
|
|
||||||
d->progress.index = i + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* ts A61119 */
|
|
||||||
d->progress.buffered_bytes += out->bytes;
|
|
||||||
|
|
||||||
d->nwa += out->sectors;
|
|
||||||
out->bytes = 0;
|
|
||||||
out->sectors = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* 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, seclen, write_ret;
|
|
||||||
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 */
|
|
||||||
/* (there is enough buffer size reserve for track->cdxa_conversion) */
|
|
||||||
if (out->bytes + seclen > BUFFER_SIZE ||
|
|
||||||
(opts->obs > 0 && out->bytes + seclen > opts->obs)) {
|
|
||||||
write_ret = sector_write_buffer(d, track, 0);
|
|
||||||
if (write_ret <= 0)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
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 || outlen < 0 || inlen < 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if ((outmode & BURN_MODE_BITS) == (inmode & BURN_MODE_BITS)) {
|
|
||||||
/* see MMC-5 4.2.3.8.5.3 Block Format for Mode 2 form 1 Data
|
|
||||||
Table 24 Mode 2 Formed Sector Sub-header Format */
|
|
||||||
if (track != NULL)
|
|
||||||
if (track->cdxa_conversion == 1)
|
|
||||||
inlen += 8;
|
|
||||||
|
|
||||||
get_bytes(track, inlen, data);
|
|
||||||
|
|
||||||
if (track != NULL)
|
|
||||||
if (track->cdxa_conversion == 1)
|
|
||||||
memmove(data, data + 8, inlen - 8);
|
|
||||||
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);
|
|
||||||
|
|
||||||
#ifdef Libburn_no_crc_C
|
|
||||||
crc = 0; /* dummy */
|
|
||||||
#else
|
|
||||||
crc = crc_ccitt(q, 10);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
q[10] = crc >> 8;
|
|
||||||
q[11] = crc & 0xFF;
|
|
||||||
d->toc_temp++;
|
|
||||||
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);
|
|
||||||
if (sector_headers(o, data, mode, 1) <= 0)
|
|
||||||
return 0;
|
|
||||||
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);
|
|
||||||
if (sector_headers(o, data, mode, 0) <= 0)
|
|
||||||
return 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);
|
|
||||||
if (sector_headers(o, data, mode, 0) <= 0)
|
|
||||||
return 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);
|
|
||||||
|
|
||||||
#ifdef Libburn_no_crc_C
|
|
||||||
crc = 0; /* dummy */
|
|
||||||
#else
|
|
||||||
crc = crc_ccitt(q, 10);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef Libburn_no_crc_C
|
|
||||||
crc = 0; /* dummy */
|
|
||||||
#else
|
|
||||||
crc = crc_ccitt(q, 10);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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);
|
|
||||||
if (sector_headers(o, data, mode, 0) <= 0)
|
|
||||||
return 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 == NULL)
|
|
||||||
return 0;
|
|
||||||
/* ts A61010 */
|
|
||||||
if (convert_data(o, t, t->mode, data) <= 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* ts A61031 */
|
|
||||||
if ((t->open_ended || t->end_on_premature_eoi) && 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);
|
|
||||||
|
|
||||||
if (sector_headers(o, data, t->mode, 0) <= 0)
|
|
||||||
return 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ts A90830 : changed return type to int
|
|
||||||
@return 0= failure
|
|
||||||
1= success
|
|
||||||
*/
|
|
||||||
int sector_headers(struct burn_write_opts *o, unsigned char *out,
|
|
||||||
int mode, int leadin)
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef Libburn_ecma130ab_includeD
|
|
||||||
|
|
||||||
struct burn_drive *d = o->drive;
|
|
||||||
unsigned int crc;
|
|
||||||
int min, sec, frame;
|
|
||||||
int modebyte = -1;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = sector_headers_is_ok(o, mode);
|
|
||||||
if (ret != 2)
|
|
||||||
return !!ret;
|
|
||||||
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) {
|
|
||||||
|
|
||||||
#ifdef Libburn_no_crc_C
|
|
||||||
crc = 0; /* dummy */
|
|
||||||
#else
|
|
||||||
crc = crc_32(out, 2064);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
out[2064] = crc & 0xFF;
|
|
||||||
crc >>= 8;
|
|
||||||
out[2065] = crc & 0xFF;
|
|
||||||
crc >>= 8;
|
|
||||||
out[2066] = crc & 0xFF;
|
|
||||||
crc >>= 8;
|
|
||||||
out[2067] = crc & 0xFF;
|
|
||||||
}
|
|
||||||
if (mode & BURN_MODE1) {
|
|
||||||
memset(out + 2068, 0, 8);
|
|
||||||
burn_rspc_parity_p(out);
|
|
||||||
burn_rspc_parity_q(out);
|
|
||||||
}
|
|
||||||
burn_ecma130_scramble(out);
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
#else /* Libburn_ecma130ab_includeD */
|
|
||||||
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = sector_headers_is_ok(o, mode);
|
|
||||||
if (ret != 2)
|
|
||||||
return (!! ret);
|
|
||||||
|
|
||||||
/* ts A90830 : lec.c is copied from cdrdao.
|
|
||||||
I have no idea yet how lec.c implements the Reed-Solomon encoding
|
|
||||||
which is described in ECMA-130 for CD-ROM.
|
|
||||||
So this got removed for now.
|
|
||||||
*/
|
|
||||||
libdax_msgs_submit(libdax_messenger, o->drive->global_index,
|
|
||||||
0x0002010a,
|
|
||||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"Raw CD write modes are not supported", 0, 0);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
#endif /* ! Libburn_ecma130ab_includeD */
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#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 do not 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 without Assert */
|
|
||||||
a ssert(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* this needs more info. subs in the data? control/adr? */
|
|
||||||
|
|
||||||
/* ts A61119 : One should not use unofficial 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)
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
burn_ecma130_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;
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
|
||||||
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __SECTOR
|
|
||||||
#define __SECTOR
|
|
||||||
|
|
||||||
#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 B20113 */
|
|
||||||
int sector_write_buffer(struct burn_drive *d,
|
|
||||||
struct burn_track *track, int flag);
|
|
||||||
|
|
||||||
/* ts A61009 */
|
|
||||||
int sector_headers_is_ok(struct burn_write_opts *o, int mode);
|
|
||||||
|
|
||||||
int 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 */
|
|
33
libburn/setup.py
Normal file
33
libburn/setup.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
from distutils.core import setup, Extension
|
||||||
|
|
||||||
|
sources = ["src/burnmodule.c", "src/disc.c", "src/drive.c",
|
||||||
|
"src/drive_info.c", "src/message.c", "src/progress.c",
|
||||||
|
"src/read_opts.c", "src/session.c", "src/source.c",
|
||||||
|
"src/toc_entry.c", "src/track.c", "src/write_opts.c"]
|
||||||
|
|
||||||
|
include_dirs = ["/usr/include", "/usr/local/include"]
|
||||||
|
library_dirs = ["/usr/lib", "/usr/local/lib"]
|
||||||
|
libraries = ["burn", "pthread"]
|
||||||
|
|
||||||
|
long_description = \
|
||||||
|
"""Python Interface to libBurn 0.2.2
|
||||||
|
|
||||||
|
pyburn is a stupid binding to libBurn, the awesome burning library"""
|
||||||
|
|
||||||
|
module = Extension('burn',
|
||||||
|
define_macros = [('MAJOR_VERSION', '0'),
|
||||||
|
('MINOR_VERSION', '1')],
|
||||||
|
include_dirs = include_dirs,
|
||||||
|
libraries = libraries,
|
||||||
|
sources = sources)
|
||||||
|
|
||||||
|
setup (name = 'burn',
|
||||||
|
version = '0.1',
|
||||||
|
description = "Stupid bindings to libBurn 0.2.2",
|
||||||
|
long_description=long_description,
|
||||||
|
author = "Anant Narayanan",
|
||||||
|
author_email = "anant@kix.in",
|
||||||
|
license = "GPLv2",
|
||||||
|
platforms = "POSIX",
|
||||||
|
url = "http://libburn.pykix.org/",
|
||||||
|
ext_modules = [module])
|
@ -1,359 +0,0 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright (c) 2009 - 2011 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
This is the main operating system dependent SCSI part of libburn. It implements
|
|
||||||
the transport level aspects of SCSI control and command i/o.
|
|
||||||
|
|
||||||
Present implementation: default dummy which enables libburn only to work
|
|
||||||
with stdio: pseudo drive addresses.
|
|
||||||
For real implementations see sg-linux.c, sg-freebsd.c,
|
|
||||||
sg-libcdio.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#ifdef Libburn_os_has_statvfS
|
|
||||||
#include <sys/statvfs.h>
|
|
||||||
#endif /* Libburn_os_has_stavtfS */
|
|
||||||
|
|
||||||
/* ts B41126 : O_BINARY is needed for Cygwin but undefined elsewhere */
|
|
||||||
#ifndef O_BINARY
|
|
||||||
#define O_BINARY 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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 "init.h"
|
|
||||||
|
|
||||||
#include "libdax_msgs.h"
|
|
||||||
extern struct libdax_msgs *libdax_messenger;
|
|
||||||
|
|
||||||
|
|
||||||
/** Returns the id string of the SCSI transport adapter and eventually
|
|
||||||
needed operating system facilities.
|
|
||||||
This call is usable even if sg_initialize() was not called yet. In that
|
|
||||||
case a preliminary constant message might be issued if detailed info is
|
|
||||||
not available yet.
|
|
||||||
@param msg returns id string
|
|
||||||
@param flag unused yet, submit 0
|
|
||||||
@return 1 = success, <=0 = failure
|
|
||||||
*/
|
|
||||||
int sg_id_string(char msg[1024], int flag)
|
|
||||||
{
|
|
||||||
strcpy(msg, "internal X/Open adapter sg-dummy");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Performs global initialization of the SCSI transport adapter and eventually
|
|
||||||
needed operating system facilities. Checks for compatibility supporting
|
|
||||||
software components.
|
|
||||||
@param msg returns ids and/or error messages of eventual helpers
|
|
||||||
@param flag unused yet, submit 0
|
|
||||||
@return 1 = success, <=0 = failure
|
|
||||||
*/
|
|
||||||
int sg_initialize(char msg[1024], int flag)
|
|
||||||
{
|
|
||||||
return sg_id_string(msg, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Performs global finalization of the SCSI transport adapter and eventually
|
|
||||||
needed operating system facilities. Releases globally acquired resources.
|
|
||||||
@param flag unused yet, submit 0
|
|
||||||
@return 1 = success, <=0 = failure
|
|
||||||
*/
|
|
||||||
int sg_shutdown(int flag)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
|
|
||||||
struct burn_drive which are defined in os-*.h.
|
|
||||||
This will be called when a burn_drive gets disposed.
|
|
||||||
@param d the drive to be finalized
|
|
||||||
@param flag unused yet, submit 0
|
|
||||||
@return 1 = success, <=0 = failure
|
|
||||||
*/
|
|
||||||
int sg_dispose_drive(struct burn_drive *d, int flag)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Returns the next index number and the next enumerated drive address.
|
|
||||||
The enumeration has to cover all available and accessible drives. It is
|
|
||||||
allowed to return addresses of drives which are not available but under
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Brings all available, not-whitelist-banned, and accessible drives into
|
|
||||||
libburn's list of drives.
|
|
||||||
*/
|
|
||||||
/* ts A61115: replacing call to sg-implementation internals from drive.c */
|
|
||||||
int scsi_enumerate_drives(void)
|
|
||||||
{
|
|
||||||
libdax_msgs_submit(libdax_messenger, -1, 0x0002016b,
|
|
||||||
LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"No MMC transport adapter is present. Running on sg-dummy.c.",
|
|
||||||
0, 0);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Tells whether libburn has the given drive in use or exclusively reserved.
|
|
||||||
If it is "open" then libburn will eventually call sg_release() on it when
|
|
||||||
it is time to give up usage and reservation.
|
|
||||||
*/
|
|
||||||
/** Published as burn_drive.drive_is_open() */
|
|
||||||
int sg_drive_is_open(struct burn_drive * d)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 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)
|
|
||||||
{
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002016a,
|
|
||||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"No MMC transport adapter is present. Running on sg-dummy.c.",
|
|
||||||
0, 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 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)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Sends a SCSI command to the drive, receives reply and evaluates whether
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002016a,
|
|
||||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"No MMC transport adapter is present. Running on sg-dummy.c.",
|
|
||||||
0, 0);
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
libdax_msgs_submit(libdax_messenger, -1, 0x0002016c,
|
|
||||||
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"No MMC transport adapter is present. Running on sg-dummy.c.",
|
|
||||||
0, 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Tells whether a text is a persistent address as listed by the enumeration
|
|
||||||
functions.
|
|
||||||
*/
|
|
||||||
int sg_is_enumerable_adr(char *adr)
|
|
||||||
{
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Return 1 if the given path leads to a regular file or a device that can be
|
|
||||||
fseeked, read, and possibly written with 2 kB granularity.
|
|
||||||
*/
|
|
||||||
int burn_os_is_2k_seekrw(char *path, int flag)
|
|
||||||
{
|
|
||||||
struct stat stbuf;
|
|
||||||
|
|
||||||
if (stat(path, &stbuf) == -1)
|
|
||||||
return 0;
|
|
||||||
if (S_ISREG(stbuf.st_mode))
|
|
||||||
return 1;
|
|
||||||
if (S_ISBLK(stbuf.st_mode))
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Estimate the potential payload capacity of a file address.
|
|
||||||
@param path The address of the file to be examined. If it does not
|
|
||||||
exist yet, then the directory will be inquired.
|
|
||||||
@param bytes The pointed value gets modified, but only if an estimation is
|
|
||||||
possible.
|
|
||||||
@return -2 = cannot perform necessary operations on file object
|
|
||||||
-1 = neither path nor dirname of path exist
|
|
||||||
0 = could not estimate size capacity of file object
|
|
||||||
1 = estimation has been made, bytes was set
|
|
||||||
*/
|
|
||||||
int burn_os_stdio_capacity(char *path, off_t write_start, off_t *bytes)
|
|
||||||
{
|
|
||||||
struct stat stbuf;
|
|
||||||
|
|
||||||
#ifdef Libburn_os_has_statvfS
|
|
||||||
struct statvfs vfsbuf;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char *testpath = NULL, *cpt;
|
|
||||||
off_t add_size = 0;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
BURN_ALLOC_MEM(testpath, char, 4096);
|
|
||||||
|
|
||||||
testpath[0] = 0;
|
|
||||||
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)
|
|
||||||
{ret = -1; goto ex;}
|
|
||||||
|
|
||||||
#ifdef Libburn_if_this_was_linuX
|
|
||||||
|
|
||||||
} else if(S_ISBLK(stbuf.st_mode)) {
|
|
||||||
long blocks;
|
|
||||||
|
|
||||||
blocks = *bytes / 512;
|
|
||||||
fd = open(path, open_mode | O_BINARY);
|
|
||||||
if (fd == -1)
|
|
||||||
{ret = -2; goto ex;}
|
|
||||||
ret = ioctl(fd, BLKGETSIZE, &blocks);
|
|
||||||
close(fd);
|
|
||||||
if (ret == -1)
|
|
||||||
{ret = -2; goto ex;}
|
|
||||||
*bytes = ((off_t) blocks) * (off_t) 512;
|
|
||||||
|
|
||||||
#endif /* Libburn_if_this_was_linuX */
|
|
||||||
|
|
||||||
} else if(S_ISREG(stbuf.st_mode)) {
|
|
||||||
add_size = burn_sparse_file_addsize(write_start, &stbuf);
|
|
||||||
strcpy(testpath, path);
|
|
||||||
} else
|
|
||||||
{ret = 0; goto ex;}
|
|
||||||
|
|
||||||
if (testpath[0]) {
|
|
||||||
|
|
||||||
#ifdef Libburn_os_has_statvfS
|
|
||||||
|
|
||||||
if (statvfs(testpath, &vfsbuf) == -1)
|
|
||||||
{ret = -2; goto ex;}
|
|
||||||
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
|
|
||||||
(off_t) vfsbuf.f_bavail;
|
|
||||||
|
|
||||||
#else /* Libburn_os_has_statvfS */
|
|
||||||
|
|
||||||
{ret = 0; goto ex;}
|
|
||||||
|
|
||||||
#endif /* ! Libburn_os_has_stavtfS */
|
|
||||||
|
|
||||||
}
|
|
||||||
ret = 1;
|
|
||||||
ex:;
|
|
||||||
BURN_FREE_MEM(testpath);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
|
|
||||||
|
|
||||||
#ifdef Libburn_read_o_direcT
|
|
||||||
|
|
||||||
/* No special O_DIRECT-like precautions are implemented here */
|
|
||||||
|
|
||||||
#endif /* Libburn_read_o_direcT */
|
|
||||||
|
|
||||||
|
|
||||||
int burn_os_open_track_src(char *path, int open_flags, int flag)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
fd = open(path, open_flags | O_BINARY);
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *burn_os_alloc_buffer(size_t amount, int flag)
|
|
||||||
{
|
|
||||||
void *buf = NULL;
|
|
||||||
|
|
||||||
buf = calloc(1, amount);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
|
|
||||||
{
|
|
||||||
if (buffer == NULL)
|
|
||||||
return 0;
|
|
||||||
free(buffer);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
@ -1,830 +0,0 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright (c) 2006 - 2011 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* THIS CODE IS NOT FUNCTIONAL YET !!! */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
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_id_string() returns an id string of the SCSI transport adapter.
|
|
||||||
It may be called before initialization but then may
|
|
||||||
return only a preliminary id.
|
|
||||||
|
|
||||||
sg_initialize() performs global initialization of the SCSI transport
|
|
||||||
adapter and eventually needed operating system
|
|
||||||
facilities. Checks for compatibility of supporting
|
|
||||||
software components.
|
|
||||||
|
|
||||||
sg_shutdown() performs global finalizations and releases globally
|
|
||||||
acquired resources.
|
|
||||||
|
|
||||||
sg_give_next_adr() iterates over the set of potentially useful drive
|
|
||||||
address strings.
|
|
||||||
|
|
||||||
scsi_enumerate_drives() brings all available, not-whitelist-banned, and
|
|
||||||
accessible drives into libburn's list of drives.
|
|
||||||
|
|
||||||
sg_dispose_drive() finalizes adapter specifics of struct burn_drive
|
|
||||||
on destruction. Releases resources which were acquired
|
|
||||||
underneath scsi_enumerate_drives().
|
|
||||||
|
|
||||||
sg_drive_is_open() tells whether 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 whether the command succeeded or shall
|
|
||||||
be retried or finally failed.
|
|
||||||
|
|
||||||
sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
|
|
||||||
|
|
||||||
|
|
||||||
burn_os_is_2k_seekrw() tells whether the given path leads to a file object
|
|
||||||
that can be used in 2 kB granularity by lseek(2),
|
|
||||||
read(2), and possibly write(2) if not read-only.
|
|
||||||
E.g. a USB stick or a hard disk.
|
|
||||||
|
|
||||||
burn_os_stdio_capacity() estimates the emulated media space of stdio-drives.
|
|
||||||
|
|
||||||
burn_os_open_track_src() opens a disk file in a way that offers best
|
|
||||||
throughput with file reading and/or SCSI write command
|
|
||||||
transmission.
|
|
||||||
|
|
||||||
burn_os_alloc_buffer() allocates a memory area that is suitable for file
|
|
||||||
descriptors issued by burn_os_open_track_src().
|
|
||||||
The buffer size may be rounded up for alignment
|
|
||||||
reasons.
|
|
||||||
|
|
||||||
burn_os_free_buffer() delete a buffer obtained by burn_os_alloc_buffer().
|
|
||||||
|
|
||||||
|
|
||||||
Porting hints are marked by the text "PORTING:".
|
|
||||||
Send feedback to libburn-hackers@pykix.org .
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** PORTING : ------- OS dependent headers and definitions ------ */
|
|
||||||
|
|
||||||
#include <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 */
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&(idx->ccb), 0, 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 *)
|
|
||||||
calloc(1, idx->bufsize);
|
|
||||||
if (idx->ccb.cdm.matches == NULL) {
|
|
||||||
warnx("cannot allocate 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 id string of the SCSI transport adapter and eventually
|
|
||||||
needed operating system facilities.
|
|
||||||
This call is usable even if sg_initialize() was not called yet. In that
|
|
||||||
case a preliminary constant message might be issued if detailed info is
|
|
||||||
not available yet.
|
|
||||||
@param msg returns id string
|
|
||||||
@param flag unused yet, submit 0
|
|
||||||
@return 1 = success, <=0 = failure
|
|
||||||
*/
|
|
||||||
int sg_id_string(char msg[1024], int flag)
|
|
||||||
{
|
|
||||||
strcpy(msg, "internal FreeBSD CAM adapter sg-freebsd-port");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Performs global initialization of the SCSI transport adapter and eventually
|
|
||||||
needed operating system facilities. Checks for compatibility supporting
|
|
||||||
software components.
|
|
||||||
@param msg returns ids and/or error messages of eventual helpers
|
|
||||||
@param flag unused yet, submit 0
|
|
||||||
@return 1 = success, <=0 = failure
|
|
||||||
*/
|
|
||||||
int sg_initialize(char msg[1024], int flag)
|
|
||||||
{
|
|
||||||
return sg_id_string(msg, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Performs global finalization of the SCSI transport adapter and eventually
|
|
||||||
needed operating system facilities. Releases globally acquired resources.
|
|
||||||
@param flag unused yet, submit 0
|
|
||||||
@return 1 = success, <=0 = failure
|
|
||||||
*/
|
|
||||||
int sg_shutdown(int flag)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
|
|
||||||
struct burn_drive which are defined in os-*.h.
|
|
||||||
The eventual initialization of those components was made underneath
|
|
||||||
scsi_enumerate_drives().
|
|
||||||
This will be called when a burn_drive gets disposed.
|
|
||||||
@param d the drive to be finalized
|
|
||||||
@param flag unused yet, submit 0
|
|
||||||
@return 1 = success, <=0 = failure
|
|
||||||
*/
|
|
||||||
int sg_dispose_drive(struct burn_drive *d, int flag)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Returns the next index number and the next enumerated drive address.
|
|
||||||
The enumeration has to cover all available and accessible drives. It is
|
|
||||||
allowed to return addresses of drives which are not available but under
|
|
||||||
some (even exotic) circumstances could be available. It is on the other
|
|
||||||
hand allowed, only to hand out addresses which can really be used right
|
|
||||||
in the moment of this call. (This implementation chooses the latter.)
|
|
||||||
@param idx An opaque handle. Make no own theories about it.
|
|
||||||
@param adr Takes the reply
|
|
||||||
@param adr_size Gives maximum size of reply including final 0
|
|
||||||
@param initialize 1 = start new,
|
|
||||||
0 = continue, use no other values for now
|
|
||||||
-1 = finish
|
|
||||||
@return 1 = reply is a valid address , 0 = no further address available
|
|
||||||
-1 = severe error (e.g. adr_size too small)
|
|
||||||
*/
|
|
||||||
int sg_give_next_adr(burn_drive_enumerator_t *idx,
|
|
||||||
char adr[], int adr_size, int initialize)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (initialize == 1) {
|
|
||||||
ret = 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, ret;
|
|
||||||
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);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Tells whether libburn has the given drive in use or exclusively reserved.
|
|
||||||
If it is "open" then libburn will eventually call sg_release() on it when
|
|
||||||
it is time to give up usage and 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)
|
|
||||||
{
|
|
||||||
struct cam_device *cam;
|
|
||||||
|
|
||||||
if(d->cam != NULL) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
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 whether it
|
|
||||||
implements the demanded functionality.
|
|
||||||
*/
|
|
||||||
/** Gives up the drive for SCSI commands and releases eventual access locks.
|
|
||||||
(Note: this is not physical tray locking.)
|
|
||||||
*/
|
|
||||||
int sg_release(struct burn_drive *d)
|
|
||||||
{
|
|
||||||
if (d->cam == NULL)
|
|
||||||
return 0;
|
|
||||||
sg_close_drive(d);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Sends a SCSI command to the drive, receives reply and evaluates whether
|
|
||||||
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);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ts B90523 : Record effective transfer length request for debugging*/
|
|
||||||
c->dxfer_len = ccb->csio.dxfer_len;
|
|
||||||
|
|
||||||
do {
|
|
||||||
memset(&ccb->csio.sense_data, 0, sizeof(ccb->csio.sense_data));
|
|
||||||
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);
|
|
||||||
c->sense_len = 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;
|
|
||||||
}
|
|
||||||
if (!done)
|
|
||||||
spc_register_retry(c);
|
|
||||||
} 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, ret;
|
|
||||||
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(path, 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 whether a text is a persistent address as listed by the enumeration
|
|
||||||
functions.
|
|
||||||
*/
|
|
||||||
int sg_is_enumerable_adr(char* adr)
|
|
||||||
{
|
|
||||||
burn_drive_enumerator_t idx;
|
|
||||||
int initialize = 1, ret;
|
|
||||||
char buf[64];
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
|
|
||||||
initialize = 0;
|
|
||||||
if (ret <= 0)
|
|
||||||
break;
|
|
||||||
if (strcmp(adr, buf) == 0) {
|
|
||||||
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts B00115 */
|
|
||||||
/* Return 1 if the given path leads to a regular file or a device that can be
|
|
||||||
seeked, written, and read with 2 kB granularity.
|
|
||||||
*/
|
|
||||||
int burn_os_is_2k_seekrw(char *path, int flag)
|
|
||||||
{
|
|
||||||
struct stat stbuf;
|
|
||||||
char *spt;
|
|
||||||
int i, e;
|
|
||||||
|
|
||||||
if (stat(path, &stbuf) == -1)
|
|
||||||
return 0;
|
|
||||||
if (S_ISREG(stbuf.st_mode))
|
|
||||||
return 1;
|
|
||||||
if (!S_ISCHR(stbuf.st_mode))
|
|
||||||
return 0;
|
|
||||||
spt = strrchr(path, '/');
|
|
||||||
if (spt == NULL)
|
|
||||||
spt = path;
|
|
||||||
else
|
|
||||||
spt++;
|
|
||||||
e = strlen(spt);
|
|
||||||
for (i = strlen(spt) - 1; i > 0; i--)
|
|
||||||
if (spt[i] >= '0' && spt[i] <= '9')
|
|
||||||
e = i;
|
|
||||||
if (strncmp(spt, "da", e) == 0) /* SCSI disk. E.g. USB stick. */
|
|
||||||
return 1;
|
|
||||||
if (strncmp(spt, "cd", e) == 0) /* SCSI CD drive might be writeable. */
|
|
||||||
return 1;
|
|
||||||
if (strncmp(spt, "ad", e) == 0) /* IDE hard drive */
|
|
||||||
return 1;
|
|
||||||
if (strncmp(spt, "acd", e) == 0) /* IDE CD drive might be writeable */
|
|
||||||
return 1;
|
|
||||||
if (strncmp(spt, "fd", e) == 0) /* Floppy disk */
|
|
||||||
return 1;
|
|
||||||
if (strncmp(spt, "fla", e) == 0) /* Flash drive */
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A70909 */
|
|
||||||
/** Estimate the potential payload capacity of a file address.
|
|
||||||
@param path The address of the file to be examined. If it does not
|
|
||||||
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 write_start, off_t *bytes)
|
|
||||||
{
|
|
||||||
struct stat stbuf;
|
|
||||||
struct statvfs vfsbuf;
|
|
||||||
char *testpath = NULL, *cpt;
|
|
||||||
off_t add_size = 0;
|
|
||||||
int fd, ret;
|
|
||||||
|
|
||||||
BURN_ALLOC_MEM(testpath, char, 4096);
|
|
||||||
testpath[0] = 0;
|
|
||||||
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)
|
|
||||||
{ret = -1; goto ex;}
|
|
||||||
|
|
||||||
#ifdef Libburn_if_this_was_linuX
|
|
||||||
|
|
||||||
} else if(S_ISBLK(stbuf.st_mode)) {
|
|
||||||
int open_mode = O_RDWR, fd, ret;
|
|
||||||
long blocks;
|
|
||||||
|
|
||||||
blocks = *bytes / 512;
|
|
||||||
if(burn_sg_open_o_excl)
|
|
||||||
open_mode |= O_EXCL;
|
|
||||||
fd = open(path, open_mode);
|
|
||||||
if (fd == -1)
|
|
||||||
{ret = -2; goto ex;}
|
|
||||||
ret = ioctl(fd, BLKGETSIZE, &blocks);
|
|
||||||
close(fd);
|
|
||||||
if (ret == -1)
|
|
||||||
{ret = -2; goto ex;}
|
|
||||||
*bytes = ((off_t) blocks) * (off_t) 512;
|
|
||||||
|
|
||||||
#endif /* Libburn_if_this_was_linuX */
|
|
||||||
|
|
||||||
|
|
||||||
} else if(S_ISCHR(stbuf.st_mode)) {
|
|
||||||
fd = open(path, O_RDONLY);
|
|
||||||
if (fd == -1)
|
|
||||||
{ret = -2; goto ex;}
|
|
||||||
ret = ioctl(fd, DIOCGMEDIASIZE, &add_size);
|
|
||||||
close(fd);
|
|
||||||
if (ret == -1)
|
|
||||||
{ret = -2; goto ex;}
|
|
||||||
*bytes = add_size;
|
|
||||||
} else if(S_ISREG(stbuf.st_mode)) {
|
|
||||||
add_size = burn_sparse_file_addsize(write_start, &stbuf);
|
|
||||||
strcpy(testpath, path);
|
|
||||||
} else
|
|
||||||
{ret = 0; goto ex;}
|
|
||||||
|
|
||||||
if (testpath[0]) {
|
|
||||||
if (statvfs(testpath, &vfsbuf) == -1)
|
|
||||||
{ret = -2; goto ex;}
|
|
||||||
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
|
|
||||||
(off_t) vfsbuf.f_bavail;
|
|
||||||
}
|
|
||||||
ret = 1;
|
|
||||||
ex:
|
|
||||||
BURN_FREE_MEM(testpath);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
|
|
||||||
|
|
||||||
#ifdef Libburn_read_o_direcT
|
|
||||||
|
|
||||||
/* No special O_DIRECT-like precautions are implemented here */
|
|
||||||
|
|
||||||
#endif /* Libburn_read_o_direcT */
|
|
||||||
|
|
||||||
|
|
||||||
int burn_os_open_track_src(char *path, int open_flags, int flag)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
fd = open(path, open_flags);
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *burn_os_alloc_buffer(size_t amount, int flag)
|
|
||||||
{
|
|
||||||
void *buf = NULL;
|
|
||||||
|
|
||||||
buf = calloc(1, amount);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
|
|
||||||
{
|
|
||||||
if (buffer == NULL)
|
|
||||||
return 0;
|
|
||||||
free(buffer);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
1181
libburn/sg-freebsd.c
1181
libburn/sg-freebsd.c
File diff suppressed because it is too large
Load Diff
1019
libburn/sg-libcdio.c
1019
libburn/sg-libcdio.c
File diff suppressed because it is too large
Load Diff
2653
libburn/sg-linux.c
2653
libburn/sg-linux.c
File diff suppressed because it is too large
Load Diff
@ -1,916 +0,0 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright (c) 2010 - 2016 Thomas Schmitt <scdbackup@gmx.net>
|
|
||||||
Provided under GPL version 2 or later.
|
|
||||||
|
|
||||||
Derived 2014 from libburn/sg-solaris.c with information learned from
|
|
||||||
dvd+rw-tools, http://fxr.watson.org/fxr/source/sys/scsiio.h?v=NETBSD,
|
|
||||||
http://netbsd.gw.com/cgi-bin/man-cgi?scsi+4+NetBSD-current,
|
|
||||||
and experiments made by Freddy Fisker.
|
|
||||||
Adapted 2016 to OpenBSD by help of SASANO Takayoshi <uaa@mx5.nisiq.net>.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
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: NetBSD 6, ioctl SCIOCCOMMAND
|
|
||||||
OpenBSD 5.9, ioctl SCIOCCOMMAND
|
|
||||||
|
|
||||||
PORTING:
|
|
||||||
|
|
||||||
Porting libburn typically will consist of adding a new operating system case
|
|
||||||
to the following switcher files:
|
|
||||||
os.h Operating system specific libburn definitions and declarations.
|
|
||||||
sg.c Operating system dependent transport level modules.
|
|
||||||
and of deriving the following system specific files from existing examples:
|
|
||||||
os-*.h Included by os.h. You will need some general system knowledge
|
|
||||||
about signals and knowledge about the storage object needs of your
|
|
||||||
transport level module sg-*.c.
|
|
||||||
|
|
||||||
sg-*.c This source module. You will need special system knowledge about
|
|
||||||
how to detect all potentially available drives, how to open them,
|
|
||||||
eventually how to exclusively reserve them, how to perform
|
|
||||||
SCSI transactions, how to inquire the (pseudo-)SCSI driver.
|
|
||||||
You will not need to care about CD burning, MMC or other high-level
|
|
||||||
SCSI aspects.
|
|
||||||
|
|
||||||
Said sg-*.c operations are defined by a public function interface, which has
|
|
||||||
to be implemented in a way that provides libburn with the desired services:
|
|
||||||
|
|
||||||
sg_id_string() returns an id string of the SCSI transport adapter.
|
|
||||||
It may be called before initialization but then may
|
|
||||||
return only a preliminary id.
|
|
||||||
|
|
||||||
sg_initialize() performs global initialization of the SCSI transport
|
|
||||||
adapter and eventually needed operating system
|
|
||||||
facilities. Checks for compatibility of supporting
|
|
||||||
software components.
|
|
||||||
|
|
||||||
sg_shutdown() performs global finalizations and releases globally
|
|
||||||
acquired resources.
|
|
||||||
|
|
||||||
sg_give_next_adr() iterates over the set of potentially useful drive
|
|
||||||
address strings.
|
|
||||||
|
|
||||||
scsi_enumerate_drives() brings all available, not-whitelist-banned, and
|
|
||||||
accessible drives into libburn's list of drives.
|
|
||||||
|
|
||||||
sg_dispose_drive() finalizes adapter specifics of struct burn_drive
|
|
||||||
on destruction. Releases resources which were acquired
|
|
||||||
underneath scsi_enumerate_drives().
|
|
||||||
|
|
||||||
sg_drive_is_open() tells whether 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 whether the command succeeded or shall
|
|
||||||
be retried or finally failed.
|
|
||||||
|
|
||||||
sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
|
|
||||||
|
|
||||||
|
|
||||||
burn_os_is_2k_seekrw() tells whether the given path leads to a file object
|
|
||||||
that can be used in 2 kB granularity by lseek(2),
|
|
||||||
read(2), and possibly write(2) if not read-only..
|
|
||||||
E.g. a USB stick or a hard disk.
|
|
||||||
|
|
||||||
burn_os_stdio_capacity() estimates the emulated media space of stdio-drives.
|
|
||||||
|
|
||||||
burn_os_open_track_src() opens a disk file in a way that offers best
|
|
||||||
throughput with file reading and/or SCSI write command
|
|
||||||
transmission.
|
|
||||||
|
|
||||||
burn_os_alloc_buffer() allocates a memory area that is suitable for file
|
|
||||||
descriptors issued by burn_os_open_track_src().
|
|
||||||
The buffer size may be rounded up for alignment
|
|
||||||
reasons.
|
|
||||||
|
|
||||||
burn_os_free_buffer() delete a buffer obtained by burn_os_alloc_buffer().
|
|
||||||
|
|
||||||
Porting hints are marked by the text "PORTING:".
|
|
||||||
Send feedback to libburn-hackers@pykix.org .
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** PORTING : ------- OS dependent headers and definitions ------ */
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#ifdef Libburn_os_has_statvfS
|
|
||||||
#include <sys/statvfs.h>
|
|
||||||
#endif /* Libburn_os_has_stavtfS */
|
|
||||||
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/scsiio.h>
|
|
||||||
|
|
||||||
|
|
||||||
/** PORTING : ------ libburn portable headers and definitions ----- */
|
|
||||||
|
|
||||||
#include "transport.h"
|
|
||||||
#include "drive.h"
|
|
||||||
#include "sg.h"
|
|
||||||
#include "spc.h"
|
|
||||||
#include "sbc.h"
|
|
||||||
#include "debug.h"
|
|
||||||
#include "toc.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "init.h"
|
|
||||||
|
|
||||||
#include "libdax_msgs.h"
|
|
||||||
extern struct libdax_msgs *libdax_messenger;
|
|
||||||
|
|
||||||
|
|
||||||
/* is in portable part of libburn */
|
|
||||||
int burn_drive_is_banned(char *device_address);
|
|
||||||
int burn_drive_resolve_link(char *path, char adr[],
|
|
||||||
int *recursion_count, int flag); /* drive.c */
|
|
||||||
|
|
||||||
/* Whether to log SCSI commands:
|
|
||||||
bit0= log in /tmp/libburn_sg_command_log
|
|
||||||
bit1= log to stderr
|
|
||||||
bit2= flush every line
|
|
||||||
*/
|
|
||||||
extern int burn_sg_log_scsi;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
/* PORTING: Private definitions. Port only if needed by public functions. */
|
|
||||||
/* (Public functions are listed below) */
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
|
|
||||||
/* Storage object is in libburn/init.c
|
|
||||||
whether to strive for exclusive access to the drive
|
|
||||||
*/
|
|
||||||
extern int burn_sg_open_o_excl;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
/* PORTING: Private functions. Port only if needed by public functions */
|
|
||||||
/* (Public functions are listed below) */
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
static int sg_close_drive(struct burn_drive * d)
|
|
||||||
{
|
|
||||||
if (d->fd != -1) {
|
|
||||||
close(d->fd);
|
|
||||||
d->fd = -1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* PORTING: Private functions which contain publicly needed functionality. */
|
|
||||||
/* Their portable part must be performed. So it is probably best */
|
|
||||||
/* to replace the non-portable part and to call these functions */
|
|
||||||
/* in your port, too. */
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
|
|
||||||
/** Wraps a detected drive into libburn structures and hands it over to
|
|
||||||
libburn drive list.
|
|
||||||
*/
|
|
||||||
static void enumerate_common(char *fname,
|
|
||||||
int bus_no, int host_no,
|
|
||||||
int channel_no, int target_no, int lun_no)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
struct burn_drive out;
|
|
||||||
|
|
||||||
/* General libburn drive setup */
|
|
||||||
burn_setup_drive(&out, fname);
|
|
||||||
|
|
||||||
/* This transport adapter uses SCSI-family commands and models
|
|
||||||
(seems the adapter would know better than its boss, if ever) */
|
|
||||||
ret = burn_scsi_setup_drive(&out, bus_no, host_no, channel_no,
|
|
||||||
target_no, lun_no, 0);
|
|
||||||
if (ret <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* PORTING: ------------------- non portable part --------------- */
|
|
||||||
|
|
||||||
/* Transport adapter is NetBSD/OpenBSD ioctl SCIOCCOMMAND */
|
|
||||||
/* Adapter specific handles and data */
|
|
||||||
|
|
||||||
out.fd = -1;
|
|
||||||
|
|
||||||
/* PORTING: ---------------- end of non portable part ------------ */
|
|
||||||
|
|
||||||
/* Adapter specific functions with standardized names */
|
|
||||||
out.grab = sg_grab;
|
|
||||||
out.release = sg_release;
|
|
||||||
out.drive_is_open = sg_drive_is_open;
|
|
||||||
out.issue_command = sg_issue_command;
|
|
||||||
/* Finally register drive and inquire drive information */
|
|
||||||
burn_drive_finish_enum(&out);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int start_enum_rcdNx(burn_drive_enumerator_t *idx, int flag)
|
|
||||||
{
|
|
||||||
idx->cdno = -1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Trying /dev/rcd[0..63][dc] */
|
|
||||||
#define Libburn_netbsd_max_cdnuM 63
|
|
||||||
|
|
||||||
static int next_enum_rcdNx(burn_drive_enumerator_t *idx,
|
|
||||||
char adr[], int adr_size, int flag)
|
|
||||||
{
|
|
||||||
static char suffix[2] = {'d', 'c'};
|
|
||||||
struct stat stbuf;
|
|
||||||
int i, stat_ret;
|
|
||||||
char path[16];
|
|
||||||
|
|
||||||
while (idx->cdno < Libburn_netbsd_max_cdnuM) {
|
|
||||||
idx->cdno++;
|
|
||||||
for (i = 0; i < 2; i++) {
|
|
||||||
sprintf(path, "/dev/rcd%d%c", idx->cdno, suffix[i]);
|
|
||||||
stat_ret = stat(path, &stbuf);
|
|
||||||
if (stat_ret == -1)
|
|
||||||
continue;
|
|
||||||
if (!S_ISCHR(stbuf.st_mode))
|
|
||||||
continue;
|
|
||||||
if ((int) strlen(path) >= adr_size)
|
|
||||||
continue;
|
|
||||||
strcpy(adr, path);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Searching the first byte address that cannot be lseeked and read
|
|
||||||
*/
|
|
||||||
static int guess_size_by_seek_set(int fd, off_t *bytes, int flag)
|
|
||||||
{
|
|
||||||
static off_t abs_limit = ((off_t) 1024) * 1024 * 1024 * 1024 * 1024;
|
|
||||||
off_t i, step = ((off_t) 1024) * 1024 * 1024 * 1024, ret;
|
|
||||||
char buf[1];
|
|
||||||
|
|
||||||
*bytes = 0;
|
|
||||||
for (i = step; i < abs_limit; i += step) {
|
|
||||||
ret = lseek(fd, i, SEEK_SET);
|
|
||||||
if (ret == -1) {
|
|
||||||
i -= step;
|
|
||||||
step = step >> 1;
|
|
||||||
if (step > 0)
|
|
||||||
continue;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
ret = read(fd, buf, 1);
|
|
||||||
if (ret == -1) {
|
|
||||||
i -= step;
|
|
||||||
step = step >> 1;
|
|
||||||
if (step > 0)
|
|
||||||
continue;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
*bytes = i + 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
/* PORTING: Public functions. These MUST be ported. */
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
|
|
||||||
/** Returns the id string of the SCSI transport adapter and eventually
|
|
||||||
needed operating system facilities.
|
|
||||||
This call is usable even if sg_initialize() was not called yet. In that
|
|
||||||
case a preliminary constant message might be issued if detailed info is
|
|
||||||
not available yet.
|
|
||||||
@param msg returns id string
|
|
||||||
@param flag unused yet, submit 0
|
|
||||||
@return 1 = success, <=0 = failure
|
|
||||||
*/
|
|
||||||
int sg_id_string(char msg[1024], int flag)
|
|
||||||
{
|
|
||||||
#ifdef __OpenBSD__
|
|
||||||
sprintf(msg, "internal OpenBSD SCIOCCOMMAND adapter sg-netbsd");
|
|
||||||
#else
|
|
||||||
sprintf(msg, "internal NetBSD SCIOCCOMMAND adapter sg-netbsd");
|
|
||||||
#endif
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Performs global initialization of the SCSI transport adapter and eventually
|
|
||||||
needed operating system facilities. Checks for compatibility of supporting
|
|
||||||
software components.
|
|
||||||
@param msg returns ids and/or error messages of eventual helpers
|
|
||||||
@param flag unused yet, submit 0
|
|
||||||
@return 1 = success, <=0 = failure
|
|
||||||
*/
|
|
||||||
int sg_initialize(char msg[1024], int flag)
|
|
||||||
{
|
|
||||||
return sg_id_string(msg, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Performs global finalization of the SCSI transport adapter and eventually
|
|
||||||
needed operating system facilities. Releases globally acquired resources.
|
|
||||||
@param flag unused yet, submit 0
|
|
||||||
@return 1 = success, <=0 = failure
|
|
||||||
*/
|
|
||||||
int sg_shutdown(int flag)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
|
|
||||||
struct burn_drive which are defined in os-*.h.
|
|
||||||
The eventual initialization of those components was made underneath
|
|
||||||
scsi_enumerate_drives().
|
|
||||||
This will be called when a burn_drive gets disposed.
|
|
||||||
@param d the drive to be finalized
|
|
||||||
@param flag unused yet, submit 0
|
|
||||||
@return 1 = success, <=0 = failure
|
|
||||||
*/
|
|
||||||
int sg_dispose_drive(struct burn_drive *d, int flag)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Returns the next index number and the next enumerated drive address.
|
|
||||||
The enumeration has to cover all available and accessible drives. It is
|
|
||||||
allowed to return addresses of drives which are not available but under
|
|
||||||
some (even exotic) circumstances could be available. It is on the other
|
|
||||||
hand allowed, only to hand out addresses which can really be used right
|
|
||||||
in the moment of this call. (This implementation chooses the 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)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (initialize == 1) {
|
|
||||||
ret = start_enum_rcdNx(idx, 0);
|
|
||||||
if (ret <= 0)
|
|
||||||
return ret;
|
|
||||||
} else if (initialize == -1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ret = next_enum_rcdNx(idx, adr, adr_size, 0);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Brings all available, not-whitelist-banned, and accessible drives into
|
|
||||||
libburn's list of drives.
|
|
||||||
*/
|
|
||||||
int scsi_enumerate_drives(void)
|
|
||||||
{
|
|
||||||
burn_drive_enumerator_t idx;
|
|
||||||
int initialize = 1, ret, i_bus_no = -1, buf_size = 4096;
|
|
||||||
int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
|
|
||||||
char *buf = NULL;
|
|
||||||
|
|
||||||
BURN_ALLOC_MEM(buf, char, buf_size);
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
ret = sg_give_next_adr(&idx, buf, buf_size, initialize);
|
|
||||||
initialize = 0;
|
|
||||||
if (ret <= 0)
|
|
||||||
break;
|
|
||||||
if (burn_drive_is_banned(buf))
|
|
||||||
continue;
|
|
||||||
sg_obtain_scsi_adr(buf, &i_bus_no, &i_host_no,
|
|
||||||
&i_channel_no, &i_target_no, &i_lun_no);
|
|
||||||
enumerate_common(buf,
|
|
||||||
i_bus_no, i_host_no, i_channel_no,
|
|
||||||
i_target_no, i_lun_no);
|
|
||||||
}
|
|
||||||
sg_give_next_adr(&idx, buf, buf_size, -1);
|
|
||||||
ret = 1;
|
|
||||||
ex:;
|
|
||||||
BURN_FREE_MEM(buf);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Tells whether libburn has the given drive in use or exclusively reserved.
|
|
||||||
If it is "open" then libburn will eventually call sg_release() on it when
|
|
||||||
it is time to give up usage and reservation.
|
|
||||||
*/
|
|
||||||
/** Published as burn_drive.drive_is_open() */
|
|
||||||
int sg_drive_is_open(struct burn_drive * d)
|
|
||||||
{
|
|
||||||
return (d->fd != -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Opens the drive for SCSI commands and - if burn activities are prone
|
|
||||||
to external interference on your system - obtains an exclusive access lock
|
|
||||||
on the drive. (Note: this is not physical tray locking.)
|
|
||||||
A drive that has been opened with sg_grab() will eventually be handed
|
|
||||||
over to sg_release() for closing and unreserving.
|
|
||||||
*/
|
|
||||||
int sg_grab(struct burn_drive *d)
|
|
||||||
{
|
|
||||||
char *msg = NULL;
|
|
||||||
int os_errno, ret;
|
|
||||||
|
|
||||||
BURN_ALLOC_MEM(msg, char, 4096);
|
|
||||||
|
|
||||||
if (d->fd != -1) {
|
|
||||||
d->released = 0;
|
|
||||||
{ret = 1; goto ex;}
|
|
||||||
}
|
|
||||||
d->fd = open(d->devname, O_RDWR | O_NDELAY);
|
|
||||||
if (d->fd == -1) {
|
|
||||||
os_errno = errno;
|
|
||||||
sprintf(msg, "Could not grab drive '%s'", d->devname);
|
|
||||||
/* (errno == ENXIO is a device file with no drive attached) */
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x00020003,
|
|
||||||
errno == ENXIO ? LIBDAX_MSGS_SEV_DEBUG :
|
|
||||||
LIBDAX_MSGS_SEV_SORRY,
|
|
||||||
LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, os_errno, 0);
|
|
||||||
{ret = 0; goto ex;}
|
|
||||||
}
|
|
||||||
|
|
||||||
d->released = 0;
|
|
||||||
|
|
||||||
/* Make sure by INQUIRY that this is really a MMC drive */
|
|
||||||
ret = spc_confirm_cd_drive(d, 0);
|
|
||||||
if (ret <= 0)
|
|
||||||
goto revoke;
|
|
||||||
|
|
||||||
/* # define Libburn_sg_netbsd_scsi_debuG */
|
|
||||||
#ifdef Libburn_sg_netbsd_scsi_debuG
|
|
||||||
{
|
|
||||||
static int sc_db = SC_DB_CMDS | SC_DB_FLOW;
|
|
||||||
|
|
||||||
ret = ioctl(d->fd, SCIOCDEBUG, &sc_db);
|
|
||||||
if (ret == -1)
|
|
||||||
fprintf(stderr,
|
|
||||||
"libburn_DEBUG: ioctl(%d, SCIOCDEBUG, &(0x%X)) returns %d, errno = %d\n",
|
|
||||||
d->fd, (unsigned int) sc_db, ret, errno);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
{ret = 1; goto ex;}
|
|
||||||
|
|
||||||
revoke:;
|
|
||||||
sprintf(msg, "Could not grab drive '%s'.", d->devname);
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x00020003,
|
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, 0, 0);
|
|
||||||
if (d->fd >= 0) {
|
|
||||||
close(d->fd);
|
|
||||||
d->fd = -1;
|
|
||||||
d->released = 1;
|
|
||||||
}
|
|
||||||
ret = 0;
|
|
||||||
ex:;
|
|
||||||
BURN_FREE_MEM(msg);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** PORTING: Is mainly about the call to sg_close_drive() and whether it
|
|
||||||
implements the demanded functionality.
|
|
||||||
*/
|
|
||||||
/** Gives up the drive for SCSI commands and releases eventual access locks.
|
|
||||||
(Note: this is not physical tray locking.)
|
|
||||||
*/
|
|
||||||
int sg_release(struct burn_drive *d)
|
|
||||||
{
|
|
||||||
if (d->fd < 0)
|
|
||||||
return 0;
|
|
||||||
sg_close_drive(d);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Sends a SCSI command to the drive, receives reply and evaluates whether
|
|
||||||
the command succeeded or shall be retried or finally failed.
|
|
||||||
Returned SCSI errors shall not lead to a return value indicating failure.
|
|
||||||
The callers get notified by c->error. An SCSI failure which leads not to
|
|
||||||
a retry shall be notified via scsi_notify_error().
|
|
||||||
The Libburn_log_sg_commandS facility might be of help when problems with
|
|
||||||
a drive have to be examined. It shall stay disabled for normal use.
|
|
||||||
@return: 1 success , <=0 failure
|
|
||||||
*/
|
|
||||||
int sg_issue_command(struct burn_drive *d, struct command *c)
|
|
||||||
{
|
|
||||||
int i, timeout_ms, ret, key, asc, ascq, done = 0, sense_len, max_sl;
|
|
||||||
time_t start_time;
|
|
||||||
scsireq_t req;
|
|
||||||
char msg[160];
|
|
||||||
static FILE *fp = NULL;
|
|
||||||
|
|
||||||
c->error = 0;
|
|
||||||
|
|
||||||
if (d->fd == -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (burn_sg_log_scsi & 1) {
|
|
||||||
if (fp == NULL) {
|
|
||||||
fp= fopen("/tmp/libburn_sg_command_log", "a");
|
|
||||||
fprintf(fp,
|
|
||||||
"\n-----------------------------------------\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (burn_sg_log_scsi & 3)
|
|
||||||
scsi_log_cmd(c,fp,0);
|
|
||||||
|
|
||||||
if (c->timeout > 0)
|
|
||||||
timeout_ms = c->timeout;
|
|
||||||
else
|
|
||||||
timeout_ms = 200000;
|
|
||||||
|
|
||||||
memset (&req, 0, sizeof(req));
|
|
||||||
memcpy(req.cmd, c->opcode, c->oplen);
|
|
||||||
req.cmdlen = c->oplen;
|
|
||||||
req.databuf = (caddr_t) c->page->data;
|
|
||||||
req.flags = SCCMD_ESCAPE; /* probably to make req.cmdlen significant */
|
|
||||||
req.timeout = timeout_ms;
|
|
||||||
max_sl = sizeof(c->sense) > SENSEBUFLEN ?
|
|
||||||
SENSEBUFLEN : sizeof(c->sense);
|
|
||||||
req.senselen = max_sl;
|
|
||||||
if (c->dir == TO_DRIVE) {
|
|
||||||
req.datalen = c->page->bytes;
|
|
||||||
req.flags |= SCCMD_WRITE;
|
|
||||||
} else if (c->dir == FROM_DRIVE) {
|
|
||||||
req.flags |= SCCMD_READ;
|
|
||||||
if (c->dxfer_len >= 0)
|
|
||||||
req.datalen = c->dxfer_len;
|
|
||||||
else
|
|
||||||
req.datalen = BUFFER_SIZE;
|
|
||||||
/* touch page so we can use valgrind */
|
|
||||||
memset(c->page->data, 0, BUFFER_SIZE);
|
|
||||||
} else {
|
|
||||||
req.flags |= SCCMD_READ;
|
|
||||||
req.datalen = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ts B90523 : Record effective transfer length request for debugging*/
|
|
||||||
c->dxfer_len = req.datalen;
|
|
||||||
|
|
||||||
/* retry-loop */
|
|
||||||
start_time = time(NULL);
|
|
||||||
for(i = 0; !done; i++) {
|
|
||||||
memset(c->sense, 0, sizeof(c->sense));
|
|
||||||
c->start_time = burn_get_time(0);
|
|
||||||
|
|
||||||
ret = ioctl(d->fd, SCIOCCOMMAND, &req);
|
|
||||||
|
|
||||||
/* <<< Fault mock-up
|
|
||||||
if (c->opcode[0] == 0x28) {
|
|
||||||
ret = -1;
|
|
||||||
errno = 9;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
c->end_time = burn_get_time(0);
|
|
||||||
|
|
||||||
/* #define Libburn_debug_sg_netbsD */
|
|
||||||
#ifdef Libburn_debug_sg_netbsD
|
|
||||||
fprintf(stderr, "libburn_DEBUG: ret= %d, retsts = 0x%X, senselen_used = %d, status = 0x%X, error= 0x%X\n", ret, (unsigned int) req.retsts, (int) req.senselen_used, (unsigned int) req.status, req.error);
|
|
||||||
fprintf(stderr, "libburn_DEBUG: datalen_used = %u\n",
|
|
||||||
(unsigned int) req.datalen_used);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ret != 0 ||
|
|
||||||
(req.retsts != SCCMD_SENSE && req.retsts != SCCMD_OK)) {
|
|
||||||
sprintf(msg, "Failed to transfer command to drive. (ioctl(%d, SCIOCCOMMAND) = %d, scsireq_t.retsts = 0x%X, errno= %d)",
|
|
||||||
d->fd, ret, (unsigned int) req.retsts, errno);
|
|
||||||
if (burn_sg_log_scsi & 3)
|
|
||||||
scsi_log_message(d, fp, msg, 0);
|
|
||||||
libdax_msgs_submit(libdax_messenger,
|
|
||||||
d->global_index, 0x0002010c,
|
|
||||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, errno, 0);
|
|
||||||
sg_close_drive(d);
|
|
||||||
d->released = 1;
|
|
||||||
d->busy = BURN_DRIVE_IDLE;
|
|
||||||
c->error = 1;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sense_len = 0;
|
|
||||||
if (req.retsts == SCCMD_SENSE) {
|
|
||||||
memcpy(c->sense, req.sense, max_sl);
|
|
||||||
sense_len = req.senselen > max_sl ?
|
|
||||||
max_sl : req.senselen;
|
|
||||||
}
|
|
||||||
spc_decode_sense(c->sense, sense_len, &key, &asc, &ascq);
|
|
||||||
if (key || asc || ascq)
|
|
||||||
sense_len = req.senselen;
|
|
||||||
else
|
|
||||||
sense_len = 0;
|
|
||||||
|
|
||||||
/* <<< Fault mock-up
|
|
||||||
if (c->opcode[0] == 0x5a) {
|
|
||||||
req.datalen_used = 0;
|
|
||||||
memset(c->page->data, 0, BUFFER_SIZE);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (c->dir == FROM_DRIVE && sense_len == 0 &&
|
|
||||||
req.datalen > 0 && req.datalen_used < req.datalen) {
|
|
||||||
sprintf(msg, "Short reply from SCSI command %2.2X: expected: %d, got: %d, req.retsts: 0x%X",
|
|
||||||
(unsigned int) c->opcode[0],
|
|
||||||
(int) req.datalen, (int) req.datalen_used,
|
|
||||||
(unsigned int) req.retsts);
|
|
||||||
if (burn_sg_log_scsi & 3)
|
|
||||||
scsi_log_message(d, fp, msg, 0);
|
|
||||||
libdax_msgs_submit(libdax_messenger,
|
|
||||||
d->global_index, 0x00000002,
|
|
||||||
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, 0, 0);
|
|
||||||
if (req.datalen_used == 0)
|
|
||||||
c->error = 1;
|
|
||||||
c->dxfer_len = req.datalen_used;
|
|
||||||
}
|
|
||||||
|
|
||||||
done = scsi_eval_cmd_outcome(d, c, fp, c->sense, sense_len,
|
|
||||||
start_time, timeout_ms, i, 0);
|
|
||||||
if (d->cancel)
|
|
||||||
done = 1;
|
|
||||||
if (!done)
|
|
||||||
spc_register_retry(c);
|
|
||||||
} /* end of retry-loop */
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Tries to obtain SCSI address parameters.
|
|
||||||
@return 1 is success , 0 is failure
|
|
||||||
*/
|
|
||||||
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
|
|
||||||
int *target_no, int *lun_no)
|
|
||||||
{
|
|
||||||
int ret, fd = -1;
|
|
||||||
struct scsi_addr addr;
|
|
||||||
|
|
||||||
fd = open(path, O_RDWR | O_NDELAY);
|
|
||||||
if (fd == -1)
|
|
||||||
return 0;
|
|
||||||
*bus_no = *host_no = *channel_no = *target_no = *lun_no = 0;
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
|
||||||
ret = ioctl(fd, SCIOCIDENTIFY, &addr);
|
|
||||||
if (ret != 0)
|
|
||||||
{ret = 0; goto ex;}
|
|
||||||
if (addr.type != TYPE_SCSI)
|
|
||||||
{ret = 0; goto ex;}
|
|
||||||
|
|
||||||
#ifdef __OpenBSD__
|
|
||||||
|
|
||||||
*bus_no = *host_no = addr.scbus;
|
|
||||||
*target_no = addr.target;
|
|
||||||
*lun_no = addr.lun;
|
|
||||||
|
|
||||||
#else /* __OpenBSD__ */
|
|
||||||
|
|
||||||
*bus_no = *host_no = addr.addr.scsi.scbus;
|
|
||||||
*target_no = addr.addr.scsi.target;
|
|
||||||
*lun_no = addr.addr.scsi.lun;
|
|
||||||
|
|
||||||
#endif /* ! __OpenBSD__ */
|
|
||||||
|
|
||||||
ret = 1;
|
|
||||||
ex:;
|
|
||||||
if (fd != -1)
|
|
||||||
close(fd);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Tells whether a text is a persistent address as listed by the enumeration
|
|
||||||
functions.
|
|
||||||
*/
|
|
||||||
int sg_is_enumerable_adr(char* adr)
|
|
||||||
{
|
|
||||||
burn_drive_enumerator_t idx;
|
|
||||||
int initialize = 1, ret;
|
|
||||||
char buf[64];
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
|
|
||||||
initialize = 0;
|
|
||||||
if (ret <= 0)
|
|
||||||
break;
|
|
||||||
if (strcmp(adr, buf) == 0) {
|
|
||||||
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Return 1 if the given path leads to a regular file or a device that can be
|
|
||||||
fseeked, read, and possibly written with 2 kB granularity.
|
|
||||||
*/
|
|
||||||
int burn_os_is_2k_seekrw(char *path, int flag)
|
|
||||||
{
|
|
||||||
struct stat stbuf;
|
|
||||||
int l, i, dev, tl;
|
|
||||||
char try[16];
|
|
||||||
|
|
||||||
/* >>> ??? Is this a comprehensive list of lseek()-capable devices ? */
|
|
||||||
/* http://www.netbsd.org/docs/guide/en/chap-rmmedia.html */
|
|
||||||
static char dev_names[][4] = {
|
|
||||||
"fd", "rfd", "sd" , "cd", "rcd", "wd", ""};
|
|
||||||
|
|
||||||
if (path[0] == 0)
|
|
||||||
return 0;
|
|
||||||
if (stat(path, &stbuf) == -1)
|
|
||||||
return 0;
|
|
||||||
if (S_ISREG(stbuf.st_mode))
|
|
||||||
return 1;
|
|
||||||
if (S_ISBLK(stbuf.st_mode))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* Look for known device names which promise the desired capabilities */
|
|
||||||
if (strncmp(path, "/dev/", 5) != 0)
|
|
||||||
return 0;
|
|
||||||
l = strlen(path);
|
|
||||||
for (dev = 0; dev_names[dev][0] != 0; dev++) {
|
|
||||||
sprintf(try, "/dev/%s", dev_names[dev]);
|
|
||||||
tl = strlen(try);
|
|
||||||
if (strncmp(path, try, tl) != 0)
|
|
||||||
continue;
|
|
||||||
l -= tl;
|
|
||||||
for (i = 0; i < Libburn_netbsd_max_cdnuM; i++) {
|
|
||||||
sprintf(try + tl, "%d", i);
|
|
||||||
if (strncmp(path, try, strlen(try)) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i >= Libburn_netbsd_max_cdnuM)
|
|
||||||
continue;
|
|
||||||
tl += strlen(try + tl);
|
|
||||||
if (l == tl)
|
|
||||||
return 1;
|
|
||||||
if (l > tl + 1)
|
|
||||||
continue;
|
|
||||||
if (path[l - 1] >= 'a' && path[l - 1] <= 'z')
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Estimate the potential payload capacity of a file address.
|
|
||||||
@param path The address of the file to be examined. If it does not
|
|
||||||
exist yet, then the directory will be inquired.
|
|
||||||
@param bytes The pointed value gets modified, but only if an estimation is
|
|
||||||
possible.
|
|
||||||
@return -2 = cannot perform necessary operations on file object
|
|
||||||
-1 = neither path nor dirname of path exist
|
|
||||||
0 = could not estimate size capacity of file object
|
|
||||||
1 = estimation has been made, bytes was set
|
|
||||||
*/
|
|
||||||
int burn_os_stdio_capacity(char *path, off_t write_start, off_t *bytes)
|
|
||||||
{
|
|
||||||
struct stat stbuf;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
#ifdef Libburn_os_has_statvfS
|
|
||||||
struct statvfs vfsbuf;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char *testpath = NULL, *cpt;
|
|
||||||
off_t add_size = 0;
|
|
||||||
|
|
||||||
BURN_ALLOC_MEM(testpath, char, 4096);
|
|
||||||
|
|
||||||
testpath[0] = 0;
|
|
||||||
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)
|
|
||||||
{ret = -1; goto ex;}
|
|
||||||
|
|
||||||
} else if(S_ISBLK(stbuf.st_mode)) {
|
|
||||||
int open_mode = O_RDONLY, fd;
|
|
||||||
|
|
||||||
fd = open(path, open_mode);
|
|
||||||
if (fd == -1)
|
|
||||||
{ret = -2; goto ex;}
|
|
||||||
*bytes = lseek(fd, 0, SEEK_END);
|
|
||||||
if (*bytes <= 0)
|
|
||||||
guess_size_by_seek_set(fd, bytes, 0);
|
|
||||||
close(fd);
|
|
||||||
if (*bytes == -1) {
|
|
||||||
*bytes = 0;
|
|
||||||
{ret = 0; goto ex;}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if(S_ISREG(stbuf.st_mode)) {
|
|
||||||
add_size = burn_sparse_file_addsize(write_start, &stbuf);
|
|
||||||
strcpy(testpath, path);
|
|
||||||
} else
|
|
||||||
{ret = 0; goto ex;}
|
|
||||||
|
|
||||||
if (testpath[0]) {
|
|
||||||
|
|
||||||
#ifdef Libburn_os_has_statvfS
|
|
||||||
|
|
||||||
if (statvfs(testpath, &vfsbuf) == -1)
|
|
||||||
{ret = -2; goto ex;}
|
|
||||||
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
|
|
||||||
(off_t) vfsbuf.f_bavail;
|
|
||||||
|
|
||||||
#else /* Libburn_os_has_statvfS */
|
|
||||||
|
|
||||||
{ret = 0; goto ex;}
|
|
||||||
|
|
||||||
#endif /* ! Libburn_os_has_stavtfS */
|
|
||||||
|
|
||||||
}
|
|
||||||
ret = 1;
|
|
||||||
ex:;
|
|
||||||
BURN_FREE_MEM(testpath);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
|
|
||||||
|
|
||||||
#ifdef Libburn_read_o_direcT
|
|
||||||
|
|
||||||
/* No special O_DIRECT-like precautions are implemented here */
|
|
||||||
|
|
||||||
#endif /* Libburn_read_o_direcT */
|
|
||||||
|
|
||||||
|
|
||||||
int burn_os_open_track_src(char *path, int open_flags, int flag)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
fd = open(path, open_flags);
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *burn_os_alloc_buffer(size_t amount, int flag)
|
|
||||||
{
|
|
||||||
void *buf = NULL;
|
|
||||||
|
|
||||||
buf = calloc(1, amount);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
|
|
||||||
{
|
|
||||||
if (buffer == NULL)
|
|
||||||
return 0;
|
|
||||||
free(buffer);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
1018
libburn/sg-solaris.c
1018
libburn/sg-solaris.c
File diff suppressed because it is too large
Load Diff
93
libburn/sg.c
93
libburn/sg.c
@ -1,93 +0,0 @@
|
|||||||
|
|
||||||
/* sg.c
|
|
||||||
Switcher for operating system dependent transport level modules of libburn.
|
|
||||||
Copyright (C) 2009 - 2016 Thomas Schmitt <scdbackup@gmx.net>,
|
|
||||||
provided under GPLv2+
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../config.h"
|
|
||||||
#undef HAVE_CONFIG_H
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef Libburn_use_sg_dummY
|
|
||||||
|
|
||||||
#include "sg-dummy.c"
|
|
||||||
|
|
||||||
#else
|
|
||||||
#ifdef Libburn_use_libcdiO
|
|
||||||
|
|
||||||
#include "sg-libcdio.c"
|
|
||||||
|
|
||||||
#else
|
|
||||||
#ifdef __NetBSD__
|
|
||||||
|
|
||||||
#include "sg-netbsd.c"
|
|
||||||
|
|
||||||
#else
|
|
||||||
#ifdef __OpenBSD__
|
|
||||||
|
|
||||||
#include "sg-netbsd.c"
|
|
||||||
|
|
||||||
#else
|
|
||||||
#ifdef __FreeBSD__
|
|
||||||
|
|
||||||
#ifdef Libburn_use_sg_freebsd_porT
|
|
||||||
#include "sg-freebsd-port.c"
|
|
||||||
#else
|
|
||||||
#include "sg-freebsd.c"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else
|
|
||||||
#ifdef __FreeBSD_kernel__
|
|
||||||
|
|
||||||
#ifdef Libburn_use_sg_freebsd_porT
|
|
||||||
#include "sg-freebsd-port.c"
|
|
||||||
#else
|
|
||||||
#include "sg-freebsd.c"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else
|
|
||||||
#ifdef __linux
|
|
||||||
|
|
||||||
#include "sg-linux.c"
|
|
||||||
|
|
||||||
#else
|
|
||||||
#ifdef __sun
|
|
||||||
|
|
||||||
#include "sg-solaris.c"
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* The dummy adapter formally fulfills the expectations of libburn towards
|
|
||||||
its SCSI command transport. It will show no drives and perform no SCSI
|
|
||||||
commands.
|
|
||||||
libburn will then be restricted to using its stdio pseudo drives.
|
|
||||||
*/
|
|
||||||
static int intentional_compiler_warning(void)
|
|
||||||
{
|
|
||||||
int INTENTIONAL_COMPILER_WARNING_;
|
|
||||||
int Cannot_recognize_supported_operating_system_;
|
|
||||||
int Like_GNU_Linux_or_FreeBSD_or_Solaris_or_NetBSD_;
|
|
||||||
int Have_to_use_dummy_MMC_transport_adapter_;
|
|
||||||
int This_libburn_will_not_be_able_to_operate_on_real_CD_drives;
|
|
||||||
int Have_to_use_dummy_MMC_transport_adapter;
|
|
||||||
int Like_GNU_Linux_or_FreeBSD_or_Solaris_or_NetBSD;
|
|
||||||
int Cannot_recognize_supported_operating_system;
|
|
||||||
int INTENTIONAL_COMPILER_WARNING;
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "sg-dummy.c"
|
|
||||||
|
|
||||||
#endif /* ! __sun */
|
|
||||||
#endif /* ! __linux */
|
|
||||||
#endif /* ! __FreeBSD_kernel__ */
|
|
||||||
#endif /* ! __FreeBSD__ */
|
|
||||||
#endif /* ! __OpenBSD__ */
|
|
||||||
#endif /* ! __NetBSD__ */
|
|
||||||
#endif /* ! Libburn_use_libcdiO */
|
|
||||||
#endif /* ! Libburn_use_sg_dummY */
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user