diff --git a/libisoburn/branches/ZeroThreeTwo/AUTHORS b/libisoburn/branches/ZeroThreeTwo/AUTHORS new file mode 100644 index 00000000..0547ea18 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/AUTHORS @@ -0,0 +1,3 @@ +Thomas Schmitt +Vreixo Formoso Lopes + diff --git a/libisoburn/branches/ZeroThreeTwo/CONTRIBUTORS b/libisoburn/branches/ZeroThreeTwo/CONTRIBUTORS new file mode 100644 index 00000000..e69de29b diff --git a/libisoburn/branches/ZeroThreeTwo/COPYING b/libisoburn/branches/ZeroThreeTwo/COPYING new file mode 100644 index 00000000..5a965fbc --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/COPYING @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/libisoburn/branches/ZeroThreeTwo/COPYRIGHT b/libisoburn/branches/ZeroThreeTwo/COPYRIGHT new file mode 100644 index 00000000..208ccb7e --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/COPYRIGHT @@ -0,0 +1,22 @@ +Mario Danic , +Vreixo Formoso +Thomas Schmitt +libisoburn is Copyright (C) 2007-2008 Vreixo Formoso, Thomas Schmitt +xorriso is Copyright (C) 2007-2008 Thomas Schmitt +libisofs (if included) is Copyright (C) 2007-2008 Vreixo Formoso, Mario Danic +libburn (if included) is Copyright (C) 2002-2006 Derek Foreman, Ben Jansens + and Copyright (C) 2006-2008 Mario Danic, Thomas Schmitt + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA diff --git a/libisoburn/branches/ZeroThreeTwo/INSTALL b/libisoburn/branches/ZeroThreeTwo/INSTALL new file mode 100644 index 00000000..a6580e5a --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/INSTALL @@ -0,0 +1,237 @@ + +See file README for libisoburn and xorriso specific installation instructions. +This file here is rather a manual for advanced usage of ./configure + +------------------------------------------------------------------- + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, +2006 Free Software Foundation, Inc. + +This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + +Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + +Some systems require unusual options for compilation or linking that the +`configure' script does not know about. Run `./configure --help' for +details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + +You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + +Installation Names +================== + +By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + +Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + +There may be some features `configure' cannot figure out automatically, +but needs to determine by the type of machine the package will run on. +Usually, assuming the package is built to be run on the _same_ +architectures, `configure' can figure that out, but if it prints a +message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + +If you want to set default values for `configure' scripts to share, you +can create a site shell script called `config.site' that gives default +values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + +Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + +`configure' recognizes the following options to control how it operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/libisoburn/branches/ZeroThreeTwo/Makefile.am b/libisoburn/branches/ZeroThreeTwo/Makefile.am new file mode 100644 index 00000000..9782ecc0 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/Makefile.am @@ -0,0 +1,167 @@ +pkgconfigdir=$(libdir)/pkgconfig +libincludedir=$(includedir)/libisoburn + +lib_LTLIBRARIES = libisoburn/libisoburn.la + +## ========================================================================= ## + +# Build libraries +libisoburn_libisoburn_la_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) +libisoburn_libisoburn_la_SOURCES = \ + libisoburn/burn_wrap.c \ + libisoburn/data_source.c \ + libisoburn/isoburn.c \ + libisoburn/isoburn.h \ + libisoburn/isofs_wrap.c \ + libisoburn/libisoburn.h \ + version.h + +libisoburn_libisoburn_la_LIBADD = \ + -lisofs \ + -lburn + +libinclude_HEADERS = \ + libisoburn/libisoburn.h + +## ========================================================================= ## + + +# This is the reference application of libisoburn. See man xorriso/xorriso.1 +# +bin_PROGRAMS = \ + xorriso/xorriso + +# This looks quite ugly with make install: xorriso.c is compiled twice again +# +# Trying to create a build timestamp file +# +# BUILT_SOURCES = xorriso/xorriso_buildstamp.h +# +# phony targets get rebuilt every time +# +# .PHONY: xorriso/xorriso_buildstamp.h +# xorriso/xorriso_buildstamp.h: +# date -u '+#define Xorriso_build_timestamP "%Y.%m.%d.%H%M%S"' >xorriso/xorriso_buildstamp.h +# cat xorriso/xorriso_buildstamp.h + +xorriso_xorriso_CPPFLAGS = -Ilibisoburn +xorriso_xorriso_CFLAGS = -DXorriso_with_maiN $(READLINE_DEF) +xorriso_xorriso_LDADD = libisoburn/libisoburn.la -lisofs -lburn $(THREAD_LIBS) +xorriso_xorriso_SOURCES = \ + xorriso/xorriso.h \ + xorriso/xorriso_private.h \ + xorriso/xorriso.c \ + xorriso/xorrisoburn.h \ + xorriso/xorrisoburn.c \ + xorriso/xorriso_timestamp.h \ + xorriso/xorriso_buildstamp.h + + +# Install symbolic links to the xorriso binary +# +install-exec-hook: + if test -e "$(DESTDIR)$(bindir)"/xorrisofs ; then rm "$(DESTDIR)$(bindir)"/xorrisofs ; else echo ; fi + ln -s xorriso "$(DESTDIR)$(bindir)"/xorrisofs + if test -e "$(DESTDIR)$(bindir)"/osirrox ; then rm "$(DESTDIR)$(bindir)"/osirrox ; else echo ; fi + ln -s xorriso "$(DESTDIR)$(bindir)"/osirrox + if test -e "$(DESTDIR)$(bindir)"/xorrecord ; then rm "$(DESTDIR)$(bindir)"/xorrecord ; else echo ; fi + ln -s xorriso "$(DESTDIR)$(bindir)"/xorrecord + + +# Alternative to the disabled .PHONY above. +# Trying to create a build timestamp file semi-manually: make buildstamped +# +buildstamp: + date -u '+#define Xorriso_build_timestamP "%Y.%m.%d.%H%M%S"' >xorriso/xorriso_buildstamp.h + cat xorriso/xorriso_buildstamp.h + +# For now make buildstamped has to be performed explicitely. +buildstamped: buildstamp + make + + + +## Build test applications +noinst_PROGRAMS = \ + test/compare_file + +# A program to compare two files in mirrored trees in mounted filesystems +# To compare tree /media/dvd and /original/dir : +# find /media/dvd -exec test/compare_file '{}' /media/dvd /original/dir ';' +# +test_compare_file_CPPFLAGS = +test_compare_file_CFLAGS = +test_compare_file_LDADD = +test_compare_file_SOURCES = test/compare_file.c + + +## ========================================================================= ## + +## Build documentation (You need Doxygen for this to work) +webhost = http://libburn-api.pykix.org +webpath = / +docdir = $(DESTDIR)$(prefix)/share/doc/$(PACKAGE)-$(VERSION) + +doc: doc/html + +doc/html: doc/doxygen.conf + if [ -f ./doc/doc.lock ]; then \ + $(RM) -r doc/html; \ + doxygen doc/doxygen.conf; \ + fi + +doc-upload: doc/html + scp -r $ + and Thomas Schmitt +Integrated sub project of libburnia-project.org. +http://files.libburnia-project.org/releases/libisoburn-0.3.1.tar.gz +Copyright (C) 2006-2008 Vreixo Formoso, Thomas Schmitt. +Provided under GPL version 2. +------------------------------------------------------------------------------ + +libisoburn is a frontend for libraries libburn and libisofs which enables +creation and expansion of ISO-9660 filesystems on all CD/DVD/BD media supported +by libburn. This includes media like DVD+RW, which do not support multi-session +management on media level and even plain disk files or block devices. + +The price for that is thorough specialization on data files in ISO-9660 +filesystem images. So libisoburn is not suitable for audio (CD-DA) or any +other CD layout which does not entirely consist of ISO-9660 sessions. + +Currently it is supported on Linux with kernels >= 2.4 and on FreeBSD versions +with ATAPI/CAM support enabled in the kernel, see atapicam(4). + +By using this software you agree to the disclaimer at the end of this text: +"... without even the implied warranty ..." + + + Compilation, First Glimpse, Installation + +Dynamic library and compile time header requirements for libisoburn-0.3.1 : +- libburn.so.4 , version libburn-0.5.8 or higher +- libisofs.so.6 , version libisofs-0.6.12 or higher +libisoburn and xorriso will not start with libraries which are older than their +headers seen at compile time. So compile in the oldest possible installation +setup unless you have reason to enforce a newer bug fix level. + +Obtain libisoburn-0.3.1.tar.gz, take it to a directory of your choice +and do: + + tar xzf libisoburn-0.3.1.tar.gz + cd libisoburn-0.3.1 + +Within that directory execute: + + ./configure --prefix=/usr + make + +Then become superuser and execute + make install +which will make available libisoburn.so.1 and program xorriso. + +For the API concepts and calls see + ./libisoburn/libisoburn.h +as well as + /usr/lib/libisofs/libisofs.h + /usr/lib/libburn/libburn.h + + + xorriso + +libisoburn comes with a command line and dialog application named xorriso, +which offers a substantial part of libisoburn features to shell scripts and +users. Its file xorriso/README describes a standalone tarball as first +preference for statically linked xorriso installation. +The libisoburn installation described above produces a dynamically linked +xorriso binary depending on libburn.so, libisofs.so, libisoburn.so. + +After installation documentation is available via + man xorriso + +Several alias links point to the xorriso binary: + xorrisofs starts xorriso with -as mkisofs emulation already enabled + xorrecord starts xorriso with -as cdrecord emulation already enabled + osirrox starts with -osirrox image-to-disk copying already enabled + +By default xorriso will depend on libreadline if the readline-dev headers +are present. This dependcy can be avoided by running + ./configure --prefix=/usr --disable-libreadline + make clean ; make +Never omit the "make clean" command after switching libreadline enabling. + + + Drives and Disk File Objects + +The user of libisoburn applications needs rw-permission for the CD/DVD burner +devices which shall be used. +A list of rw-accessible drives can be obtained by + xorriso -devices +resp. by libburn API call + burn_drive_scan() + + +A possible source of problems are hald or other automounters. +If you can spot a process "hald-addon-storage" with the address of +your desired drive, then consider to kill it. + +If you cannot get rid of the automounter that easily, try whether it helps +to always load the drive tray manually before starting a write run of +xorriso. Wait until the drive light is off. +Better try to unmount an eventually mounted media before a write run. + + +Besides true optical drives, libisoburn can also address disk files as input or +output drives. The addresses of the disk files have to be preceded by "stdio:". +Like: + "stdio:/tmp/pseudo_drive" + + + Testing + +We are quite sure that libisofs produces accurate representations of the disk +files. This opinion is founded on a lot of test burns and checks by a little +test program which compares files from the mounted image with the orignals +on disk. It uses the normal POSIX filesystem calls, i.e. no libburnia stuff. + +This program is not installed systemwide but stays in the installation +directory of the xorriso tarball as test/compare_file . Usually it is +run as -exec payload of a find command. It demands at least three arguments: +The path of the file to compare, the prefix1 to be cut off from path +and the prefix2 which gets prepended afterwards to obtain the path of the +second file to compare. +As further argument there can be -no_ctime which suppresses the comparison +of ctime date stamps. +The exit value is 0 if no difference was detected, non-0 else. + +Example: After + xorriso ... -pathspecs on -add /=/original/dir -- + mount /media/dvd + cd test +compare tree /media/dvd with tree /original/dir : + find /original/dir -exec ./compare_file '{}' /original/dir /media/dvd ';' \ + | less +and vice versa: + find /media/dvd -exec ./compare_file '{}' /media/dvd /original/dir ';' \ + | less + + +------------------------------------------------------------------------------ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +------------------------------------------------------------------------------ +Based on and sub project of: +libburnia-project.org +By Mario Danic , + Vreixo Formoso + Thomas Schmitt +Copyright (C) 2006-2008 Mario Danic, Vreixo Formoso, Thomas Schmitt. + +libburnia-project.org is inspired by and in other components still containing +parts of old +Libburn. By Derek Foreman and + Ben Jansens +Copyright (C) 2002-2006 Derek Foreman and Ben Jansens + diff --git a/libisoburn/branches/ZeroThreeTwo/TODO b/libisoburn/branches/ZeroThreeTwo/TODO new file mode 100644 index 00000000..23e3b643 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/TODO @@ -0,0 +1,11 @@ +[Task] Figure out how to use "Requires" in pc.in (libisoburn and libisofs would benefit) +[Task] Figure out the usage of Libs.private (used in libburn) +[Task] Improve build system +[Task] Investigate build system, so other libburnia components can benefit +[Task] Write Doxygen files +[Task] Explain to Thomas & Vreixo about NEWS importance (all libburnia components + will benefit +[Task] Write a document about ABI & API +[Task] Create following targets for make: Src, Indent, Docs, Test, All [Any other suggestions?) + +All those tasks are currently assigned to Mario. diff --git a/libisoburn/branches/ZeroThreeTwo/acinclude.m4 b/libisoburn/branches/ZeroThreeTwo/acinclude.m4 new file mode 100644 index 00000000..861847bb --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/acinclude.m4 @@ -0,0 +1,22 @@ +AC_DEFUN([TARGET_SHIZZLE], +[ + ARCH="" + + AC_MSG_CHECKING([target operating system]) + + case $target in + *-*-linux*) + ARCH=linux + LIBBURN_ARCH_LIBS= + ;; + *-*-freebsd*) + ARCH=freebsd + LIBBURN_ARCH_LIBS=-lcam + ;; + *) + AC_ERROR([You are attempting to compile for an unsupported platform]) + ;; + esac + + AC_MSG_RESULT([$ARCH]) +]) diff --git a/libisoburn/branches/ZeroThreeTwo/bootstrap b/libisoburn/branches/ZeroThreeTwo/bootstrap new file mode 100755 index 00000000..3583d1c7 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/bootstrap @@ -0,0 +1,7 @@ +#!/bin/sh -x + +aclocal +libtoolize --copy --force +autoconf +automake --foreign --add-missing --copy --include-deps + diff --git a/libisoburn/branches/ZeroThreeTwo/configure.ac b/libisoburn/branches/ZeroThreeTwo/configure.ac new file mode 100644 index 00000000..ea70a065 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/configure.ac @@ -0,0 +1,139 @@ +AC_INIT([libisoburn], [0.3.1], [http://libburnia-project.org]) +AC_PREREQ([2.50]) +dnl AC_CONFIG_HEADER([config.h]) + +AC_CANONICAL_HOST +AC_CANONICAL_TARGET + +AM_INIT_AUTOMAKE([subdir-objects]) + +dnl Hint: Search list for version code aspects: +dnl /AC_INT( +dnl /ISOBURN_.*_VERSION +dnl /LT_.* +dnl /LIB.*_REQUIRED + +dnl The API version codes are defined in libisoburn/libisoburn.h +dnl #define isoburn_header_version_* +dnl configure.ac only rules the libtool revision numbering about +dnl LT_CURREN, LT_AGE, LT_REVISION where SONAME becomes LT_CURRENT - LT_AGE +dnl +dnl These three are only copies to provide libtool with unused LT_RELEASE +ISOBURN_MAJOR_VERSION=0 +ISOBURN_MINOR_VERSION=3 +ISOBURN_MICRO_VERSION=1 +dnl ISOBURN_VERSION=$ISOBURN_MAJOR_VERSION.$ISOBURN_MINOR_VERSION.$ISOBURN_MICRO_VERSION + +AC_SUBST(ISOBURN_MAJOR_VERSION) +AC_SUBST(ISOBURN_MINOR_VERSION) +AC_SUBST(ISOBURN_MICRO_VERSION) +dnl AC_SUBST(ISOBURN_VERSION) + +dnl Libtool versioning +dnl Generate libisoburn.so.1.x.y +dnl SONAME will become LT_CURRENT - LT_AGE +dnl +dnl ts A81201 +dnl ### This is the release version 0.3.0 = libisoburn.so.1.19.0 +dnl This is the development version after above stable release +dnl LT_CURRENT++, LT_AGE++ have not happened happened yet. +dnl ### LT_CURRENT++, LT_AGE++ has happened meanwhile. +dnl +dnl SONAME = 20 - 19 = 1 . Library name = libisoburn.so.1.19.0 +LT_RELEASE=$ISOBURN_MAJOR_VERSION.$ISOBURN_MINOR_VERSION +LT_CURRENT=20 +LT_AGE=19 +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) + +AC_PREFIX_DEFAULT([/usr/local]) +test "$prefix" = "NONE" && prefix=$ac_default_prefix + +AM_MAINTAINER_MODE + +AM_PROG_CC_C_O +AC_C_CONST +AC_C_INLINE +AC_C_BIGENDIAN + +dnl Large file support +AC_SYS_LARGEFILE +AC_FUNC_FSEEKO +AC_CHECK_FUNC([fseeko]) +if test ! $ac_cv_func_fseeko; then + AC_ERROR([Libburn requires largefile support.]) +fi + +AC_PROG_LIBTOOL +AC_SUBST(LIBTOOL_DEPS) +LIBTOOL="$LIBTOOL --silent" + +AC_PROG_INSTALL + +AC_CHECK_HEADERS() + +THREAD_LIBS=-lpthread +AC_SUBST(THREAD_LIBS) + +TARGET_SHIZZLE +AC_SUBST(ARCH) +AC_SUBST(LIBBURN_ARCH_LIBS) + + +AC_ARG_ENABLE(libreadline, +[ --enable-libreadline Enable use of libreadline by xorriso, default=yes], + , enable_libreadline=yes) +if test x$enable_libreadline = xyes; then +dnl Check whether there is readline-devel and readline-runtime. +dnl If not, erase this macro which would enable use of readline(),add_history() + READLINE_DEF="-DXorriso_with_readlinE" +dnl The empty yes case obviously causes -lreadline to be linked + AC_CHECK_HEADER(readline/readline.h, AC_CHECK_LIB(readline, readline, , READLINE_DEF= ), READLINE_DEF= ) +dnl The X= in the yes case prevents that -lreadline gets linked twice + AC_CHECK_HEADER(readline/history.h, AC_CHECK_LIB(readline, add_history, X= , READLINE_DEF= ), READLINE_DEF= ) +else + READLINE_DEF= +fi +AC_SUBST(READLINE_DEF) + +AC_CHECK_HEADER(libburn/libburn.h) +AC_CHECK_HEADER(libisofs/libisofs.h) + +dnl Check for proper library versions +LIBBURN_REQUIRED=0.5.9 +LIBISOFS_REQUIRED=0.6.12 +PKG_CHECK_MODULES(LIBBURN, libburn-1 >= $LIBBURN_REQUIRED) +PKG_CHECK_MODULES(LIBISOFS, libisofs-1 >= $LIBISOFS_REQUIRED) + +dnl Add compiler-specific flags + +dnl See if the user wants aggressive optimizations of the code +AC_ARG_ENABLE(debug, +[ --enable-debug Disable aggressive optimizations [default=yes]], + , enable_debug=yes) +if test x$enable_debug != xyes; then + if test x$GCC = xyes; then + CFLAGS="$CFLAGS -O3" + CFLAGS="$CFLAGS -fexpensive-optimizations" + fi + CFLAGS="$CFLAGS -DNDEBUG" +else + if test x$GCC = xyes; then + CFLAGS="$CFLAGS -g -pedantic -Wall" + fi + CFLAGS="$CFLAGS -DDEBUG" +fi + +AC_CONFIG_FILES([ + Makefile + doc/doxygen.conf + version.h + libisoburn-1.pc + ]) +AC_OUTPUT diff --git a/libisoburn/branches/ZeroThreeTwo/doc/comments b/libisoburn/branches/ZeroThreeTwo/doc/comments new file mode 100644 index 00000000..6d50d4e6 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/doc/comments @@ -0,0 +1,58 @@ +/** + @author Mario Danic, Vreixo Formoso, Thomas Schmitt + + @mainpage Libisoburn 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 read, manipulate, and +write ISO 9660 filesystems with Rock Ridge extensions. Media can be optical +media or filesystem objects. + +Our scope is currently Linux 2.4 and 2.6, or FreeBSD . + +libisoburn is an add-on to libburn and libisofs which coordinates both and +also allows to grow ISO-9660 filesystem images on multi-session media as well +as on overwriteable media via the same API. +All media peculiarities are handled automatically. + +xorriso is an application of all three libraries which creates, loads, +manipulates and writes ISO 9660 filesystem images with Rock Ridge extensions. +Manipulation is not only adding or overwriting of files but also deletion, +renaming, and attribute changing. An incremental backup feature is provided. +See xorriso/README for more + +SONAME: +libisoburn.so.1 (since 0.1.0, February 2008). + + + @section using Using the libraries + +Our build system is based on autotools. +User experience tells us that you will need at least autotools version 1.7. + +To build libisoburn go into its toplevel directory and execute + +- ./bootstrap (needed if you downloaded from SVN) + +- ./configure + +- make + +To make the libraries accessible for running resp. developing applications + +- make install + +Read libisoburn/libisoburn.h for a description of the API. +See also README, xorriso/README, and the man page xorriso/xorriso.1 which +gives an idea of the capabilities provided by Libburnia. + +You will also have to install and understand the two libraries of the +Libburnia project which provide fundamental services: +libburn is the library by which preformatted data get onto optical media. +See libburn/libburn.h for its API description. +libisofs is the library to handle ISO 9660 filesystems with Rock Ridge +extensions. Its API is described in libisofs/libisofs.h . + +*/ diff --git a/libisoburn/branches/ZeroThreeTwo/doc/doxygen.conf.in b/libisoburn/branches/ZeroThreeTwo/doc/doxygen.conf.in new file mode 100644 index 00000000..0a847861 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/doc/doxygen.conf.in @@ -0,0 +1,1298 @@ +# Doxyfile 1.5.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file that +# follow. The default is UTF-8 which is also the encoding used for all text before +# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into +# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of +# possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = @PACKAGE_NAME@ + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = @PACKAGE_VERSION@ + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, +# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, +# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, +# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = @top_srcdir@ + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = YES + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to +# include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be extracted +# and appear in the documentation as a namespace called 'anonymous_namespace{file}', +# where file will be replaced with the base name of the file that contains the anonymous +# namespace. By default anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text " + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = libisoburn \ + doc \ + test + +# This tag can be used to specify the character encoding of the source files that +# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default +# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. +# See http://www.gnu.org/software/libiconv for the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the output. +# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, +# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = test + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH +# then you must also enable this option. If you don't then doxygen will produce +# a warning and turn it on anyway + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = YES + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = OB \ + OTK \ + _ + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = doc/html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 200 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = letter + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = DOXYGEN + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to +# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to +# specify the directory where the mscgen tool resides. If left empty the tool is assumed to +# be found in the default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a caller dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = NO + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the number +# of direct children of the root node in a graph is already larger than +# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/libisoburn/branches/ZeroThreeTwo/doc/susp_aaip_0_2.txt b/libisoburn/branches/ZeroThreeTwo/doc/susp_aaip_0_2.txt new file mode 100644 index 00000000..f5448051 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/doc/susp_aaip_0_2.txt @@ -0,0 +1,328 @@ + + + Arbitrary Attribute Interchange Protocol + + Draft version 0.2 + Dec 19 2008 + + Interchange of Persistent File Attributes + + by Thomas Schmitt - mailto:scdbackup@gmx.net + Libburnia project - mailto:libburn-hackers@pykix.org + + +AAIP is intended as companion of the Rock Ridge Interchange Protocol RRIP +which under the general design of System Use Sharing Protocol SUSP extends +ISO 9660 aka ECMA-119 filesystem semantics to match POSIX needs. + +Goal is to have for each file an arbitrary number of attributes which consist +of two components (Name and Value) of arbitrary length and to have a compact +representation of ACLs. + +This document describes a SUSP field with adjustable name (Signature Word). +The name is defined in an ER field of which the content form is described here. +Recommended is to use the name "AA" which collides neither with SUSP 1.12 nor +with RRIP 1.12. +The field has been designed to be as similar to the RRIP field SL as possible. + +Since the size of a SUSP field is limited to 255, multiple fields may be +needed to describe one component. The CE mechanism of SUSP shall be used to +address enough storage if needed. + +------------------------------------------------------------------------------- + +System Entries Provided by this Specification + +* AA (or another name which does not disturb other co-existing SUSP protocols) + +Description of the "AA" System Use Entry + +The field has exactly the same layout as RRIP field SL. One has to expect +more data bytes than with SL, though, and any of the 256 possible byte values. +The reader shall be prepared to detect and handle oversized data. + +One or more AA fields form the Attribute List of a file object with +a pare number of components. Each two consequtive components form a pair of +Name and Value. The empty name is reserved for a compact representation of +ALCs. The meaning of any other name is not specified by this document. + +All AA fields except the last one shall have the CONTINUE flag set. An AA +field with CONTINUE set to 0 indicates the end of the Attribute List. + +The format of the "AA" System Use Field is as follows: + + [1] "BP 1 to BP 2 - Signature Word" shall be (41)(41) ("AA") resp. the word + that is defined in the ER field. See below. + + [2] "BP 3 - Length" shall specify as an 8-bit number the length in bytes of + the "AA" entry recorded according to ISO 9660:7.1.1. + + [3] "BP 4 - System Use Entry Version" shall be 1 as in ISO 9660:7.1.1. + + [4] "BP 5 - Flags" shall contain bit field flags numbered 0 to 7 starting + with the least significant bit as follows: + 0 CONTINUE This AA field continues in the next AA field. + All other bits shall be set to 0. + + [5] "BP 6 to Length - Component Area" shall contain Component Records + as described below. + + | 'A' | 'A' | LENGTH | 1 | FLAGS | COMPONENT AREA | + + +Within "AA" fields each component (Name or Value) shall be recorded as one +or more component records. If a component does not fit into the remaining +space of an AA field then it shall be continued in following AA fields. + +All Component Records of a component except the last one shall have the +CONTINUE flag set. A Component Record with CONTINUE set to 0 indicates the end +of the component. An eventually following Component Record starts the next +component. + +------------------------------------------------------------------------------- + +The Component Record format is identical to the one of the SL field. +The complete form of the following summary can be found in RRIP 1.12 "4.1.3.1". +In case of discrepancies, RRIP 1.12 is the decisive specification. + +Component Records shall be recorded contiguously within each Component Area, +starting in the first byte of the Component Area. The last Component Record +in the Component Area of an "AA" System Use Entry may be continued in the +Component Area of the next recorded "AA" System Use Entry in the same +System Use Area. + +Each Component Record shall have the following format: + + [A] "BP 1 - Component Flags" shall contain bit field flags numbered 0 to 7, + starting with the least significant bit, as follows: + 0 CONTINUE This Component Record continues in the next + AA Component Record. + The following bits are defined but may not be set if the Component + Record shall carry payload. (Their use case is unclear yet.) + 1 CURRENT This Component Record refers to the current + directory. + 2 PARENT This Component Record refers to the parent of + the current directory. + 3 ROOT This Component Record refers to root directory. + + all others are RESERVED and shall be 0. + + No more than one of "AA" Component Flag Bits 0-3 shall be set to ONE. + + [B] "BP 2 - Component Length (LEN_CP)" shall specify as an 8-bit number the + number of component bytes in the Component Record. This length shall not + include the first two bytes of the Component Record. + If any of the bit positions 1-3 is set, the value of this field shall be + set to ZERO and no Component Content shall be recorded. + This field shall be recorded according to ISO 9660 Format section 7.1.1. + + [C] "BP 3 to 2 + LEN_CP - Component Content" shall contain the component + bytes in the Component Record. + + | COMPONENT FLAGS | LEN_CP | COMPONENT BYTES | + + +Example: Two pairs of "name"="long...content" and "one"="more" encoded as + two AA fields + + Field 1 contains the Component Record of Name and one Component Record of + Value : + { 'A', 'A', 255, 1, 1, + 0, 4, 'n', 'a', 'm', 'e', + 1, 255, 'l', 'o', 'n', 'g', ... 238 more bytes, 13 go to next AA ... } + Field 2 contains the rest of "long...content" and the complete second pair. + It marks the end of the Attribute List : + { 'A', 'A', 38, 1, 0, + ... 13 remaining bytes of the Component Record in first field ... + 0, 7, 'c', 'o', 'n', 't', 'e', 'n', 't', + 0, 3, 'o', 'n', 'e', + 0, 4, 'm', 'o', 'r', 'e' } + +------------------------------------------------------------------------------- + +Specification of binary ACL representation as special Arbitrary Attribute + +The Name component of a binary ACL shall be of length 0. + +The Value shall be an arbitrary number of ACL Entries: + + [a] "BP 1 - Entry Flags" shall contain bit field flags numbered 0 to 7, + starting with the least significant bit, as follows: + 0 EXEC indicates that this entry grants execute permission + 1 WRITE write permission + 2 READ read permission + 3 QUALIFIER indicates that one or more Qualifier Records follow + 4 - 7 TYPE + shall contain the tag type of the ACL entry as four bit code: + 0 TRANSLATE entry for a global map of name to numeric id + 1 ACL_USER_OBJ permissions of owning user (as of PX field) + 2 ACL_USER of arbitrary user, with name as qualifier + 3 ACL_GROUP_OBJ permissions of owning group (as of PX field) + 4 ACL_GROUP of arbitrary group, with name as qualifier + 5 ACL_MASK restricts 2, 3, and 4 via logical AND + 6 ACL_OTHER permissions of non-listed, non-owning users + 8 SWITCH_MARK switch from "access" ACL to "default" ACL + 10 ACL_USER_N like 2, with numeric user id as qualifier + 12 ACL_GROUP_N like 4, with numeric group id as qualifier + 15 FUTURE_VERSION will indicate that this document + does not apply to the entry. + The other values are reserved. Readers shall ignore them if + they are not aware of updates of this document which would + assign a meaning to them. + +If any of ACL_USER_OBJ, ACL_GROUP_OBJ, ACL_OTHER are missing then the settings +from the PX field shall get into effect. If they exist then they shall override +the PX field. + +A numeric qualifier is a binary number of variable length. The Most Significant +Byte comes first. The number shall be the "POSIX File User ID" resp. +"POSIX File Group ID" as also used in RRIP PX fields. The ids of owning user +and owning group shall be taken from the PX field of the file object. + +Optional TRANSLATE entries may associate user or group names with numeric +ids to allow the reading system to remap the numeric ids. See below. +The writer is not obliged to write them and the reader is not obliged to +interpret them. + +The ACL entries belong to the "access" ACL of a file object. An optional +SWITCH_MARK entry may direct further entries to the "default" ACL which +is defined for directory objects. The switching is controlled by the EXEC bit. + 0 "access" ACL + 1 "default" ACL +The bits for WRITE, READ, QUALIFIER shall be 0 with SWITCH_MARK. + +The eventually needed qualifier is stored in one or more Qualifier Records. + + [b] "BP 2 - Qualifier Record Head" shall be present only if QUALIFIER is set + to 1. It shall give the number of Qualifier Bytes and eventually + indicate that the qualifier continues in a Qualifier Record which comes + imediately after this record. + 0 to 127 Q_LENGTH, the qualifier is complete by this record + 128 to 255 Q_LENGTH+128, the qualifier is continued by next record + So a Qualifier Record can contain at most 127 Qualifier Bytes. + This field shall be recorded according to ISO 9660 Format section 7.1.1. + + [c] "BP 3 to BP 2 + Q_LENGTH - Qualifier Bytes" shall be present only if + QUALIFIER is set to 1 and hold the announced number of bytes of the + user or group name. + + | ENTRY FLAGS [ | QUALIFIER HEAD | QUALIFIER BYTES | ] + + +Example: From man 5 acl: u::rw-,u:lisa:rw-,g::r--,g:toolies:rw-,m::r--,o::r-- + { 'A', 'A', 28, 1, 0, + 0, 0, + 0, 19, 0x16, + 0x2E, 4, 'l', 'i', 's', 'a', + 0x34, + 0x4E, 7, 't', 'o', 'o', 'l', 'i', 'e', 's', + 0x54, + 0x64 } + +Example: An entry with very long qualifier u:His_Excellency_..._the_Boss:r-- + 0x2C, 255, 'H', 'i', 's', '_', 'E', 'x', 'c', 'e', 'l', 'e', + ... 117 more bytes ..., + 8, 't', 'h', 'e', '_', 'B', 'o', 's', 's', + +Example: User number 71 in numerical form gets rwx + 0xAF, 1, 71, + Group number 65534 gets r-x + 0xCD, 2, 255, 254, + + +------------------------------------------------------------------------------- + +About Names and Numeric Identifiers + +It makes an important difference whether qualifiers are represented as names +or as id numbers. By storing names (and usually wasting space) it is possible +to control permissions in a way that is portable between uncoordinated +computers as long as the human readable user/group names are present on both +sides. POSIX File ID numbers make most sense in backups which shall be read +by the same system which wrote it. +Rock Ridge can only record POSIX File Ids but not user or group names. + +The entry flag value 0x08 TRANSLATE is not a ACL entry of the hosting object +but rather a global hint about the relation of roles, names and numeric ids. +If it is recorded at all, then it shall be recorded with the first Directory +Entry of the volume's root directory. According to the description of SUSP +field ER, this has to be "dot" or (00). Other than with ER, a TRANSLATE entry +may not appear in the root of directory sub trees. + +An interested reader shall examine the Arbitrary Attributes of this Directory +Entry in order to collect a translation table. +The advised translation is: PX or AA Id number -> name -> local id number. + +The Qualifier Bytes of a TRANSLATE entry shall have the following format: + + [i] "BP 0 - Role" shall tell whether it is about a user name (role 0) or + a group name (role 1). Other values are not allowed. + + [ii] "BP 1 to BP 8 - Numeric Id" shall hold the 32 bit POSIX Id number of the + entry. This field shall be recorded according to ISO 9660:7.3.3. + +[iii] "BP 9 to End Of Qualifier - Name" shall hold the name bytes of this + entry. + + | ROLE | NUMERIC ID | NAME | + +Example: User id number 1001 gets associated with user name "lisa" + + 0x08, 13, 0, 233,3,0,0, 0,0,3,233, 'l', 'i', 's', 'a', + + +------------------------------------------------------------------------------- + +Specification of the ER System Use Entry Values for AAIP: + +The Extension Version number for this version of AAIP shall be 1. + +The Extension Identifier field shall be "AAIP_0002" with Identifier Length 9. + +The mandatory content form of the Extension Descriptor is +"AA PROVIDES VIA AAIP 0.2 SUPPORT FOR ARBITRARY FILE ATTRIBUTES IN ISO 9660 IMAGES" +with possibly two letters other than "AA" at the start of the string. +The Description Length is 81. + +The reader of AAIP shall take the actual name of the AA field from BP 19 and +BP 20 of the ER field. + +The recommended content of the Extension Source is +"PLEASE CONTACT THE LIBBURNIA PROJECT VIA LIBBURNIA-PROJECT.ORG". +The corresponding Source Length is 62. + + +------------------------------------------------------------------------------- + +Model Relations: + + Attribute List ------------- [1:0..1] ------------- ACL + [1:0..n] [1:0..n] + Arbitrary Attribute ( [1:0..1] ACL ) Entry + [1:2..2n] [1:0..1] + Component ( [1..m:1..n] AA Field ) Qualifier + [1:1..n] << one of >> + Component Record / \ \ + [1..m:1..n] Translation Entry , Name , Numeric Id + AA Field | | | + [1:1..n] [1:1..n] [1:1] + \ | / + Qualifier Record + +------------------------------------------------------------------------------- +Revoked drafts: + +There was a draft AAIP 0.0 with ER signature "AAIP_2008A". It did not resemble +the existing field SL and therefore shall not be used by writers of ISO images. + +------------------------------------------------------------------------------- +References: + +ECMA-119 http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-119.pdf + +SUSP 1.12 ftp://ftp.ymi.com/pub/rockridge/susp112.ps + +RRIP 1.12 ftp://ftp.ymi.com/pub/rockridge/rrip112.ps +(especially field SL) + + diff --git a/libisoburn/branches/ZeroThreeTwo/libisoburn-1.pc.in b/libisoburn/branches/ZeroThreeTwo/libisoburn-1.pc.in new file mode 100644 index 00000000..7fae3f90 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/libisoburn-1.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libisoburn +Description: Multi-session filesystem extension to libisofs, libburn. +Version: @VERSION@ +Requires: +Libs: -L${libdir} -lisoburn +Cflags: -I${includedir}/libisoburn + diff --git a/libisoburn/branches/ZeroThreeTwo/libisoburn/burn_wrap.c b/libisoburn/branches/ZeroThreeTwo/libisoburn/burn_wrap.c new file mode 100644 index 00000000..bbad77e9 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/libisoburn/burn_wrap.c @@ -0,0 +1,1701 @@ + +/* + cc -g -c \ + -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE \ + burn_wrap.c +*/ +/* libburn wrappers for libisoburn + + Copyright 2007 - 2008 Thomas Schmitt, +*/ + +/* <<< A70929 : hardcoded CD-RW with fabricated -msinfo +#define Hardcoded_cd_rW 1 +#define Hardcoded_cd_rw_c1 12999 +#define Hardcoded_cd_rw_nwA 152660 +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifndef Xorriso_standalonE + +#include + +#include + +#else /* ! Xorriso_standalonE */ + +#include "../libisofs/libisofs.h" +#include "../libburn/libburn.h" + +#endif /* Xorriso_standalonE */ + + +#include "libisoburn.h" +#include "isoburn.h" + + +/* The global list of isoburn objects. Usually there is only one. */ +extern struct isoburn *isoburn_list_start; /* in isoburn.c */ + +/* Default values for application provided msgs_submit methods. + To be attached to newly aquired drives. + Storage location is isoburn.c +*/ +extern int (*libisoburn_default_msgs_submit) + (void *handle, int error_code, char msg_text[], + int os_errno, char severity[], int flag); +extern void *libisoburn_default_msgs_submit_handle; +extern int libisoburn_default_msgs_submit_flag; + + +static int isoburn_emulate_toc(struct burn_drive *d, int flag); + + +int isoburn_initialize(char msg[1024], int flag) +{ + int major, minor, micro, bad_match= 0; + + +/* First two ugly compile time checks for header version compatibility. + If everthing matches, then they produce no C code. In case of mismatch, + intentionally faulty C code will be inserted. +*/ + +#ifdef iso_lib_header_version_major +/* The minimum requirement of libisoburn towards the libisofs header + at compile time is defined in libisoburn/libisoburn.h : + isoburn_libisofs_req_major + isoburn_libisofs_req_minor + isoburn_libisofs_req_micro + It gets compared against the version macros in libisofs/libisofs.h : + iso_lib_header_version_major + iso_lib_header_version_minor + iso_lib_header_version_micro + If the header is too old then the following code shall cause failure of + cdrskin compilation rather than to allow production of a program with + unpredictable bugs or memory corruption. + The compiler messages supposed to appear in this case are: + error: 'LIBISOFS_MISCONFIGURATION' undeclared (first use in this function) + error: 'INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libisofs_dot_h_TOO_OLD__SEE_libisoburn_dot_h_and_burn_wrap_dot_h' undeclared (first use in this function) + error: 'LIBISOFS_MISCONFIGURATION_' undeclared (first use in this function) +*/ +/* The indendation is an advise of man gcc to help old compilers ignoring */ + #if isoburn_libisofs_req_major > iso_lib_header_version_major + #define Isoburn_libisofs_dot_h_too_olD 1 + #endif + #if isoburn_libisofs_req_major == iso_lib_header_version_major && isoburn_libisofs_req_minor > iso_lib_header_version_minor + #define Isoburn_libisofs_dot_h_too_olD 1 + #endif + #if isoburn_libisofs_req_minor == iso_lib_header_version_minor && isoburn_libisofs_req_micro > iso_lib_header_version_micro + #define Isoburn_libisofs_dot_h_too_olD 1 + #endif + +#ifdef Isoburn_libisofs_dot_h_too_olD +LIBISOFS_MISCONFIGURATION = 0; +INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libisofs_dot_h_TOO_OLD__SEE_libisoburn_dot_h_and_burn_wrap_dot_h = 0; +LIBISOFS_MISCONFIGURATION_ = 0; +#endif + +#endif /* iso_lib_header_version_major */ + +/* The minimum requirement of libisoburn towards the libburn header + at compile time is defined in libisoburn/libisoburn.h : + isoburn_libburn_req_major + isoburn_libburn_req_minor + isoburn_libburn_req_micro + It gets compared against the version macros in libburn/libburn.h : + burn_header_version_major + burn_header_version_minor + burn_header_version_micro + If the header is too old then the following code shall cause failure of + cdrskin compilation rather than to allow production of a program with + unpredictable bugs or memory corruption. + The compiler messages supposed to appear in this case are: + error: 'LIBBURN_MISCONFIGURATION' undeclared (first use in this function) + error: 'INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libburn_dot_h_TOO_OLD__SEE_libisoburn_dot_h_and_burn_wrap_dot_h' undeclared (first use in this function) + error: 'LIBBURN_MISCONFIGURATION_' undeclared (first use in this function) +*/ + +/* The indendation is an advise of man gcc to help old compilers ignoring */ + #if isoburn_libburn_req_major > burn_header_version_major + #define Isoburn_libburn_dot_h_too_olD 1 + #endif + #if isoburn_libburn_req_major == burn_header_version_major && isoburn_libburn_req_minor > burn_header_version_minor + #define Isoburn_libburn_dot_h_too_olD 1 + #endif + #if isoburn_libburn_req_minor == burn_header_version_minor && isoburn_libburn_req_micro > burn_header_version_micro + #define Isoburn_libburn_dot_h_too_olD 1 + #endif + +#ifdef Isoburn_libburn_dot_h_too_olD +LIBBURN_MISCONFIGURATION = 0; +INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libburn_dot_h_TOO_OLD__SEE_libisoburn_dot_h_and_burn_wrap_dot_h = 0; +LIBBURN_MISCONFIGURATION_ = 0; +#endif + +/* End of ugly compile time tests (scroll up for explanation) */ + + + + msg[0]= 0; + if(iso_init()<0) { + sprintf(msg+strlen(msg), "Cannot initialize libisofs\n"); + return(0); + } + iso_lib_version(&major, &minor, µ); + sprintf(msg+strlen(msg), "libisofs-%d.%d.%d ", major, minor, micro); +#ifdef iso_lib_header_version_major + if(iso_lib_is_compatible(iso_lib_header_version_major, + iso_lib_header_version_minor, + iso_lib_header_version_micro)) { + sprintf(msg+strlen(msg), "ok, "); + } else { + sprintf(msg+strlen(msg),"- TOO OLD -, need at least libisofs-%d.%d.%d ,\n", + iso_lib_header_version_major, iso_lib_header_version_minor, + iso_lib_header_version_micro); + bad_match= 1; + } +#else + if(iso_lib_is_compatible(isoburn_libisofs_req_major, + isoburn_libisofs_req_minor, + isoburn_libisofs_req_micro)) { + sprintf(msg+strlen(msg), "suspicious, "); + } else { + sprintf(msg+strlen(msg),"- TOO OLD -, need at least libisofs-%d.%d.%d ,\n", + isoburn_libisofs_req_major, isoburn_libisofs_req_minor, + isoburn_libisofs_req_micro); + bad_match= 1; + } +#endif /* ! iso_lib_header_version_major */ + + if(!burn_initialize()) { + sprintf(msg+strlen(msg), "Cannot initialize libburn\n"); + return(0); + } + burn_version(&major, &minor, µ); + sprintf(msg+strlen(msg), "libburn-%d.%d.%d ", major, minor, micro); + if(major > burn_header_version_major + || (major == burn_header_version_major + && (minor > burn_header_version_minor + || (minor == burn_header_version_minor + && micro >= burn_header_version_micro)))) { + sprintf(msg+strlen(msg), "ok, "); + } else { + sprintf(msg+strlen(msg), "- TOO OLD -, need at least libburn-%d.%d.%d ,\n", + burn_header_version_major, burn_header_version_minor, + burn_header_version_micro); + bad_match= 1; + } + + isoburn_version(&major, &minor, µ); + sprintf(msg+strlen(msg), "for libisoburn-%d.%d.%d", major, minor, micro); + if(bad_match) + return(0); + + isoburn_destroy_all(&isoburn_list_start, 0); /* isoburn_list_start= NULL */ + return(1); +} + + +/* API @since 0.1.0 */ +int isoburn_libisofs_req(int *major, int *minor, int *micro) +{ + *major= iso_lib_header_version_major; + *minor= iso_lib_header_version_minor; + *micro= iso_lib_header_version_micro; + return(1); +} + + +/* API @since 0.1.0 */ +int isoburn_libburn_req(int *major, int *minor, int *micro) +{ + *major= burn_header_version_major; + *minor= burn_header_version_minor; + *micro= burn_header_version_micro; + return(1); +} + + +int isoburn_set_msgs_submit(int (*msgs_submit)(void *handle, int error_code, + char msg_text[], int os_errno, + char severity[], int flag), + void *submit_handle, int submit_flag, int flag) +{ + libisoburn_default_msgs_submit= msgs_submit; + libisoburn_default_msgs_submit_handle= submit_handle; + libisoburn_default_msgs_submit_flag= submit_flag; + return(1); +} + + +int isoburn_is_intermediate_dvd_rw(struct burn_drive *d, int flag) +{ + int profile, ret= 0, format_status, num_formats; + char profile_name[80]; + enum burn_disc_status s; + off_t format_size= -1; + unsigned bl_sas; + + s= isoburn_disc_get_status(d); + ret= burn_disc_get_profile(d, &profile, profile_name); + if(ret>0 && profile==0x13) + ret= burn_disc_get_formats(d, &format_status, &format_size, + &bl_sas, &num_formats); + if(ret>0 && profile==0x13 && s==BURN_DISC_BLANK && + format_status==BURN_FORMAT_IS_UNKNOWN) + return(1); + return(0); +} + + +/** Examines the media and sets appropriate emulation if needed. + @param flag bit0= pretent blank on overwriteable media + bit3= if the drive reports a -ROM profile then try to read + table of content by scanning for ISO image headers. + bit4= do not emulate TOC on overwriteable media +*/ +static int isoburn_welcome_media(struct isoburn **o, struct burn_drive *d, + int flag) +{ + int ret, lba, nwa, profile, readonly= 0; + struct burn_multi_caps *caps= NULL; + struct isoburn_toc_entry *t; + char profile_name[80]; + + profile_name[0]= 0; + ret= burn_disc_get_profile(d, &profile, profile_name); + if(ret<=0) + profile= 0x00; + ret= burn_disc_get_multi_caps(d, BURN_WRITE_NONE, &caps, 0); + if(ret<0) /* == 0 is read-only media, but it is too early to reject it here */ + goto ex; + if(ret==0) + readonly= 1; + ret= isoburn_new(o, 0); + if(ret<=0) + goto ex; + (*o)->drive= d; + (*o)->msgs_submit= libisoburn_default_msgs_submit; + (*o)->msgs_submit_handle= libisoburn_default_msgs_submit_handle; + (*o)->msgs_submit_flag= libisoburn_default_msgs_submit_flag; + +#ifdef Hardcoded_cd_rW + /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */ + caps->start_adr= 0; + (*o)->fabricated_disc_status= BURN_DISC_APPENDABLE; +#endif + + if(caps->start_adr) { /* set emulation to overwriteable */ + (*o)->emulation_mode= 1; + ret= isoburn_is_intermediate_dvd_rw(d, 0); + if(ret>0) { + (*o)->min_start_byte= 0; + (*o)->nwa= 0; + (*o)->zero_nwa= 0; + } + if(flag&1) { + (*o)->nwa= (*o)->zero_nwa; + (*o)->fabricated_disc_status= BURN_DISC_BLANK; + } else { + ret= isoburn_start_emulation(*o, 0); + if(ret<=0) { + (*o)->emulation_mode= -1; + goto ex; + } + if(!(flag & 16)) { + /* try to read emulated toc */ + ret= isoburn_emulate_toc(d, 0); + if(ret<0) { + (*o)->emulation_mode= -1; + goto ex; + } + } + } + + } else { + + /* >>> recognize unsuitable media (but allow read-only media) */; + + if(readonly) { + /* This might be overwriteable media in a -ROM drive */ + if((flag & 16)) { + ret= 0; + } else { + ret= isoburn_emulate_toc(d, 1); + if(ret<0) + goto ex; + } + if(ret==0 && profile !=0x08 && (flag&8)) { + /* This might also be multi-session media which do not + get shown with a decent TOC. + CD-R TOC (profile 0x08) can be trusted. Others not. + Do a scan search of ISO headers. + */ + ret= isoburn_emulate_toc(d, 1|2); + if(ret<0) + goto ex; + if(ret>0) { /* point msc1 to last session */ + if((*o)->toc!=NULL) { + for(t= (*o)->toc; t->next!=NULL; t= t->next); + (*o)->fabricated_msc1= t->start_lba; + } + } + } + } +#ifdef Hardcoded_cd_rW + (*o)->nwa= Hardcoded_cd_rw_nwA; +#else + ret= burn_disc_track_lba_nwa(d, NULL, 0, &lba, &nwa); + if(ret>0) + (*o)->nwa= nwa; +#endif + + } + + ret= 1; +ex: + if(caps!=NULL) + burn_disc_free_multi_caps(&caps); + return(ret); +} + + +/** + @param flag bit0= load + bit1= regard overwriteable media as blank + bit2= if the drive is a regular disk file: truncate it to + the write start address + bit3= if the drive reports a -ROM profile then try to read + table of content by scanning for ISO image headers. + (depending on media type and drive state this might + help or it might make the resulting toc even worse) + bit4= do not emulate TOC on overwriteable media +*/ +int isoburn_drive_aquire(struct burn_drive_info *drive_infos[], + char *adr, int flag) +{ + int ret, drive_grabbed= 0; + struct isoburn *o= NULL; + +#ifndef NIX + +/* <<< should be obsolete by new drive addressing of libburn-0.5.2 */ +/* >>> but helps with kernel 2.4 to use /dev/sr */ + + int conv_ret; + char libburn_drive_adr[BURN_DRIVE_ADR_LEN]; + + conv_ret= burn_drive_convert_fs_adr(adr, libburn_drive_adr); + if(conv_ret<=0) + strcpy(libburn_drive_adr, adr); + ret= burn_drive_scan_and_grab(drive_infos, libburn_drive_adr, flag&1); + +#else + + ret= burn_drive_scan_and_grab(drive_infos, adr, flag & 1); + +#endif /* ! NIX */ + + if(ret<=0) + goto ex; + drive_grabbed= 1; + ret= isoburn_welcome_media(&o, (*drive_infos)[0].drive, + (flag & 24) | !!(flag&2)); + if(ret<=0) + goto ex; + + if(flag&4) { + ret= isoburn_find_emulator(&o, (*drive_infos)[0].drive, 0); + if(ret>0 && o!=NULL) + o->truncate= 1; + } + + ret= 1; +ex: + if(ret<=0) { + if(drive_grabbed) + burn_drive_release((*drive_infos)[0].drive, 0); + isoburn_destroy(&o, 0); + } + return(ret); +} + + +int isoburn_drive_scan_and_grab(struct burn_drive_info *drive_infos[], + char *adr, int load) +{ + int ret; + + ret= isoburn_drive_aquire(drive_infos, adr, !!load); + return(ret); +} + + +int isoburn_drive_grab(struct burn_drive *drive, int load) +{ + int ret; + struct isoburn *o= NULL; + + ret= burn_drive_grab(drive, load); + if(ret<=0) + goto ex; + ret= isoburn_welcome_media(&o, drive, 0); + if(ret<=0) + goto ex; + + ret= 1; +ex: + if(ret<=0) + isoburn_destroy(&o,0); + return(ret); +} + + +/** Retrieve media emulation and eventual isoburn emulator of drive. + @return -1 unsuitable media, 0 generic media, 1 emulated media. +*/ +int isoburn_find_emulator(struct isoburn **pt, + struct burn_drive *drive, int flag) +{ + int ret; + + ret= isoburn_find_by_drive(pt, drive, 0); + if(ret<=0) + return(0); + if((*pt)->emulation_mode==-1) { + isoburn_msgs_submit(*pt, 0x00060000, + "Unsuitable drive and media state", 0, "FAILURE", 0); + return(-1); + } + if((*pt)->emulation_mode==0) + return(0); + return(1); +} + + +enum burn_disc_status isoburn_disc_get_status(struct burn_drive *drive) +{ + int ret; + struct isoburn *o; + + ret= isoburn_find_emulator(&o, drive, 0); + if(ret<0) + return(BURN_DISC_UNSUITABLE); + if(o!=NULL) + if(o->fabricated_disc_status!=BURN_DISC_UNREADY) + return(o->fabricated_disc_status); + if(ret==0) + return(burn_disc_get_status(drive)); + + /* emulated status */ + if(o->emulation_mode==-1) + return(BURN_DISC_UNSUITABLE); + if(o->nwa>o->zero_nwa) + return(BURN_DISC_APPENDABLE); + return(BURN_DISC_BLANK); +} + + +int isoburn_disc_erasable(struct burn_drive *d) +{ + int ret; + struct isoburn *o; + + ret= isoburn_find_emulator(&o, d, 0); + if(ret>0) + if(o->emulation_mode==1) + return(1); + return burn_disc_erasable(d); +} + + +void isoburn_disc_erase(struct burn_drive *drive, int fast) +{ + int ret; + struct isoburn *o; + enum burn_disc_status s; + char zero_buffer[Libisoburn_target_head_sizE]; + + ret= isoburn_find_emulator(&o, drive, 0); + if(ret>0) { + if(o->emulation_mode==-1) { + /* To cause a negative reply with burn_drive_wrote_well() */ + burn_drive_cancel(drive); + return; + } + if(o->emulation_mode>0) { + s= isoburn_disc_get_status(drive); + if(s==BURN_DISC_FULL) { /* unknown data format in first 64 kB */ + memset(zero_buffer, 0, Libisoburn_target_head_sizE); + ret= burn_random_access_write(drive, (off_t) 0, zero_buffer, + (off_t) Libisoburn_target_head_sizE, 1); + } else { + ret= isoburn_invalidate_iso(o, 0); + } + if(ret<=0) + burn_drive_cancel(drive); /* mark run as failure */ + return; + } + } + burn_disc_erase(drive, fast); +} + + +off_t isoburn_disc_available_space(struct burn_drive *d, + struct burn_write_opts *opts) +{ + int ret; + struct isoburn *o; + struct burn_write_opts *eff_opts= NULL, *local_opts= NULL; + enum burn_disc_status s; + off_t avail; + + eff_opts= opts; + ret= isoburn_find_emulator(&o, d, 0); + if(ret>0 && o!=NULL) + if(o->emulation_mode!=0) { + s= isoburn_disc_get_status(d); + if(s==BURN_DISC_FULL) /* unknown data format in first 64 kB */ + return((off_t) 0); + local_opts= burn_write_opts_new(d); + eff_opts= local_opts; + burn_write_opts_set_start_byte(eff_opts, ((off_t) o->nwa) * (off_t) 2048); + } + avail= burn_disc_available_space(d, eff_opts); + if(local_opts!=NULL) + burn_write_opts_free(local_opts); + local_opts= NULL; + return(avail); +} + + +int isoburn_disc_get_msc1(struct burn_drive *d, int *start_lba) +{ + int ret; + struct isoburn *o; + +#ifdef Hardcoded_cd_rW + /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */ + *start_lba= Hardcoded_cd_rw_c1; + return(1); +#endif + + if(isoburn_disc_get_status(d)!=BURN_DISC_APPENDABLE && + isoburn_disc_get_status(d)!=BURN_DISC_FULL) { + isoburn_msgs_submit(NULL, 0x00060000, + "Media contains no recognizable data", 0, "SORRY", 0); + return(0); + } + ret= isoburn_find_emulator(&o, d, 0); + if(ret<0) + return(0); + if(o->fabricated_msc1>=0) { + *start_lba= o->fabricated_msc1; + return(1); + } + if(ret>0) if(o->emulation_mode>0) { + *start_lba= 0; + return(1); + } + return(burn_disc_get_msc1(d, start_lba)); +} + + +int isoburn_disc_track_lba_nwa(struct burn_drive *d, + struct burn_write_opts *opts, + int trackno, int *lba, int *nwa) +{ + int ret; + struct isoburn *o; + +#ifdef Hardcoded_cd_rW + /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */ + *lba= Hardcoded_cd_rw_c1; + *nwa= Hardcoded_cd_rw_nwA; + return(1); +#endif + + *nwa= *lba= 0; + ret= isoburn_find_emulator(&o, d, 0); + if(ret<0) + return(0); + if(ret>0) if(o->emulation_mode>0) { + *lba= 0; + *nwa= o->nwa; + return(1); + } + if(burn_drive_get_drive_role(d) != 1) + return(1); + return(burn_disc_track_lba_nwa(d, opts, trackno, lba, nwa)); +} + + +int isoburn_get_msc2(struct isoburn *o, + struct burn_write_opts *opts, int *msc2, int flag) +{ + int ret, lba, nwa; + + if(o->fabricated_msc2>=0) + *msc2= o->fabricated_msc2; + else { + ret= isoburn_disc_track_lba_nwa(o->drive, opts, 0, &lba, &nwa); + if(ret<=0) + return(ret); + *msc2= nwa; + } + return(1); +} + + +void isoburn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc) +{ + int ret; + off_t nwa= 0; + struct isoburn *o; + struct burn_drive *drive; + char reasons[BURN_REASONS_LEN],msg[160+BURN_REASONS_LEN]; + char adr[BURN_DRIVE_ADR_LEN]; + enum burn_write_types write_type; + struct stat stbuf; + + drive= burn_write_opts_get_drive(opts); + ret= isoburn_find_emulator(&o, drive, 0); + if(ret<0) + return; + if(o!=NULL) { + o->wrote_well= -1; + if(o->emulation_mode!=0) { + burn_write_opts_set_multi(opts, 0); + if(o->emulation_mode>0 && o->nwa >= 0) { + nwa= o->nwa; + + /* This caters for unwritten formatted DVD-RW. They need to be written + sequentially on the first use. Only written areas are random access. + If the first session is not written to LBA 0, then re-opening of + formatting and padding is needed. + This can be done. But when the track gets closed after padding, + this lasts a long time. There is a high risk that an app will not + poll the message queue while waiting for isoburn_disc_write() to + return. The pacifier loop usually happens only afterwards. + So automatic formatting might cause a nervous clueless user. + */ + ret= isoburn_is_intermediate_dvd_rw(drive, 0); + if(ret>0 && nwa>0 && nwa <= o->zero_nwa) { + /* actually this should not happen since such media get recognized + by isoburn_welcome_media and o->zero_nwa gets set to 0 + */ + sprintf(msg, + "DVD-RW insufficiently formatted. (Intermediate State, size unknown)"); + isoburn_msgs_submit(o, 0x00060000, msg, 0, "FAILURE", 0); + sprintf(msg, + "It might help to first deformat it and then format it again"); + isoburn_msgs_submit(o, 0x00060000, msg, 0, "HINT", 0); + burn_drive_cancel(drive); /* mark run as failure */ + return; + } + /* end of DVD-RW oriented check */ + + burn_write_opts_set_start_byte(opts, nwa * (off_t) 2048); + } + } + } + + write_type= burn_write_opts_auto_write_type(opts, disc, reasons, 0); + if (write_type == BURN_WRITE_NONE) { + sprintf(msg, "Failed to find a suitable write mode:\n%s", reasons); + isoburn_msgs_submit(o, 0x00060000, msg, 0, "FAILURE", 0); + if(o!=NULL) + o->wrote_well= 0; + /* To cause a negative reply with burn_drive_wrote_well() */ + burn_drive_cancel(drive); + return; + } + + sprintf(reasons, "%d", (int) write_type); + sprintf(msg, "Write_type = %s\n", + (write_type == BURN_WRITE_SAO ? "SAO" : + (write_type == BURN_WRITE_TAO ? "TAO" : reasons))); + isoburn_msgs_submit(o, 0x00060000, msg, 0, "DEBUG", 0); + +#ifdef Hardcoded_cd_rW + /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */ + fprintf(stderr, "Setting write address to LBA %d\n", Hardcoded_cd_rw_nwA); + burn_write_opts_set_start_byte(opts, + ((off_t) Hardcoded_cd_rw_nwA) * (off_t) 2048); +#endif + + if(o->truncate) { + ret= burn_drive_get_drive_role(drive); + if(ret==2) { + ret= burn_drive_d_get_adr(drive, adr); + if(ret>0) { + ret= lstat(adr, &stbuf); + if(ret!=-1) + if(S_ISREG(stbuf.st_mode)) + truncate(adr, nwa * (off_t) 2048); + } + } + } + + burn_disc_write(opts, disc); +} + + +void isoburn_drive_release(struct burn_drive *drive, int eject) +{ + int ret; + struct isoburn *o; + + ret= isoburn_find_emulator(&o, drive, 0); + if(ret<0) + return; + if(o!=NULL) { + isoburn_destroy(&o, 0); + } + burn_drive_release(drive, eject); +} + + +void isoburn_finish(void) +{ + isoburn_destroy_all(&isoburn_list_start, 0); + burn_finish(); + iso_finish(); +} + + +int isoburn_needs_emulation(struct burn_drive *drive) +{ + int ret; + struct isoburn *o; + enum burn_disc_status s; + + s= isoburn_disc_get_status(drive); + if(s!=BURN_DISC_BLANK && s!=BURN_DISC_APPENDABLE) + return(-1); + ret= isoburn_find_emulator(&o, drive, 0); + if(ret<0) + return(-1); + if(ret>0) + if(o->emulation_mode>0) + return(1); + return(0); +} + + +int isoburn_set_start_byte(struct isoburn *o, off_t value, int flag) +{ + int ret; + struct burn_drive *drive = o->drive; + struct burn_multi_caps *caps= NULL; + + ret= burn_disc_get_multi_caps(drive, BURN_WRITE_NONE, &caps, 0); + if(ret<=0) + goto ex; + if(!caps->start_adr) { + isoburn_msgs_submit(o, 0x00060000, + "Cannot set start byte address with this type of media", + 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + o->min_start_byte= value; + if(value % caps->start_alignment) + value+= caps->start_alignment - (value % caps->start_alignment); + o->nwa= value/2048; + /* If suitable for media alignment, round up to Libisoburn_nwa_alignemenT */ + if((o->nwa % Libisoburn_nwa_alignemenT) && + ((Libisoburn_nwa_alignemenT*2048) % caps->start_alignment)==0 ) + o->nwa+= Libisoburn_nwa_alignemenT - (o->nwa % Libisoburn_nwa_alignemenT); + ret= 1; +ex: + if(caps!=NULL) + burn_disc_free_multi_caps(&caps); + return(ret); +} + + +int isoburn_get_min_start_byte(struct burn_drive *d, off_t *start_byte, + int flag) +{ + int ret; + struct isoburn *o; + + ret= isoburn_find_emulator(&o, d, 0); + if(ret<0) + return(-1); + if(ret==0) + return(0); + *start_byte= o->min_start_byte; + if(o->min_start_byte<=0) + return(0); + return(1); +} + + +int isoburn_drive_wrote_well(struct burn_drive *d) +{ + int ret; + struct isoburn *o; + + ret= isoburn_find_emulator(&o, d, 0); + if(ret<0) + return(-1); + if(o!=NULL) + if(o->wrote_well>=0) + return(o->wrote_well); + ret= burn_drive_wrote_well(d); + return ret; +} + + +int isoburn_get_fifo_status(struct burn_drive *d, int *size, int *free_bytes, + char **status_text) +{ + int ret; + struct isoburn *o; + size_t hsize= 0, hfree_bytes= 0; + + ret= isoburn_find_emulator(&o, d, 0); + if(ret<0) + return(-1); + + if(o==NULL) + return(-1); + if(o->iso_source==NULL) + return(-1); + ret= iso_ring_buffer_get_status(o->iso_source, &hsize, &hfree_bytes); + if(hsize > 1024*1024*1024) + *size= 1024*1024*1024; + else + *size= hsize; + if(hfree_bytes > 1024*1024*1024) + *free_bytes= 1024*1024*1024; + else + *free_bytes= hfree_bytes; + *status_text= ""; + if(ret==0) + *status_text= "standby"; + else if(ret==1) + *status_text= "active"; + else if(ret==2) + *status_text= "ending"; + else if(ret==3) + *status_text= "failing"; + else if(ret==4) + *status_text= "unused"; + else if(ret==5) + *status_text= "abandoned"; + else if(ret==6) + *status_text= "ended"; + else if(ret==7) + *status_text= "aborted"; + return(ret); +} + + +/* @param flag bit0= -reserved- + bit1= this is a libburn severity +*/ +int isoburn__sev_to_text(int severity, char **severity_name, + int flag) +{ + int ret; + + ret= iso_sev_to_text(severity, severity_name); + if(ret>0) + return(ret); + ret= burn_sev_to_text(severity, severity_name, 0); + return(ret); +} + + +int isoburn__text_to_sev(char *severity_name, int *severity_number, int flag) +{ + int ret= 1; + + ret= iso_text_to_sev(severity_name, severity_number); + if(ret>0) + return(ret); + ret= burn_text_to_sev(severity_name, severity_number, 0); + return(ret); +} + + +int isoburn_report_iso_error(int iso_error_code, char msg_text[], int os_errno, + char min_severity[], int flag) +{ + int error_code, iso_sev, min_sev, ret; + char *sev_text_pt, *msg_text_pt= NULL; + + error_code= iso_error_get_code(iso_error_code); + if(error_code < 0x00030000 || error_code >= 0x00040000) + error_code= (error_code & 0xffff) | 0x00050000; + + if(iso_error_code<0) + msg_text_pt= (char *) iso_error_to_msg(iso_error_code); + if(msg_text_pt==NULL) + msg_text_pt= msg_text; + iso_sev= iso_error_get_severity(iso_error_code); + sev_text_pt= min_severity; + isoburn__text_to_sev(min_severity, &min_sev, 0); + if(min_sev < iso_sev) + isoburn__sev_to_text(iso_sev, &sev_text_pt, 0); + ret= iso_msgs_submit(error_code, msg_text_pt, os_errno, sev_text_pt, 0); + return(ret); +} + + +/* @param flag bit0-7: info return mode + 0= do not return anything in info (do not even touch it) + 1= copy volume id to info (info needs 33 bytes) + 2= do not touch info (caller will copy 64 kB header to it) + bit14= -reserved - + bit15= -reserved- + @return 1 seems to be a valid ISO image , 0 format not recognized, <0 error +*/ +int isoburn_read_iso_head_parse(struct burn_drive *d, unsigned char *data, + int *image_blocks, char *info, int flag) +{ + int i, info_mode; + + /* is this an ISO image ? */ + if(data[0]!=1) + return(0); + if(strncmp((char *) (data+1),"CD001",5)!=0) + return(0); + /* believe so */ + + *image_blocks= data[80] | (data[81]<<8) | (data[82]<<16) | (data[83]<<24); + info_mode= flag&255; + if(info_mode==0) { + ; + } else if(info_mode==1) { + strncpy(info, (char *) (data+40), 32); + info[32]= 0; + for(i= strlen(info)-1; i>=0; i--) + if(info[i]!=' ') + break; + else + info[i]= 0; + } else if(info_mode==2) { + ; + } else { + isoburn_msgs_submit(NULL, 0x00060000, + "Program error: Unknown info mode with isoburn_read_iso_head()", + 0, "FATAL", 0); + return(-1); + } + return(1); +} + + +/* API + @param flag bit0-7: info return mode + 0= do not return anything in info (do not even touch it) + 1= copy volume id to info (info needs 33 bytes) + 2= copy 64 kB header to info (needs 65536 bytes) + bit13= do not read head from media but use first 64 kB from info + bit14= check both half buffers (not only second) + return 2 if found in first block + bit15= return-1 on read error + @return 1 seems to be a valid ISO image , 2 found in first half buffer, + 0 format not recognized, <0 error +*/ +int isoburn_read_iso_head(struct burn_drive *d, int lba, + int *image_blocks, char *info, int flag) +{ + unsigned char buffer[64*1024]; + int ret, info_mode; + off_t data_count; + + info_mode= flag&255; + *image_blocks= 0; + if(flag&(1<<13)) { + memcpy(buffer, info, 64*1024); + } else { + ret = burn_read_data(d, ((off_t) lba) * (off_t) 2048, (char *) buffer, + (off_t) 64*1024, &data_count, 2); /* no error messages */ + if(ret<=0) + return(-1*!!(flag&(1<<15))); + if(info_mode==2) + memcpy(info, buffer, 64*1024); + } + + if(flag&(1<<14)) { + ret= isoburn_read_iso_head_parse(d, buffer, image_blocks, info, info_mode); + if(ret<0) + return(ret); + if(ret>0) + return(2); + } + ret= isoburn_read_iso_head_parse(d, buffer+32*1024, image_blocks, info, + info_mode); + if(ret<=0) + return(ret); + return(1); +} + + +int isoburn_make_toc_entry(struct isoburn *o, int *session_count, int lba, + int track_blocks, int flag) +{ + int ret; + struct isoburn_toc_entry *item; + + ret= isoburn_toc_entry_new(&item, o->toc, 0); + if(ret<=0) { + isoburn_msgs_submit(o, 0x00060000, + "Not enough memory for emulated TOC entry object", + 0, "FATAL", 0); + return(-1); + } + if(o->toc==NULL) + o->toc= item; + (*session_count)++; + item->session= *session_count; + item->track_no= *session_count; + item->start_lba= lba; + item->track_blocks= track_blocks; + return(1); +} + + +/* @param flag bit0= allow unemulated media + bit1= free scanning without enclosing LBA-0-header + @return -1 severe error, 0= no neat header chain, 1= credible chain read +*/ +int isoburn_emulate_toc(struct burn_drive *d, int flag) +{ + int ret, image_size= 0, lba, track_blocks, session_count= 0, read_flag= 0; + int scan_start= 0, scan_count= 0, probe_minus_16= 0, growisofs_nwa; + int with_enclosure= 0; + struct isoburn *o; + char msg[160], size_text[80], *sev; + time_t start_time, last_pacifier, now; + + /* is the media emulated multi-session ? */ + ret= isoburn_find_emulator(&o, d, 0); + if(ret<0) + return(-1); + if(o==NULL) + return(-1); + if(o->emulation_mode<=0 && !(flag&1)) + return(0); + + start_time= last_pacifier= time(NULL); + lba= 0; + if(!(flag&2)) { + ret= isoburn_read_iso_head(d, lba, &image_size, NULL, 0); + if(ret<=0) + {ret= 0; goto failure;} + lba= Libisoburn_overwriteable_starT; + with_enclosure= 1; + } + while(lba= 5) { + last_pacifier= now; + if(scan_count>=10*512) + sprintf(size_text, "%.f MB", ((double) scan_count) / 512.0); + else + sprintf(size_text, "%.f kB", 2 * (double) scan_count); + sprintf(msg, "Found %d ISO sessions by scanning %s in %.f seconds", + session_count, size_text, (double) (now - start_time)); + isoburn_msgs_submit(o, 0x00060000, msg, 0, "UPDATE", 0); + } + read_flag= 0; + if(flag&2) + read_flag|= (1<<15)|((session_count>0)<<14); + else { + + /* growisofs aligns to 16 rather than 32. Overwriteable TOC emulation + relies on not accidentially seeing inter-session trash data. + But one can safely access 16 blocks earlier because a xorriso header + would have overwritten with the unused 16 blocks at its start. + If libisoburn alignment would increase, then this would not be + possible any more. + */ + + if(probe_minus_16) + read_flag|= (1<<14); + probe_minus_16= 0; + } + + ret= isoburn_read_iso_head(d, lba, &track_blocks, NULL, read_flag); + if(ret<=0) { + if(session_count>0) { + if(flag&2) { + if(ret==0) { + /* try at next 64 k block (check both 32 k halves) */ + lba+= 32; + scan_count+= 32; + if(lba-scan_start <= Libisoburn_toc_scan_max_gaP) + continue; + } + break; + } + sprintf(msg, + "Chain of ISO session headers broken at #%d, LBA %ds", + session_count+1, lba); + isoburn_msgs_submit(o, 0x00060000, msg, 0, "WARNING", 0); + + if(with_enclosure) { + ret= isoburn_make_toc_entry(o, &session_count, 0, image_size, 0); + if(ret<=0) + goto failure; + } + break; /* do not return failure */ + + } + {ret= 0; goto failure;} + } + if(ret==2) /* ISO header was found in first half block */ + lba-= 16; + + ret= isoburn_make_toc_entry(o, &session_count, lba, track_blocks, 0); + if(ret<=0) + goto failure; + lba+= track_blocks; + scan_count+= 32; + + /* growisofs aligns to 16 rather than 32 */ + growisofs_nwa= lba; + if(growisofs_nwa % 16) + growisofs_nwa+= 16 - (growisofs_nwa % 16); + if(lba % Libisoburn_nwa_alignemenT) + lba+= Libisoburn_nwa_alignemenT - (lba % Libisoburn_nwa_alignemenT); + scan_start= lba; + if(lba - growisofs_nwa == 16) + probe_minus_16= 1; + } + if(last_pacifier != start_time) + sev= "UPDATE"; + else + sev= "DEBUG"; + now= time(NULL); + if(scan_count>=10*512) + sprintf(size_text, "%.f MB", ((double) scan_count) / 512.0); + else + sprintf(size_text, "%.f kB", 2 * (double) scan_count); + sprintf(msg, "Found %d ISO sessions by scanning %s in %.f seconds", + session_count, size_text, (double) (now - start_time)); + isoburn_msgs_submit(o, 0x00060000, msg, 0, sev, 0); + return(1); +failure:; + isoburn_toc_entry_destroy(&(o->toc), 1); + if(with_enclosure && o->emulation_mode == 1) { + session_count= 0; + ret= isoburn_make_toc_entry(o, &session_count, 0, image_size, 0); + } + return(ret); +} + + +int isoburn_toc_new_arrays(struct isoburn_toc_disc *o, + int session_count, int track_count, int flag) +{ + int i; + int isoburn_toc_destroy_arrays(struct isoburn_toc_disc *o, int flag); + + o->sessions= calloc(session_count, sizeof(struct isoburn_toc_session)); + o->session_pointers= + calloc(session_count, sizeof(struct isoburn_toc_session *)); + o->tracks= calloc(track_count, sizeof(struct isoburn_toc_track)); + o->track_pointers= calloc(track_count, sizeof(struct isoburn_toc_track *)); + if(o->sessions!=NULL && o->session_pointers!=NULL && + o->tracks!=NULL && o->track_pointers!=NULL) { + for(i= 0; isessions[i].session= NULL; + o->sessions[i].track_pointers= NULL; + o->sessions[i].track_count= 0; + o->sessions[i].toc_entry= NULL; + o->session_pointers[i]= NULL; + } + for(i= 0; itracks[i].track= NULL; + o->tracks[i].toc_entry= NULL; + o->track_pointers[i]= NULL; + } + return(1); + } + /* failed */ + isoburn_toc_destroy_arrays(o, 0); + return(-1); +} + + +int isoburn_toc_destroy_arrays(struct isoburn_toc_disc *o, int flag) +{ + if(o->sessions!=NULL) + free((char *) o->sessions); + o->sessions= NULL; + if(o->session_pointers!=NULL) + free((char *) o->session_pointers); + o->session_pointers= NULL; + if(o->tracks!=NULL) + free((char *) o->tracks); + o->tracks= NULL; + if(o->track_pointers!=NULL) + free((char *) o->track_pointers); + o->track_pointers= NULL; + return(1); +} + + +struct isoburn_toc_disc *isoburn_toc_drive_get_disc(struct burn_drive *d) +{ + int ret, session_count= 0, track_count= 0, num_tracks= 0, i, j; + struct isoburn *o; + struct isoburn_toc_entry *t; + struct isoburn_toc_disc *toc_disc= NULL; + struct burn_session **s; + struct burn_track **tracks; + + toc_disc= calloc(1, sizeof(struct isoburn_toc_disc)); + if(toc_disc==NULL) + return(NULL); + toc_disc->disc= NULL; + toc_disc->sessions= NULL; + toc_disc->session_pointers= NULL; + toc_disc->tracks= NULL; + toc_disc->track_pointers= NULL; + toc_disc->session_count= 0; + toc_disc->track_count= 0; + toc_disc->toc= NULL; + + /* is the media emulated multi-session ? */ + ret= isoburn_find_emulator(&o, d, 0); + if(ret<0) + goto libburn; + if(o->toc==NULL) + goto libburn; + + /* This is an emulated TOC */ + toc_disc->toc= o->toc; + for(t= toc_disc->toc; t!=NULL; t= t->next) + session_count++; + ret= isoburn_toc_new_arrays(toc_disc, session_count, session_count, 0); + if(ret<=0) + goto failure; + t= toc_disc->toc; + for(i= 0; isessions[i].track_pointers= toc_disc->track_pointers+i; + toc_disc->sessions[i].track_count= 1; + toc_disc->sessions[i].toc_entry= t; + toc_disc->session_pointers[i]= toc_disc->sessions+i; + toc_disc->tracks[i].toc_entry= t; + toc_disc->track_pointers[i]= toc_disc->tracks+i; + t= t->next; + } + toc_disc->session_count= session_count; + toc_disc->track_count= session_count; + return(toc_disc); + +libburn:; + /* This is a libburn provided TOC */ + toc_disc->disc= burn_drive_get_disc(d); + if(toc_disc->disc == NULL) { +failure:; + free((char *) toc_disc); + return(NULL); + } + s= burn_disc_get_sessions(toc_disc->disc, &session_count); + for(i= 0; isessions[i].session= s[i]; + toc_disc->sessions[i].track_pointers= toc_disc->track_pointers+track_count; + toc_disc->sessions[i].track_count= num_tracks; + toc_disc->session_pointers[i]= toc_disc->sessions+i; + for(j= 0; jtracks[track_count+j].track= tracks[j]; + toc_disc->track_pointers[track_count+j]= toc_disc->tracks+(track_count+j); + } + track_count+= num_tracks; + } + toc_disc->session_count= session_count; + toc_disc->track_count= track_count; + return(toc_disc); +} + + +int isoburn_toc_disc_get_sectors(struct isoburn_toc_disc *disc) +{ + struct isoburn_toc_entry *t; + int ret= 0, num_sessions, num_tracks; + struct burn_session **sessions; + struct burn_track **tracks; + struct burn_toc_entry entry; + + if(disc==NULL) + return(0); + if(disc->toc!=NULL) { + for(t= disc->toc; t!=NULL; t= t->next) + ret= t->start_lba + t->track_blocks; + } else if(disc->disc!=NULL) { + sessions= burn_disc_get_sessions(disc->disc, &num_sessions); + if(num_sessions > 0) { + tracks = burn_session_get_tracks(sessions[num_sessions - 1], + &num_tracks); + if(num_tracks > 0) { + burn_track_get_entry(tracks[num_tracks - 1], &entry); + if(entry.extensions_valid & 1) + ret= entry.start_lba + entry.track_blocks; + } + } +/* + ret= burn_disc_get_sectors(disc->disc); +*/ + } + return(ret); +} + + +struct isoburn_toc_session **isoburn_toc_disc_get_sessions( + struct isoburn_toc_disc *disc, int *num) +{ + *num= disc->session_count; + return(disc->session_pointers); +} + + +int isoburn_toc_session_get_sectors(struct isoburn_toc_session *s) +{ + struct isoburn_toc_entry *t; + int count= 0, i; + + if(s==NULL) + return(0); + if(s->toc_entry!=NULL) { + t= s->toc_entry; + for(i= 0; itrack_count; i++) { + count+= t->track_blocks; + t= t->next; + } + } else if(s->session!=NULL) + count= burn_session_get_sectors(s->session); + return(count); +} + + +int isoburn_toc_entry_finish(struct burn_toc_entry *entry, + int session_no, int track_no, int flag) +{ + int pmin, psec, pframe; + + entry->extensions_valid= 1; + entry->adr= 1; + entry->control= 4; + entry->session= session_no & 255; + entry->session_msb= (session_no >> 8) & 255; + entry->point= track_no & 255; + entry->point_msb= (track_no >> 8) & 255; + + burn_lba_to_msf(entry->start_lba, &pmin, &psec, &pframe); + if(pmin<=255) + entry->pmin= pmin; + else + entry->pmin= 255; + entry->psec= psec; + entry->pframe= pframe; + return(1); +} + + +void isoburn_toc_session_get_leadout_entry(struct isoburn_toc_session *s, + struct burn_toc_entry *entry) +{ + struct isoburn_toc_track *t; + + if(s==NULL) + return; + if(s->session!=NULL && s->toc_entry==NULL) { + burn_session_get_leadout_entry(s->session, entry); + return; + } + if(s->track_count<=0 || s->track_pointers==NULL || s->toc_entry==NULL) + return; + t= s->track_pointers[s->track_count-1]; + entry->start_lba= t->toc_entry->start_lba + t->toc_entry->track_blocks; + entry->track_blocks= 0; + isoburn_toc_entry_finish(entry, s->toc_entry->session, t->toc_entry->track_no, + 0); +} + + +struct isoburn_toc_track **isoburn_toc_session_get_tracks( + struct isoburn_toc_session *s, int *num) +{ + *num= s->track_count; + return(s->track_pointers); +} + + +void isoburn_toc_track_get_entry(struct isoburn_toc_track *t, + struct burn_toc_entry *entry) +{ + if(t==0) + return; + if(t->track!=NULL && t->toc_entry==NULL) { + burn_track_get_entry(t->track, entry); + return; + } + if(t->toc_entry==NULL) + return; + entry->start_lba= t->toc_entry->start_lba; + entry->track_blocks= t->toc_entry->track_blocks; + isoburn_toc_entry_finish(entry, t->toc_entry->session, t->toc_entry->track_no, + 0); +} + + +void isoburn_toc_disc_free(struct isoburn_toc_disc *d) +{ + if(d->disc!=NULL) + burn_disc_free(d->disc); + isoburn_toc_destroy_arrays(d, 0); + free((char *) d); +} + + +int isoburn_get_track_lba(struct isoburn_toc_track *track, int *lba, int flag) +{ + struct burn_toc_entry entry; + + isoburn_toc_track_get_entry(track, &entry); + if (entry.extensions_valid & 1) + *lba= entry.start_lba; + else + *lba= burn_msf_to_lba(entry.pmin, entry.psec, entry.pframe); + return(1); +} + + +int isoburn_drive_set_msgs_submit(struct burn_drive *d, + int (*msgs_submit)(void *handle, int error_code, + char msg_text[], int os_errno, + char severity[], int flag), + void *submit_handle, int submit_flag, int flag) +{ + struct isoburn *o; + int ret; + + ret= isoburn_find_emulator(&o, d, 0); + if(ret<0 || o==NULL) + return(-1); + o->msgs_submit= msgs_submit; + o->msgs_submit_handle= submit_handle; + o->msgs_submit_flag= submit_flag; + return(1); +} + + +/* @param flag bit0= with adr_mode 3: adr_value might be 16 blocks too high + bit1= insist in seeing a disc object with at least one session + bit2= with adr_mode 4: use adr_value as regular expression +*/ +int isoburn_set_msc1(struct burn_drive *d, int adr_mode, char *adr_value, + int flag) +{ + int ret, num_sessions, num_tracks, adr_num, i, j, total_tracks; + int lba, best_lba, size, re_valid= 0; + char volid[33], msg[160]; + struct isoburn *o; + struct isoburn_toc_disc *disc= NULL; + struct isoburn_toc_session **sessions= NULL; + struct isoburn_toc_track **tracks= NULL; + static char mode_names[][20]= {"auto", "session", "track", "lba", "volid"}; + static int max_mode_names= 4; + regex_t re; + regmatch_t match[1]; + + ret= isoburn_find_emulator(&o, d, 0); + if(ret<0) + return(-1); + if(o==NULL) + return(-1); + + adr_num= atoi(adr_value); + if(adr_mode!=3 || (flag & 2)) { + disc= isoburn_toc_drive_get_disc(d); + if(disc==NULL) { +not_found:; + if(adr_mode<0 || adr_mode>max_mode_names) + goto unknown_mode; + sprintf(msg, "Failed to find %s %s", mode_names[adr_mode], + strlen(adr_value)<=80 ? adr_value : "-oversized-string-"); + isoburn_msgs_submit(o, 0x00060000, msg, 0, "FAILURE", 0); + ret= 0; goto ex; + } + sessions= isoburn_toc_disc_get_sessions(disc, &num_sessions); + if(sessions==NULL || num_sessions<=0) + goto not_found; + } + if(adr_mode==0) { + /* Set fabricated_msc1 to last session in TOC */ + tracks= isoburn_toc_session_get_tracks(sessions[num_sessions-1], + &num_tracks); + if(tracks==NULL || num_tracks<=0) + goto not_found; + isoburn_get_track_lba(tracks[0], &(o->fabricated_msc1), 0); + + } else if(adr_mode==1) { + /* Use adr_num as session index (first session is 1, not 0) */ + if(adr_num<1 || adr_num>num_sessions) + goto not_found; + tracks= isoburn_toc_session_get_tracks(sessions[adr_num-1], &num_tracks); + if(tracks==NULL || num_tracks<=0) + goto not_found; + isoburn_get_track_lba(tracks[0], &(o->fabricated_msc1), 0); + + } else if(adr_mode==2) { + /* use adr_num as track index */ + total_tracks= 0; + for(i=0; ifabricated_msc1), 0); + ret= 1; goto ex; + } + } + } + goto not_found; + + } else if(adr_mode==3) { + o->fabricated_msc1= adr_num; + if((flag & 1) && o->fabricated_msc1 >= 16) { + /* adr_num is possibly 16 blocks too high */ + ret= isoburn_read_iso_head(d, o->fabricated_msc1, &size,volid, 1|(1<<14)); + if(ret==2) + o->fabricated_msc1-= 16; + } + } else if(adr_mode==4) { + /* search for volume id that is equal to adr_value */ + if(flag & 4) { + ret= regcomp(&re, adr_value, 0); + if(ret != 0) + flag&= ~4; + else + re_valid= 1; + } + best_lba= -1; + for(i=0; ifabricated_msc1= best_lba; + + } else { +unknown_mode:; + sprintf(msg, "Program error: Unknown msc1 address mode %d", adr_mode); + isoburn_msgs_submit(o, 0x00060000, msg, 0, "FATAL", 0); + ret= 0; goto ex; + } + ret= 1; +ex:; + if(disc!=NULL) + isoburn_toc_disc_free(disc); + if((flag & 4) && re_valid) + regfree(&re); + return(ret); +} + + +int isoburn_get_mount_params(struct burn_drive *d, + int adr_mode, char *adr_value, + int *lba, int *track, int *session, + char volid[33], int flag) +{ + int msc1_mem, ret, total_tracks, num_sessions, num_tracks, i, j, track_lba; + int size, is_iso= 0; + struct isoburn *o; + struct isoburn_toc_disc *disc= NULL; + struct isoburn_toc_session **sessions= NULL; + struct isoburn_toc_track **tracks= NULL; + + *lba= *track= *session= -1; + volid[0]= 0; + ret= isoburn_find_emulator(&o, d, 0); + if(ret < 0 || o == NULL) + return(-1); + msc1_mem= o->fabricated_msc1; + ret= isoburn_set_msc1(d, adr_mode, adr_value, 2 | (flag & 4)); + if(ret <= 0) + return(ret); + *lba= o->fabricated_msc1; + + disc= isoburn_toc_drive_get_disc(d); + if(disc==NULL) + {ret= -1; goto ex;} /* cannot happen because checked by isoburn_set_msc1 */ + sessions= isoburn_toc_disc_get_sessions(disc, &num_sessions); + if(sessions==NULL || num_sessions<=0) + {ret= -1; goto ex;} /* cannot happen because checked by isoburn_set_msc1 */ + total_tracks= 0; + for(i=0; ifabricated_msc1= msc1_mem; + return(2 - is_iso); +} + + diff --git a/libisoburn/branches/ZeroThreeTwo/libisoburn/data_source.c b/libisoburn/branches/ZeroThreeTwo/libisoburn/data_source.c new file mode 100644 index 00000000..b5a481df --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/libisoburn/data_source.c @@ -0,0 +1,269 @@ +/* + data source for libisoburn. + + Copyright 2007 - 2008 Vreixo Formoso Lopes + and Thomas Schmitt +*/ + +#include +#include + +#include + + +#ifndef Xorriso_standalonE + +#include + +#include + +#else /* ! Xorriso_standalonE */ + +#include "../libisofs/libisofs.h" +#include "../libburn/libburn.h" + +#endif /* Xorriso_standalonE */ + + +#include "isoburn.h" + + +/* Cached reading of image tree data */ +/* Multi tile: 32 * 64 kB */ + +/* The size of a single tile. + Powers of 2 only ! Less than 16 makes not much sense. +*/ +#define Libisoburn_tile_blockS 32 + +/* The number of tiles in the cache +*/ +#define Libisoburn_cache_tileS 32 + + +/* Debugging only: This reports cache loads on stderr. +#define Libisoburn_read_cache_reporT 1 +*/ + + +struct isoburn_cache_tile { + char cache_data[Libisoburn_tile_blockS * 2048]; + uint32_t cache_lba; + uint32_t last_error_lba; + uint32_t last_aligned_error_lba; + int cache_hits; + int age; +}; + +struct isoburn_cached_drive { + struct burn_drive *drive; + struct isoburn_cache_tile tiles[Libisoburn_cache_tileS]; + int current_age; +}; + +#define Libisoburn_max_agE 2000000000 + +static int ds_inc_age(struct isoburn_cached_drive *icd, int idx, int flag); + + +int ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer) +{ + int ret, i, oldest, oldest_age; + struct burn_drive *d; + off_t count; + uint32_t aligned_lba; + char msg[80]; + struct isoburn_cache_tile *tiles; + struct isoburn_cached_drive *icd; + + if(src == NULL || buffer == NULL) + /* It is not required by the specs of libisofs but implicitely assumed + by its current implementation that a data source read result <0 is + a valid libisofs error code. + */ + return ISO_NULL_POINTER; + + icd = (struct isoburn_cached_drive *) src->data; + d = (struct burn_drive*) icd->drive; + + if(d == NULL) { + /* This would happen if libisoburn saw output data in the fifo and + performed early drive release and afterwards libisofs still tries + to read data. + That would constitute a bad conceptual problem in libisoburn. + */ + isoburn_msgs_submit(NULL, 0x00060000, + "Programming error: Drive released while libisofs still attempts to read", + 0, "FATAL", 0); + return ISO_ASSERT_FAILURE; + } + + tiles = (struct isoburn_cache_tile *) icd->tiles; + + aligned_lba= lba & ~(Libisoburn_tile_blockS - 1); + + for(i=0; i 0) + return 1; + tiles[oldest].last_error_lba = lba; + +#ifdef ISO_DATA_SOURCE_MISHAP + ret= ISO_DATA_SOURCE_MISHAP; +#else + /* <<< pre libisofs-0.6.7 */ + /* It is not required by the specs of libisofs but implicitely assumed + ... + But it is not possible to ignore FAILURE. + libisofs insists in original error codes, i.e. libisoburn cannot + change severity FAILURE associated with ISO_FILE_READ_ERROR. + So ISO_FILE_READ_ERROR is not an option and libisoburn has to + misuse ISO_FILE_CANT_WRITE, which is actually for image generation + and not for image reading. + This is quite wrong, although the error message text is unclear + enough to make it appear plausible. + */ + ret= ISO_FILE_CANT_WRITE; +#endif + + if(ret >= 0) + ret = -1; + sprintf(msg, "ds_read_block(%lu) returns %d", (unsigned long) lba, ret); + isoburn_msgs_submit(NULL, 0x00060000, msg, 0, "DEBUG", 0); + return ret; + } + +#ifdef Libisoburn_read_cache_reporT + fprintf(stderr, "Tile %2.2d : After %3d hits, new load from %8x , count= %d\n", + oldest, tiles[oldest].cache_hits, aligned_lba, (int) count); +#endif + + tiles[oldest].cache_lba= aligned_lba; + tiles[oldest].cache_hits= 1; + ds_inc_age(icd, oldest, 0); + + memcpy(buffer, tiles[oldest].cache_data + (lba - aligned_lba) * 2048, 2048); + count= 2048; + + return 1; +} + + +static int ds_open(IsoDataSource *src) +{ + /* nothing to do, device is always grabbed */ + return 1; +} + +static int ds_close(IsoDataSource *src) +{ + /* nothing to do, device is always grabbed */ + return 1; +} + +static void ds_free_data(IsoDataSource *src) +{ + /* nothing to do */; + if(src->data != NULL) + free(src->data); + src->data= NULL; +} + + +int isoburn_data_source_shutdown(IsoDataSource *src, int flag) +{ + struct isoburn_cached_drive *icd; + + if(src==NULL) + return(0); + icd= (struct isoburn_cached_drive *) src->data; + icd->drive= NULL; + return(1); +} + + +IsoDataSource *isoburn_data_source_new(struct burn_drive *d) +{ + IsoDataSource *ret; + struct isoburn_cached_drive *icd= NULL; + int i; + + if (d==NULL) + return NULL; + ret = malloc(sizeof(IsoDataSource)); + icd = calloc(1,sizeof(struct isoburn_cached_drive)); + if (ret == NULL || icd == NULL) + return NULL; + ret->refcount = 1; + ret->read_block = ds_read_block; + ret->open = ds_open; + ret->close = ds_close; + ret->free_data = ds_free_data; + ret->data = icd; + icd->drive = d; + icd->current_age= 0; + for(i= 0; itiles[i].cache_lba = 0xffffffff; + icd->tiles[i].cache_hits = 0; + icd->tiles[i].last_error_lba = 0xffffffff; + icd->tiles[i].last_aligned_error_lba = 0xffffffff; + icd->tiles[i].age= 0; + } + return ret; +} + + +static int ds_inc_age(struct isoburn_cached_drive *icd, int idx, int flag) +{ + int i; + + (icd->current_age)++; + if(icd->current_age>=Libisoburn_max_agE) { /* reset all ages (allow waste) */ + for(i= 0; itiles)[i].age= 0; + icd->current_age= 1; + } + (icd->tiles)[idx].age= icd->current_age; + return(1); +} + + diff --git a/libisoburn/branches/ZeroThreeTwo/libisoburn/isoburn.c b/libisoburn/branches/ZeroThreeTwo/libisoburn/isoburn.c new file mode 100644 index 00000000..eac0e617 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/libisoburn/isoburn.c @@ -0,0 +1,962 @@ + +/* + cc -g -c isoburn.c +*/ + +/* + Class core of libisoburn. + + Copyright 2007 - 2008 Vreixo Formoso Lopes + Thomas Schmitt +*/ + +/* ( derived from stub generated by CgeN on Sat, 01 Sep 2007 12:04:36 GMT ) */ + +#include +#include +#include +#include +#include +#include + +#ifndef Xorriso_standalonE + +#include + +#include + +#else /* ! Xorriso_standalonE */ + +#include "../libisofs/libisofs.h" +#include "../libburn/libburn.h" + +#endif /* Xorriso_standalonE */ + + +#include "libisoburn.h" + +#include "isoburn.h" + + +/* Default values for application provided msgs_submit methods. + To be attached to newly aquired drives. +*/ +int (*libisoburn_default_msgs_submit) + (void *handle, int error_code, char msg_text[], + int os_errno, char severity[], int flag)= NULL; +void *libisoburn_default_msgs_submit_handle= NULL; +int libisoburn_default_msgs_submit_flag= 0; + + +/* ----------------------- isoburn_toc_entry ---------------------- */ + + +int isoburn_toc_entry_new(struct isoburn_toc_entry **objpt, + struct isoburn_toc_entry *boss, int flag) +{ + struct isoburn_toc_entry *o, *s; + + *objpt= o= (struct isoburn_toc_entry *) + malloc(sizeof(struct isoburn_toc_entry)); + if(o==NULL) { + isoburn_msgs_submit(NULL, 0x00060000, + "Cannot allocate memory for isoburn toc entry", + 0, "FATAL", 0); + return(-1); + } + o->session= 0; + o->track_no= 0; + o->start_lba= -1; + o->track_blocks= 0; + o->next= NULL; + if(boss!=NULL) { + for(s= boss; s->next!=NULL; s= s->next); + s->next= o; + } + return(1); +} + + +/* @param flag bit0= delete all subordinates too +*/ +int isoburn_toc_entry_destroy(struct isoburn_toc_entry **o, int flag) +{ + if(*o==NULL) + return(0); + if(flag&1) + isoburn_toc_entry_destroy(&((*o)->next), flag); + free((char *) (*o)); + *o= NULL; + return(1); +} + + +/* --------------------- end isoburn_toc_entry -------------------- */ + +/* -------------------------- isoburn ----------------------- */ + + +/* The global list of isoburn objects. Usually there is only one. + >>> we are not ready for multiple control threads yet. See >>> mutex . + Multiple burns under one control thread should work. +*/ +struct isoburn *isoburn_list_start= NULL; + + +int isoburn_new(struct isoburn **objpt, int flag) +{ + struct isoburn *o; + int i, ret; + + *objpt= o= (struct isoburn *) malloc(sizeof(struct isoburn)); + if(o==NULL) { + isoburn_msgs_submit(NULL, 0x00060000, + "Cannot allocate memory for isoburn control object", + 0, "FATAL", 0); + return(-1); + } + + o->drive= NULL; + o->emulation_mode= 0; + o->fabricated_msc1= -1; + o->fabricated_msc2= -1; + o->zero_nwa= Libisoburn_overwriteable_starT; + o->min_start_byte= o->zero_nwa * 2048; + o->nwa= o->zero_nwa; + o->truncate= 0; + o->iso_source= NULL; + o->fabricated_disc_status= BURN_DISC_UNREADY; + o->toc= NULL; + o->wrote_well= -1; + for(i=0;itarget_iso_head[i]= 0; + o->image= NULL; + o->iso_data_source= NULL; + o->read_pacifier= NULL; + o->read_pacifier_handle= NULL; + o->msgs_submit= NULL; + o->msgs_submit_handle= NULL; + o->msgs_submit_flag= 0; + o->prev= NULL; + o->next= NULL; + ret= iso_image_new("ISOIMAGE", &o->image); + if(ret<0) { + isoburn_report_iso_error(ret, "Cannot create image", 0, "FATAL", 0); + goto failed; + } + isoburn_link(o, isoburn_list_start, 1); + return(1); +failed:; + isoburn_destroy(objpt, 0); + return(-1); +} + + +int isoburn_destroy(struct isoburn **objpt, int flag) +{ + struct isoburn *o; + + o= *objpt; + if(o==NULL) + return(0); + + /* >>> mutex */ + + if(o==isoburn_list_start) + isoburn_list_start= o->next; + if(o->prev!=NULL) + o->prev->next= o->next; + if(o->next!=NULL) + o->next->prev= o->prev; + + /* >>> end mutex */ + + if(o->image!=NULL) + iso_image_unref(o->image); + if(o->toc!=NULL) + isoburn_toc_entry_destroy(&(o->toc), 1); /* all */ + if(o->iso_source!=NULL) + burn_source_free(o->iso_source); + if(o->iso_data_source!=NULL) + iso_data_source_unref(o->iso_data_source); + free((char *) o); + *objpt= NULL; + return(1); +} + + +int isoburn_destroy_all(struct isoburn **objpt, int flag) +{ + struct isoburn *o,*n; + + o= *objpt; + if(o==NULL) + return(0); + for(;o->prev!=NULL;o= o->prev); + for(;o!=NULL;o= n) { + n= o->next; + isoburn_destroy(&o,0); + } + *objpt= NULL; + return(1); +} + + +int isoburn_get_target_image(struct isoburn *o, IsoImage **pt, int flag) +{ + *pt= o->image; + return(1); +} + + +int isoburn_get_prev(struct isoburn *o, struct isoburn **pt, int flag) +{ + *pt= o->prev; + return(1); +} + + +int isoburn_get_next(struct isoburn *o, struct isoburn **pt, int flag) +{ + *pt= o->next; + return(1); +} + + +int isoburn_link(struct isoburn *o, struct isoburn *link, int flag) +/* + bit0= insert as link->prev rather than as link->next +*/ +{ + + /* >>> mutex */ + + if(isoburn_list_start==NULL || + (isoburn_list_start==link && (flag&1))) + isoburn_list_start= o; + if(o->prev!=NULL) + o->prev->next= o->next; + if(o->next!=NULL) + o->next->prev= o->prev; + o->prev= o->next= NULL; + if(link==NULL) + return(1); + if(flag&1) { + o->next= link; + o->prev= link->prev; + if(o->prev!=NULL) + o->prev->next= o; + link->prev= o; + } else { + o->prev= link; + o->next= link->next; + if(o->next!=NULL) + o->next->prev= o; + link->next= o; + } + + /* >>> end mutex */ + + return(1); +} + + +int isoburn_count(struct isoburn *o, int flag) +/* flag: bit1= count from start of list */ +{ + int counter= 0; + + if(flag&2) + for(;o->prev!=NULL;o= o->prev); + for(;o!=NULL;o= o->next) + counter++; + return(counter); +} + + +int isoburn_by_idx(struct isoburn *o, int idx, struct isoburn **pt, int flag) +/* flag: bit0= fetch first (idx<0) or last (idx>0) item in list + bit1= address from start of list */ +{ + int i,abs_idx; + struct isoburn *npt; + + if(flag&2) + for(;o->prev!=NULL;o= o->prev); + abs_idx= (idx>0?idx:-idx); + *pt= o; + for(i= 0;(i0) + npt= o->next; + else + npt= o->prev; + if(npt==NULL && (flag&1)) + break; + *pt= npt; + } + return(*pt!=NULL); +} + + +int isoburn_find_by_drive(struct isoburn **pt, struct burn_drive *d, int flag) +{ + struct isoburn *o; + + *pt= NULL; + for(o= isoburn_list_start;o!=NULL;o= o->next) + if(o->drive==d) { + *pt= o; + return(1); + } + return(0); +} + + +int isoburn_msgs_submit(struct isoburn *o, int error_code, char msg_text[], + int os_errno, char severity[], int flag) +{ + int ret, use_drive_method= 0; + + if(o!=NULL) + if(o->msgs_submit!=NULL) + use_drive_method= 1; + if(use_drive_method) { + ret= o->msgs_submit(o->msgs_submit_handle, error_code, msg_text, os_errno, + severity, o->msgs_submit_flag); + return(ret); + } + if(libisoburn_default_msgs_submit != NULL) { + ret= libisoburn_default_msgs_submit(libisoburn_default_msgs_submit_handle, + error_code, msg_text, os_errno, severity, + libisoburn_default_msgs_submit_flag); + return(ret); + } + /* Fallback: use message queue of libburn */ + burn_msgs_submit(error_code, msg_text, os_errno, severity, NULL); + return(1); +} + + +/* @param flag bit0= modifying rather than growing + bit1= prepare for early release of input drive: + wait until input and then disable image data source +*/ +static +int isoburn_prepare_disc_aux(struct burn_drive *in_d, struct burn_drive *out_d, + struct burn_disc **disc, + struct isoburn_imgen_opts *opts, int flag) +{ + struct burn_source *wsrc; + struct burn_session *session; + struct burn_track *track; + struct isoburn *in_o, *out_o; + IsoWriteOpts *wopts= NULL; + enum burn_disc_status state; + int ret, fifo_chunks, lba, nwa, i, new_img, early_indev_release; + size_t buffer_size= 0, buffer_free= 0; + char msg[160]; + + new_img= flag&1; + early_indev_release= flag&2; + if(new_img && early_indev_release) { + isoburn_msgs_submit(in_o, 0x00060000, + "Programming error: Wrong session setup: new_img && early_indev_release", + 0, "FATAL", 0); + {ret= -4; goto ex;} + } + + ret= isoburn_find_emulator(&in_o, in_d, 0); + if(ret<0 || in_o==NULL) + {ret= -1; goto ex;} + ret= isoburn_find_emulator(&out_o, out_d, 0); + if(ret<0 || out_o==NULL) + {ret= -1; goto ex;} + /* early end will be registered as failure */ + in_o->wrote_well= out_o->wrote_well= 0; + + state = isoburn_disc_get_status(in_d); + if (state != BURN_DISC_BLANK && state != BURN_DISC_APPENDABLE && + state != BURN_DISC_FULL) { + isoburn_msgs_submit(in_o, 0x00060000, "Unsuitable source media state", + 0, "FAILURE", 0); + {ret= -2; goto ex;} + } + state = isoburn_disc_get_status(out_d); + if (state != BURN_DISC_BLANK && state != BURN_DISC_APPENDABLE) { + isoburn_msgs_submit(out_o, 0x00060000, "Unsuitable target media state", + 0, "FAILURE", 0); + {ret= -2; goto ex;} + } + + fifo_chunks= 32; + if(opts->fifo_size >= 64*1024 && opts->fifo_size <= 1024.0 * 1024.0 * 1024.0){ + fifo_chunks= opts->fifo_size/2048; + if(fifo_chunks*2048 < opts->fifo_size) + fifo_chunks++; + } + + ret = iso_write_opts_new(&wopts, 0); + if (ret < 0) { + isoburn_report_iso_error(ret, "Cannot create iso_write_opts", 0, "FATAL",0); + goto ex; + } + iso_write_opts_set_iso_level(wopts, opts->level); + iso_write_opts_set_rockridge(wopts, opts->rockridge); + iso_write_opts_set_joliet(wopts, opts->joliet); + iso_write_opts_set_iso1999(wopts, opts->iso1999); + iso_write_opts_set_omit_version_numbers(wopts, opts->omit_version_numbers); + iso_write_opts_set_allow_deep_paths(wopts, opts->allow_deep_paths); + iso_write_opts_set_allow_longer_paths(wopts, opts->allow_longer_paths); + iso_write_opts_set_max_37_char_filenames(wopts, opts->max_37_char_filenames); + iso_write_opts_set_no_force_dots(wopts, opts->no_force_dots); + iso_write_opts_set_allow_lowercase(wopts, opts->allow_lowercase); + iso_write_opts_set_allow_full_ascii(wopts, opts->allow_full_ascii); + iso_write_opts_set_relaxed_vol_atts(wopts, 1); + iso_write_opts_set_joliet_longer_paths(wopts, opts->joliet_longer_paths); + iso_write_opts_set_always_gmt(wopts, opts->always_gmt); + iso_write_opts_set_rrip_version_1_10(wopts, opts->rrip_version_1_10); + iso_write_opts_set_dir_rec_mtime(wopts, opts->dir_rec_mtime); + iso_write_opts_set_sort_files(wopts, opts->sort_files); + iso_write_opts_set_replace_mode(wopts, opts->replace_dir_mode, + opts->replace_file_mode, opts->replace_uid, opts->replace_gid); + iso_write_opts_set_default_dir_mode(wopts, opts->dir_mode); + iso_write_opts_set_default_file_mode(wopts, opts->file_mode); + iso_write_opts_set_default_uid(wopts, opts->uid); + iso_write_opts_set_default_gid(wopts, opts->gid); + iso_write_opts_set_output_charset(wopts, opts->output_charset); + iso_write_opts_set_fifo_size(wopts, fifo_chunks); + + ret = isoburn_disc_track_lba_nwa(out_d, NULL, 0, &lba, &nwa); + opts->effective_lba= nwa; + ret= isoburn_get_msc2(out_o, NULL, &nwa, 0); + if (ret != 1) { + isoburn_msgs_submit(out_o, 0x00060000, + "Cannot determine next writeable address", 0, "FAILURE", 0); + {ret= -3; goto ex;} + } + iso_write_opts_set_ms_block(wopts, nwa); + iso_write_opts_set_appendable(wopts, !new_img); + iso_write_opts_set_overwrite_buf(wopts, + nwa>0 ? out_o->target_iso_head : NULL); + + ret = iso_image_create_burn_source(in_o->image, wopts, &wsrc); + if (ret < 0) { + isoburn_report_iso_error(ret, "Cannot create burn source", 0, "FAILURE", 0); + {ret= -1; goto ex;} + } + if (early_indev_release) { + for(i= 0; i<300; i++) { + + /* <<< ??? */ + if((i%30) == 0) { + sprintf(msg, "Waiting for data in fifo since %d seconds", i/30); + isoburn_msgs_submit(in_o, 0x00060000, msg, 0, "DEBUG", 0); + } + + usleep(100000); + ret= iso_ring_buffer_get_status(wsrc, &buffer_size, &buffer_free); + if(ret >0 && buffer_size != buffer_free) + break; + } + + /* <<< ??? */ + sprintf(msg, + "After %.1f seconds: %d bytes of output available (fifo state=%d)", + ((double) i+1) / 10.0, (int) (buffer_size - buffer_free), ret); + isoburn_msgs_submit(in_o, 0x00060000, msg, 0, "DEBUG", 0); + + if(in_o->iso_data_source!=NULL) + isoburn_data_source_shutdown(in_o->iso_data_source, 0); + } + + /* TODO check return values for failure. propertly clean-up on error */ + + out_o->iso_source= wsrc; + + *disc = burn_disc_create(); + session = burn_session_create(); + burn_disc_add_session(*disc, session, BURN_POS_END); + track = burn_track_create(); + burn_track_set_source(track, out_o->iso_source); + burn_session_add_track(session, track, BURN_POS_END); + + /* give up local references */ + burn_track_free(track); + burn_session_free(session); + + in_o->wrote_well= out_o->wrote_well= -1; /* neutral */ + ret= 1; +ex: + if(wopts!=NULL) + {iso_write_opts_free(wopts); wopts= NULL;} + return ret; +} + + +int isoburn_prepare_disc(struct burn_drive *d, struct burn_disc **disc, + struct isoburn_imgen_opts *opts) +{ + return isoburn_prepare_disc_aux(d, d, disc, opts, 0); +} + + +int isoburn_prepare_new_image(struct burn_drive *d, struct burn_disc **disc, + struct isoburn_imgen_opts *opts, + struct burn_drive *out_drive) +{ + int ret; + + ret= isoburn_prepare_disc_aux(d, out_drive, disc, opts, 1); + if (ret<=0) + return ret; + return 1; +} + + +/* API since 0.2.2 */ +int isoburn_prepare_blind_grow(struct burn_drive *d, struct burn_disc **disc, + struct isoburn_imgen_opts *opts, + struct burn_drive *out_drive, int nwa) +{ + int ret; + struct isoburn *o= NULL; + + ret= isoburn_find_emulator(&o, out_drive, 0); + if(ret<0 || o==NULL) + return(-1); + if(nwa >= 0) + o->fabricated_msc2= nwa; + if(o->nwa == o->zero_nwa) + o->nwa= o->zero_nwa= 0; + else + o->zero_nwa= 0; + ret= isoburn_prepare_disc_aux(d, out_drive, disc, opts, 2); + if (ret<=0) + return ret; + return(1); +} + + +/* API @since 0.1.0 + @param flag bit0= this is a regular end, not an abort + give up source reference +*/ +int isoburn_cancel_prepared_write(struct burn_drive *d, + struct burn_drive *output_drive, int flag) +{ + int ret; + struct isoburn *o= NULL; + + if(output_drive!=NULL) { + ret= isoburn_find_emulator(&o, output_drive, 0); + if(ret<0 || o==NULL) + o= NULL; + else if(o->iso_source==NULL) + o= NULL; + } + if(o==NULL) { + ret= isoburn_find_emulator(&o, d, 0); + if(ret<0) + return(-1); + if(o==NULL) + return(0); + if(o->iso_source==NULL) + return(0); + } + if(o->iso_source->read!=NULL) + return(0); + if(o->iso_source->version<1) + return(0); + o->iso_source->cancel(o->iso_source); + burn_source_free(o->iso_source); + o->iso_source= NULL; + return(1); +} + + +/* API @since 0.1.0 */ +int isoburn_sync_after_write(struct burn_drive *d, + struct burn_drive *output_drive, int flag) +{ + return isoburn_cancel_prepared_write(d, output_drive, 1); +} + + +void isoburn_version(int *major, int *minor, int *micro) +{ + *major= isoburn_header_version_major; + *minor= isoburn_header_version_minor; + *micro= isoburn_header_version_micro; + +/* No more: values from version.h generated from version.h.in and + macro values defined in configure.ac + + *major = ISOBURN_MAJOR_VERSION; + *minor = ISOBURN_MINOR_VERSION; + *micro = ISOBURN_MICRO_VERSION; +*/ +} + + +int isoburn_is_compatible(int major, int minor, int micro, int flag) +{ + int own_major, own_minor, own_micro; + + isoburn_version(&own_major, &own_minor, &own_micro); + return(own_major > major || + (own_major == major && (own_minor > minor || + (own_minor == minor && own_micro >= micro)))); +} + + +/* ----------------------------------------------------------------------- */ +/* + Options for image reading. +*/ +/* ----------------------------------------------------------------------- */ + + +int isoburn_ropt_new(struct isoburn_read_opts **new_o, int flag) +{ + struct isoburn_read_opts *o; + + o= (*new_o)= calloc(1, sizeof(struct isoburn_read_opts)); + if(o==NULL) { + isoburn_msgs_submit(NULL, 0x00060000, + "Cannot allocate memory for read options", 0, "FATAL", 0); + return(-1); + } + o->norock= 0; + o->nojoliet= 0; + o->noiso1999= 1; + o->preferjoliet= 0; + o->uid= geteuid(); + o->gid= getegid(); + o->mode= 0444; + o->dirmode= 0555; + o->input_charset= NULL; + o->hasRR= 0; + o->hasJoliet= 0; + o->hasIso1999= 0; + o->hasElTorito= 0; + o->size= 0; + o->pretend_blank= 1; + return(1); +} + + +int isoburn_ropt_destroy(struct isoburn_read_opts **o, int flag) +{ + if(*o==NULL) + return(0); + free(*o); + *o= NULL; + return(1); +} + + +int isoburn_ropt_set_extensions(struct isoburn_read_opts *o, int ext) +{ + o->norock= !!(ext&1); + o->nojoliet= !!(ext&2); + o->noiso1999= !!(ext&4); + o->preferjoliet= !!(ext&8); + o->pretend_blank= !!(ext&16); + return(1); +} + + +int isoburn_ropt_get_extensions(struct isoburn_read_opts *o, int *ext) +{ + *ext= (!!o->norock) | ((!!o->nojoliet)<<1) | ((!!o->noiso1999)<<2) | + ((!!o->preferjoliet)<<3) | ((!!o->pretend_blank)<<4); + return(1); +} + + +int isoburn_ropt_set_default_perms(struct isoburn_read_opts *o, + uid_t uid, gid_t gid, mode_t mode) +{ + mode_t dirmode; + + o->uid= uid; + o->gid= gid; + o->mode= mode; + dirmode= mode; + if(dirmode & S_IRUSR) + dirmode|= S_IXUSR; + if(dirmode & S_IRGRP) + dirmode|= S_IXGRP; + if(dirmode & S_IROTH) + dirmode|= S_IXOTH; + o->dirmode= dirmode; + return(1); +} + + +int isoburn_ropt_get_default_perms(struct isoburn_read_opts *o, + uid_t *uid, gid_t *gid, mode_t *mode) +{ + *uid= o->uid; + *gid= o->gid; + *mode= o->mode; + return(1); +} + + +int isoburn_ropt_set_default_dirperms(struct isoburn_read_opts *o, + mode_t mode) +{ + o->dirmode= mode; + return(1); +} + + +int isoburn_ropt_get_default_dirperms(struct isoburn_read_opts *o, + mode_t *mode) +{ + *mode= o->dirmode; + return(1); +} + + +int isoburn_ropt_set_input_charset(struct isoburn_read_opts *o, + char *input_charset) +{ + o->input_charset= input_charset; + return(1); +} + + +int isoburn_igopt_get_in_charset(struct isoburn_read_opts *o, + char **input_charset) +{ + *input_charset= o->input_charset; + return(1); +} + + +int isoburn_ropt_get_size_what(struct isoburn_read_opts *o, + uint32_t *size, int *has_what) +{ + *size= o->size; + *has_what= (!!o->hasRR) | ((!!o->hasJoliet)<<1) | + ((!!o->hasIso1999)<<2) | ((!!o->hasElTorito)<<3); + return(1); +} + + +/* ----------------------------------------------------------------------- */ +/* + Options for image generation by libisofs and image transport to libburn. +*/ +/* ----------------------------------------------------------------------- */ + + +int isoburn_igopt_new(struct isoburn_imgen_opts **new_o, int flag) +{ + struct isoburn_imgen_opts *o; + + o= (*new_o)= calloc(1, sizeof(struct isoburn_imgen_opts)); + if(o==NULL) { + isoburn_msgs_submit(NULL, 0x00060000, + "Cannot allocate memory for image generation options", + 0, "FATAL", 0); + return(-1); + } + o->level= 2; + o->rockridge= 1; + o->joliet= 0; + o->iso1999= 0; + o->omit_version_numbers= 0; + o->allow_deep_paths= 1; + o->allow_longer_paths= 0; + o->max_37_char_filenames= 0; + o->no_force_dots= 0; + o->allow_lowercase= 0; + o->allow_full_ascii= 0; + o->joliet_longer_paths= 0; + o->always_gmt= 0; + o->rrip_version_1_10= 0; + o->dir_rec_mtime= 0; + o->sort_files= 0; + o->replace_dir_mode= 0; + o->replace_file_mode= 0; + o->replace_uid= 0; + o->replace_gid= 0; + o->dir_mode= 0555; + o->file_mode= 0444; + o->uid= 0; + o->gid= 0; + o->output_charset= NULL; + o->fifo_size= 4*1024*1024; + o->effective_lba= -1; + return(1); +} + + +int isoburn_igopt_destroy(struct isoburn_imgen_opts **o, int flag) +{ + if(*o==NULL) + return(0); + free(*o); + *o= NULL; + return(1); +} + + +int isoburn_igopt_set_level(struct isoburn_imgen_opts *o, int level) +{ + o->level= level; + return(1); +} + + +int isoburn_igopt_get_level(struct isoburn_imgen_opts *o, int *level) +{ + *level= o->level; + return(1); +} + + +int isoburn_igopt_set_extensions(struct isoburn_imgen_opts *o, int ext) +{ + o->rockridge= !!(ext&1); + o->joliet= !!(ext&2); + o->iso1999= !!(ext&4); + return(1); +} + + +int isoburn_igopt_get_extensions(struct isoburn_imgen_opts *o, int *ext) +{ + *ext= (!!o->rockridge) | ((!!o->joliet)<<1) | ((!!o->iso1999)<<2); + return(1); +} + + +int isoburn_igopt_set_relaxed(struct isoburn_imgen_opts *o, int relax) +{ + o->omit_version_numbers= !!(relax&1); + o->allow_deep_paths= !!(relax&2); + o->allow_longer_paths= !!(relax&4); + o->max_37_char_filenames= !!(relax&8); + o->no_force_dots= !!(relax&16); + o->allow_lowercase= !!(relax&32); + o->allow_full_ascii= !!(relax&64); + o->joliet_longer_paths= !!(relax&128); + o->always_gmt= !!(relax & isoburn_igopt_always_gmt); + o->rrip_version_1_10= !!(relax & isoburn_igopt_rrip_version_1_10); + o->dir_rec_mtime= !!(relax & isoburn_igopt_dir_rec_mtime); + return(1); +} + + +int isoburn_igopt_get_relaxed(struct isoburn_imgen_opts *o, int *relax) +{ + *relax= (!!o->omit_version_numbers) | ((!!o->allow_deep_paths)<<1) | + ((!!o->allow_longer_paths)<<2) | ((!!o->max_37_char_filenames)<<3) | + ((!!o->no_force_dots)<<4) | ((!!o->allow_lowercase)<<5) | + ((!!o->allow_full_ascii)<<6) | ((!!o->joliet_longer_paths)<<7); + return(1); +} + + +int isoburn_igopt_set_sort_files(struct isoburn_imgen_opts *o, int value) +{ + o->sort_files= !!(value&1); + return(1); +} + + +int isoburn_igopt_get_sort_files(struct isoburn_imgen_opts *o, int *value) +{ + *value= !!o->sort_files; + return(1); +} + + +int isoburn_igopt_set_over_mode(struct isoburn_imgen_opts *o, + int replace_dir_mode, int replace_file_mode, + mode_t dir_mode, mode_t file_mode) +{ + o->replace_dir_mode= replace_dir_mode%3; + o->replace_file_mode= replace_file_mode%3; + o->dir_mode= dir_mode; + o->file_mode= file_mode; + return(1); +} + + +int isoburn_igopt_get_over_mode(struct isoburn_imgen_opts *o, + int *replace_dir_mode, int *replace_file_mode, + mode_t *dir_mode, mode_t *file_mode) +{ + *replace_dir_mode= o->replace_dir_mode%3; + *replace_file_mode= o->replace_file_mode%3; + *dir_mode= o->dir_mode; + *file_mode= o->file_mode; + return(1); +} + + +int isoburn_igopt_set_over_ugid(struct isoburn_imgen_opts *o, + int replace_uid, int replace_gid, + uid_t uid, gid_t gid) +{ + o->replace_uid= replace_uid%3; + o->replace_gid= replace_gid%3; + o->uid= uid; + o->gid= gid; + return(1); +} + +int isoburn_igopt_get_over_ugid(struct isoburn_imgen_opts *o, + int *replace_uid, int *replace_gid, + uid_t *uid, gid_t *gid) +{ + *replace_uid= o->replace_uid%3; + *replace_gid= o->replace_gid%3; + *uid= o->uid; + *gid= o->gid; + return(1); +} + + +int isoburn_igopt_set_out_charset(struct isoburn_imgen_opts *o, + char *output_charset) +{ + o->output_charset= output_charset; + return(1); +} + + +int isoburn_igopt_get_out_charset(struct isoburn_imgen_opts *o, + char **output_charset) +{ + *output_charset= o->output_charset; + return(1); +} + + +int isoburn_igopt_set_fifo_size(struct isoburn_imgen_opts *o, int fifo_size) +{ + o->fifo_size= fifo_size; + return(1); +} + + +int isoburn_igopt_get_fifo_size(struct isoburn_imgen_opts *o, int *fifo_size) +{ + *fifo_size= o->fifo_size; + return(1); +} + + +int isoburn_igopt_get_effective_lba(struct isoburn_imgen_opts *o, int *lba) +{ + *lba= o->effective_lba; + return(1); +} + + diff --git a/libisoburn/branches/ZeroThreeTwo/libisoburn/isoburn.h b/libisoburn/branches/ZeroThreeTwo/libisoburn/isoburn.h new file mode 100644 index 00000000..5ee483bb --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/libisoburn/isoburn.h @@ -0,0 +1,492 @@ + +/* + Class struct of libisoburn. + + Copyright 2007 Vreixo Formoso Lopes + and Thomas Schmitt +*/ + +#ifndef Isoburn_includeD +#define Isoburn_includeD + + +/* for uint8_t */ +#include + +/* For emulated TOC of overwriteable media. + Provides minimal info for faking a struct burn_toc_entry. +*/ +struct isoburn_toc_entry { + int session; + int track_no; /* point */ + int start_lba; + int track_blocks; + + struct isoburn_toc_entry *next; +}; + +int isoburn_toc_entry_new(struct isoburn_toc_entry **objpt, + struct isoburn_toc_entry *boss, int flag); + +/* @param flag bit0= delete all subordinates too +*/ +int isoburn_toc_entry_destroy(struct isoburn_toc_entry **o, int flag); + + +/* Size of target_iso_head which is to be written during + isoburn_activate_session() +*/ +#define Libisoburn_target_head_sizE (32*2048) + +struct isoburn { + + + /* The libburn drive to which this isoburn object is related + Most isoburn calls will use a burn_drive as object handle */ + struct burn_drive *drive; + + /* -1= inappropriate media state detected + 0= libburn multi-session media, resp. undecided yet + 1= random access media */ + int emulation_mode; + + /* Although rarely used, libburn can operate on several + drives simultaneously. */ + struct isoburn *prev; + struct isoburn *next; + + + /* If >= 0, this address is used as reply for isoburn_disc_get_msc1() + */ + int fabricated_msc1; + + /* If >= 0, this address is used in isoburn_disc_track_lba_nwa() + as reply parameter nwa. + (The other nwa parameters below apply only to the effective write address + on random access media. msc2 is handed to libisofs but not to libburn.) + */ + int fabricated_msc2; + + + /* The nwa to be used for a first session on the present kind of overwriteable + media (usually Libisoburn_overwriteable_starT, but might be forced to 0) + */ + int zero_nwa; + + /* Start address as given by image examination (bytes, not blocks) */ + off_t min_start_byte; + + /* Aligned start address to be used for processing (counted in blocks) */ + int nwa; + + + /* Truncate to .nwa an eventual regular file serving as output drive */ + int truncate; + + /* Eventual freely fabricated isoburn_disc_get_status(). + BURN_DISC_UNREADY means that this variable is disabled + and normally emulated status is in effect. + */ + enum burn_disc_status fabricated_disc_status; + + /* Eventual emulated table of content read from the chain of ISO headers + on overwriteable media. + */ + struct isoburn_toc_entry *toc; + + /* Indicator wether the most recent burn run worked : + -1 = undetermined, ask libburn , 0 = failure , 1 = success + To be inquired by isoburn_drive_wrote_well() + */ + int wrote_well; + + + /* Buffered ISO head from media (should that become part of + ecma119_read_opts ?) */ + uint8_t target_iso_head[Libisoburn_target_head_sizE]; + + /* Libisofs image context */ + IsoImage *image; + + /* The block data source from which the existing image is read. + */ + IsoDataSource *iso_data_source; + + /* The burn source which transfers data from libisofs to libburn. + It has its own fifo. + */ + struct burn_source *iso_source; + + /* For iso_tree_set_report_callback() */ + int (*read_pacifier)(IsoImage*, IsoFileSource*); + + /* For iso_image_attach_data() */ + void *read_pacifier_handle; + + /* An application provided method to immediately deliver messages */ + int (*msgs_submit)(void *handle, int error_code, char msg_text[], + int os_errno, char severity[], int flag); + void *msgs_submit_handle; /* specific to application method */ + int msgs_submit_flag; /* specific to application method */ + +}; + + +/* Creation and disposal function */ +int isoburn_new(struct isoburn **objpt, int flag); +int isoburn_destroy(struct isoburn **objpt, int flag); + +/* Eventual readers for public attributes */ +/* ( put into separate .h file then ) */ +int isoburn_get_emulation_mode(struct isoburn *o, int *pt, int flag); +int isoburn_get_target_volset(struct isoburn *o, IsoImage **pt, int flag); + +/* List management */ +int isoburn_get_prev(struct isoburn *o, struct isoburn **pt, int flag); +int isoburn_get_next(struct isoburn *o, struct isoburn **pt, int flag); +int isoburn_destroy_all(struct isoburn **objpt, int flag); +int isoburn_link(struct isoburn *o, struct isoburn *link, int flag); +int isoburn_count(struct isoburn *o, int flag); +int isoburn_by_idx(struct isoburn *o, int idx, struct isoburn **pt, int flag); +int isoburn_find_by_drive(struct isoburn **pt, struct burn_drive *d, int flag); + + +/* Non API inner interfaces */ + +/* Submit a libisofs error to the libburn messenger. An application message + reader shall recognize the error code range and attribute it to the + libisofs message channel to which one cannot submit via API. + @param iso_error_code return value <= 0 from a libisofs API call. + @param default_msg_text is to be put out if iso_error_code leads to no + error message + @param os_errno operating system errno, submit 0 if none is known + @param min_severity minimum severity, might be be increased if libisofs + error severity surpasses min_severity. + @param flag Bitfield, submit 0 for now +*/ +int isoburn_report_iso_error(int iso_error_code, char default_msg_text[], + int os_errno, char min_severity[], int flag); + +/* Calls from burn_wrap.c into isofs_wrap.c */ + +int isoburn_start_emulation(struct isoburn *o, int flag); +int isoburn_invalidate_iso(struct isoburn *o, int flag); + + +/* Calls from isofs_wrap.c into burn_wrap.c */ + +/** Get an eventual isoburn object which is wrapped around the drive. + @param pt Eventually returns a pointer to the found object. + It is allowed to become NULL if return value is -1 or 0. + In this case, the drive is a genuine libburn drive + with no emulation activated by isoburn. + @param drive The drive to be searched for + @param flag unused yet + @return -1 unsuitable media, 0 generic media, 1 emulated media. +*/ +int isoburn_find_emulator(struct isoburn **pt, + struct burn_drive *drive, int flag); + +/* Deliver an event message. Either via a non-NULL o->msgs_submit() method + or via burn_msgs_submit() of libburn. +*/ +int isoburn_msgs_submit(struct isoburn *o, int error_code, char msg_text[], + int os_errno, char severity[], int flag); + +/** Set the start address for an emulated add-on session. The value will + be rounded up to the alignment necessary for the media. The aligned + value will be divided by 2048 and then put into o->nwa . + @param o The isoburn object to be programmed. + @param value The start address in bytes + @param flag unused yet + @return <=0 is failure , >0 success +*/ +int isoburn_set_start_byte(struct isoburn *o, off_t value, int flag); + +/** Obtains the image address offset to be used with image generation. + This is either the (emulated) drive nwa or a value set by + isoburn_prepare_blind_grow(). + In any case this is the address to tell to iso_write_opts_set_ms_block(). + @param o The isoburn object to be inquired + @param opts If not NULL: write parameters to be set on drive before query + @param msc2 The value to be used with iso_write_opts_set_ms_block() + @param flag unused yet + @return <=0 is failure , >0 success +*/ +int isoburn_get_msc2(struct isoburn *o, + struct burn_write_opts *opts, int *msc2, int flag); + +/** Get a data source suitable for read from a drive using burn_read_data() + function. + @param d drive to read from. Must be grabbed. + @return the data source, NULL on error. Must be freed with libisofs + iso_data_source_unref() function. Note: this doesn't release + the drive. +*/ +IsoDataSource * +isoburn_data_source_new(struct burn_drive *d); + +/** Disable read capabilities of a data source which was originally created + by isoburn_data_source_new(). After this any attempt to read will yield + a FATAL programming error event. + This is usually done to allow libburn to release the drive while libisofs + still holds a reference to the data source object. libisofs is not supposed + to use this object for reading any more, nevertheless. The disabled state + of the data source is a safety fence around this daring situation. + @param src The data source to be disabled + @param flag unused yet + @return <=0 is failure , >0 success +*/ +int isoburn_data_source_shutdown(IsoDataSource *src, int flag); + + +/** + * Options for image reading. + (Comments here may be outdated. API getter/setter function descriptions + may override the descriptions here. Any difference is supposed to be a + minor correction only.) + */ +struct isoburn_read_opts { + unsigned int norock:1; /*< Do not read Rock Ridge extensions */ + unsigned int nojoliet:1; /*< Do not read Joliet extensions */ + unsigned int noiso1999:1; /*< Do not read ISO 9660:1999 enhanced tree */ + unsigned int preferjoliet:1; + /*< When both Joliet and RR extensions are present, the RR + * tree is used. If you prefer using Joliet, set this to 1. */ + uid_t uid; /**< Default uid when no RR */ + gid_t gid; /**< Default uid when no RR */ + mode_t mode; /**< Default mode when no RR (only permissions) */ + mode_t dirmode; /**< Default mode for directories + when no RR (only permissions) */ + + /** + * Input charset for RR file names. NULL to use default locale charset. + */ + char *input_charset; + + /* modified by the function isoburn_read_image */ + unsigned int hasRR:1; /*< It will be set to 1 if RR extensions are present, + to 0 if not. */ + unsigned int hasJoliet:1; /*< It will be set to 1 if Joliet extensions are + present, to 0 if not. */ + + /** + * It will be set to 1 if the image is an ISO 9660:1999, i.e. it has + * a version 2 Enhanced Volume Descriptor. + */ + unsigned int hasIso1999:1; + + /** It will be set to 1 if El-Torito boot record is present, to 0 if not.*/ + unsigned int hasElTorito:1; + + uint32_t size; /**< Will be filled with the size (in 2048 byte block) of + * the image, as reported in the PVM. */ + unsigned int pretend_blank:1; /* always create empty image */ +}; + + +/** + * Options for image generation by libisofs and image transport to libburn. + (Comments here may be outdated. API getter/setter function descriptions + may override the descriptions here. Any difference is supposed to be a + minor correction only.) + */ +struct isoburn_imgen_opts { + + /* Options for image generation */ + + int level; /**< ISO level to write at. */ + + /** Which extensions to support. */ + unsigned int rockridge :1; + unsigned int joliet :1; + unsigned int iso1999 :1; + + /* relaxed constraints */ + + /* + * Relaxed constraints. Setting any of these to 1 break the specifications, + * but it is supposed to work on most moderns systems. Use with caution. + */ + + /** + * Omit the version number (";1") at the end of the ISO-9660 identifiers. + * Version numbers are usually not used. + */ + unsigned int omit_version_numbers :1; + + /** + * Allow ISO-9660 directory hierarchy to be deeper than 8 levels. + */ + unsigned int allow_deep_paths :1; + + /** + * Allow path in the ISO-9660 tree to have more than 255 characters. + */ + unsigned int allow_longer_paths :1; + + /** + * Allow a single file or directory hierarchy to have up to 37 characters. + * This is larger than the 31 characters allowed by ISO level 2, and the + * extra space is taken from the version number, so this also forces + * omit_version_numbers. + */ + unsigned int max_37_char_filenames :1; + + /** + * ISO-9660 forces filenames to have a ".", that separates file name from + * extension. libisofs adds it if original filename doesn't has one. Set + * this to 1 to prevent this behavior + */ + unsigned int no_force_dots :1; + + /** + * Allow lowercase characters in ISO-9660 filenames. By default, only + * uppercase characters, numbers and a few other characters are allowed. + */ + unsigned int allow_lowercase :1; + + /** + * Allow all ASCII characters to be appear on an ISO-9660 filename. Note + * that "/" and "\0" characters are never allowed, even in RR names. + */ + unsigned int allow_full_ascii :1; + + /** + * Allow paths in the Joliet tree to have more than 240 characters. + */ + unsigned int joliet_longer_paths :1; + + /** + * Store timestamps as GMT rather than in local time. + */ + unsigned int always_gmt :1; + + /** + * Write Rock Ridge info as of specification RRIP-1.10 rather than + * RRIP-1.12: signature "RRIP_1991A" rather than "IEEE_1282", + * field PX without file serial number + */ + unsigned int rrip_version_1_10 :1; + + /** + * Store as ECMA-119 Directory Record timestamp the mtime + * of the source rather than the image creation time. + */ + unsigned int dir_rec_mtime :1; + + unsigned int sort_files:1; + /**< If files should be sorted based on their weight. */ + + /** + * The following options set the default values for files and directory + * permissions, gid and uid. All these take one of three values: 0, 1 or 2. + * If 0, the corresponding attribute will be kept as set in the IsoNode. + * Unless you have changed it, it corresponds to the value on disc, so it + * is suitable for backup purposes. If set to 1, the corresponding attrib. + * will be changed by a default suitable value. Finally, if you set it to + * 2, the attrib. will be changed with the value specified in the options + * below. Note that for mode attributes, only the permissions are set, the + * file type remains unchanged. + */ + unsigned int replace_dir_mode :2; + unsigned int replace_file_mode :2; + unsigned int replace_uid :2; + unsigned int replace_gid :2; + + mode_t dir_mode; /** Mode to use on dirs when replace_dir_mode == 2. */ + mode_t file_mode; /** Mode to use on files when replace_file_mode == 2. */ + uid_t uid; /** uid to use when replace_uid == 2. */ + gid_t gid; /** gid to use when replace_gid == 2. */ + + char *output_charset; /**< NULL to use default charset */ + + + /* Options for image transport */ + + /** The number of bytes to be used for the fifo which decouples libisofs + and libburn for better throughput and for reducing the risk of + interrupting signals hitting the libburn thread which operates the + MMC drive. + The size will be rounded up to the next full 2048. + Minimum is 64kiB, maximum is 1 GiB (but that is too much anyway). + */ + int fifo_size; + + + /** Output value: Block address of session start as evaluatedfrom media + and other options by libisoburn and libburn. + If <0 : Invalid + If >=0: Valid block number. Block size is always 2 KiB. + */ + int effective_lba; +}; + + +/* Alignment for session starts on overwriteable media. + (Increased from 16 to 32 blocks for aligning to BD-RE clusters.) +*/ +#define Libisoburn_nwa_alignemenT 32 + + +/* Alignment for outer session scanning with -ROM drives. + (E.g. my DVD-ROM drive shows any DVD type as 0x10 "DVD-ROM" with + more or less false capacity and TOC.) +*/ +#define Libisoburn_toc_scan_alignemenT 16 + +/* Maximum gap to be bridged during a outer TOC scan. Gaps appear between the + end of a session and the start of the next session. + The longest gap found so far was about 38100 after the first session of a + DVD-R. +*/ +#define Libisoburn_toc_scan_max_gaP 65536 + + +/* Creating a chain of image headers which form a TOC: + + The header of the first session is written after the LBA 0 header. + So it persists and can give the end of its session. By help of + Libisoburn_nwa_alignemenT it should be possible to predict the start + of the next session header. + The LBA 0 header is written by isoburn_activate_session() already + with the first session. So the media is mountable. + A problem arises with DVD-RW in Intermediate State. They cannot be + written by random access before they were written sequentially. + In this case, no copy of the session 1 header is maintained and no TOC + will be possible. Thus writing begins sequentially at LBA 0. +*/ +#define Libisoburn_overwriteable_starT \ + ((off_t) (Libisoburn_target_head_sizE/2048)) + + +/* Wrappers for emulation of TOC on overwriteable media */ + +struct isoburn_toc_track { + /* Either track or toc_entry are supposed to be NULL */ + struct burn_track *track; + struct isoburn_toc_entry *toc_entry; +}; + +struct isoburn_toc_session { + /* Either session or tracks and toc_entry are supposed to be NULL */ + struct burn_session *session; + struct isoburn_toc_track **track_pointers; + int track_count; + struct isoburn_toc_entry *toc_entry; +}; + +struct isoburn_toc_disc { + /* Either disc or sessions and toc are supposed to be NULL */ + struct burn_disc *disc; + struct isoburn_toc_session *sessions; /* storage array */ + struct isoburn_toc_session **session_pointers; /* storage array */ + struct isoburn_toc_track *tracks; /* storage array */ + struct isoburn_toc_track **track_pointers; /* storage array */ + int session_count; + int track_count; + struct isoburn_toc_entry *toc; +}; + +#endif /* Isoburn_includeD */ + diff --git a/libisoburn/branches/ZeroThreeTwo/libisoburn/isofs_wrap.c b/libisoburn/branches/ZeroThreeTwo/libisoburn/isofs_wrap.c new file mode 100644 index 00000000..c5443212 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/libisoburn/isofs_wrap.c @@ -0,0 +1,407 @@ + +/* + cc -g -c isofs_wrap.c +*/ + +/* + libisofs related functions of libisoburn. + + Copyright 2007 - 2008 Vreixo Formoso Lopes + Thomas Schmitt +*/ + +#include +#include +#include + +#ifndef Xorriso_standalonE + +#include + +#include + +#else /* ! Xorriso_standalonE */ + +#include "../libisofs/libisofs.h" +#include "../libburn/libburn.h" + +#endif /* Xorriso_standalonE */ + +#include "isoburn.h" +#include "libisoburn.h" + +#define BP(a,b) [(b) - (a) + 1] + +struct ecma119_pri_vol_desc +{ + uint8_t vol_desc_type BP(1, 1); + uint8_t std_identifier BP(2, 6); + uint8_t vol_desc_version BP(7, 7); + uint8_t unused1 BP(8, 8); + uint8_t system_id BP(9, 40); + uint8_t volume_id BP(41, 72); + uint8_t unused2 BP(73, 80); + uint8_t vol_space_size BP(81, 88); + uint8_t unused3 BP(89, 120); + uint8_t vol_set_size BP(121, 124); + uint8_t vol_seq_number BP(125, 128); + uint8_t block_size BP(129, 132); + uint8_t path_table_size BP(133, 140); + uint8_t l_path_table_pos BP(141, 144); + uint8_t opt_l_path_table_pos BP(145, 148); + uint8_t m_path_table_pos BP(149, 152); + uint8_t opt_m_path_table_pos BP(153, 156); + uint8_t root_dir_record BP(157, 190); + uint8_t vol_set_id BP(191, 318); + uint8_t publisher_id BP(319, 446); + uint8_t data_prep_id BP(447, 574); + uint8_t application_id BP(575, 702); + uint8_t copyright_file_id BP(703, 739); + uint8_t abstract_file_id BP(740, 776); + uint8_t bibliographic_file_id BP(777, 813); + uint8_t vol_creation_time BP(814, 830); + uint8_t vol_modification_time BP(831, 847); + uint8_t vol_expiration_time BP(848, 864); + uint8_t vol_effective_time BP(865, 881); + uint8_t file_structure_version BP(882, 882); + uint8_t reserved1 BP(883, 883); + uint8_t app_use BP(884, 1395); + uint8_t reserved2 BP(1396, 2048); +}; + +static +uint32_t iso_read_lsb(const uint8_t *buf, int bytes) +{ + int i; + uint32_t ret = 0; + + for (i=0; iimage); + return o->image; +} + + +static void isoburn_idle_free_function(void *ignored) +{ + return; +} + + +/* API function. See libisoburn.h +*/ +int isoburn_read_image(struct burn_drive *d, + struct isoburn_read_opts *read_opts, + IsoImage **image) +{ + int ret, int_num, dummy; + IsoReadOpts *ropts= NULL; + IsoReadImageFeatures *features= NULL; + uint32_t ms_block; + char msg[160]; + enum burn_disc_status status= BURN_DISC_BLANK; + IsoDataSource *ds= NULL; + struct isoburn *o= NULL; + + if(d != NULL) { + ret = isoburn_find_emulator(&o, d, 0); + if (ret < 0 || o == NULL) + return 0; + status = isoburn_disc_get_status(d); + } + if(read_opts==NULL) { + isoburn_msgs_submit(o, 0x00060000, + "Program error: isoburn_read_image: read_opts==NULL", + 0, "FATAL", 0); + return(-1); + } + if (d == NULL || status == BURN_DISC_BLANK || read_opts->pretend_blank) { +create_blank_image:; + /* + * Blank disc, we create a new image without files. + */ + + if (d == NULL) { + /* New empty image without relation to a drive */ + if (image==NULL) { + isoburn_msgs_submit(o, 0x00060000, + "Program error: isoburn_read_image: image==NULL", + 0, "FATAL", 0); + return -1; + } + /* create a new image */ + ret = iso_image_new("ISOIMAGE", image); + if (ret < 0) { + isoburn_report_iso_error(ret, "Cannot create image", 0, "FATAL", 0); + return ret; + } + } else { + /* Blank new image for the drive */ + iso_image_unref(o->image); + ret = iso_image_new("ISOIMAGE", &o->image); + if (ret < 0) { + isoburn_report_iso_error(ret, "Cannot create image", 0, "FATAL", 0); + return ret; + } + if (image) { + *image = o->image; + iso_image_ref(*image); /*protects object from premature free*/ + } + } + return 1; + } + + if (status != BURN_DISC_APPENDABLE && status != BURN_DISC_FULL) { + isoburn_msgs_submit(o, 0x00060000, + "Program error: isoburn_read_image: incorrect disc status", + 0, "FATAL", 0); + return -4; + } + + memset((char *) &ropts, 0, sizeof(ropts)); + + ret = isoburn_disc_get_msc1(d, &int_num); + if (ret <= 0) + return -2; + ms_block= int_num; + ret = isoburn_read_iso_head(d, int_num, &dummy, NULL, 0); + if (ret <= 0) { + sprintf(msg, "No ISO 9660 image at LBA %d. Creating blank image.", int_num); + isoburn_msgs_submit(o, 0x00060000, msg, 0, "WARNING", 0); + goto create_blank_image; + } + + /* create the data source */ + ret = iso_read_opts_new(&ropts, 0); + if (ret < 0) { + isoburn_report_iso_error(ret, "Cannot create write opts", 0, "FATAL", 0); + return ret; + } + /* Important: do not return until iso_read_opts_free() */ + iso_read_opts_set_start_block(ropts, ms_block); + iso_read_opts_set_no_rockridge(ropts, read_opts->norock); + iso_read_opts_set_no_joliet(ropts, read_opts->nojoliet); + iso_read_opts_set_no_iso1999(ropts, read_opts->noiso1999); + iso_read_opts_set_preferjoliet(ropts, read_opts->preferjoliet); + iso_read_opts_set_default_permissions(ropts, + read_opts->mode, read_opts->dirmode); + iso_read_opts_set_default_uid(ropts, read_opts->uid); + iso_read_opts_set_default_gid(ropts, read_opts->gid); + iso_read_opts_set_input_charset(ropts, read_opts->input_charset); + + /* <<< experimental API call of libisofs + iso_read_opts_set_error_behavior(ropts, 1); + */ + + ds = isoburn_data_source_new(d); + if(o->iso_data_source!=NULL) + iso_data_source_unref(o->iso_data_source); + o->iso_data_source= ds; + iso_image_attach_data(o->image, o->read_pacifier_handle, + isoburn_idle_free_function); + if(o->read_pacifier_handle==NULL) + iso_tree_set_report_callback(o->image, NULL); + else + iso_tree_set_report_callback(o->image, o->read_pacifier); + ret = iso_image_import(o->image, ds, ropts, &features); + iso_tree_set_report_callback(o->image, NULL); + iso_read_opts_free(ropts); + + if (ret < 0) { + isoburn_report_iso_error(ret, "Cannot import image", 0, "FAILURE", 0); + return ret; + } + /* Important: do not return until free(features) */ + if (image!=NULL) { + *image = o->image; + iso_image_ref(*image); /*protects object from premature free*/ + } + read_opts->hasRR = iso_read_image_features_has_rockridge(features); + read_opts->hasJoliet = iso_read_image_features_has_joliet(features); + read_opts->hasIso1999 = iso_read_image_features_has_iso1999(features); + read_opts->hasElTorito = iso_read_image_features_has_eltorito(features); + read_opts->size = iso_read_image_features_get_size(features); + iso_read_image_features_destroy(features); + return 1; +} + + +/* API function. See libisoburn.h +*/ +int isoburn_attach_image(struct burn_drive *d, IsoImage *image) +{ + int ret; + struct isoburn *o; + + ret = isoburn_find_emulator(&o, d, 0); + if (ret < 0 || o == NULL) + return 0; + if (image == NULL) { + isoburn_msgs_submit(o, 0x00060000, + "Program error: isoburn_attach_image: image==NULL", + 0, "FATAL", 0); + return -1; + } + if(o->image != NULL) + iso_image_unref(o->image); + o->image = image; + return(1); +} + + +/* API function. See libisoburn.h +*/ +int isoburn_activate_session(struct burn_drive *drive) +{ + int ret; + struct isoburn *o; + + ret = isoburn_find_emulator(&o, drive, 0); + if (ret < 0) + return -1; + + if (o->emulation_mode != 1) + return 1; /* don't need to activate session */ + if (o->fabricated_msc2 >= 0) + return 1; /* blind growing: do not alter anything outside the session */ + + if (!(o->fabricated_disc_status == BURN_DISC_APPENDABLE || + (o->fabricated_disc_status == BURN_DISC_BLANK && + o->zero_nwa > 0))) + return 1; + + ret = burn_random_access_write(drive, (off_t) 0, (char*)o->target_iso_head, + Libisoburn_target_head_sizE, 1); + + return ret; +} + + +/** Initialize the emulation of multi-session on random access media. + The need for emulation is confirmed already. + @param o A freshly created isoburn object. isoburn_create_data_source() was + already called, nevertheless. + @return <=0 error , 1 = success +*/ +int isoburn_start_emulation(struct isoburn *o, int flag) +{ + int ret, i; + off_t data_count; + struct burn_drive *drive; + struct ecma119_pri_vol_desc *pvm; + + if(o==NULL) { + isoburn_msgs_submit(NULL, 0x00060000, + "Program error: isoburn_start_emulation: o==NULL", + 0, "FATAL", 0); + return -1; + } + + drive= o->drive; + + /* we can assume 0 as start block for image */ + /* TODO what about ms? where we validate valid iso image in ms disc? */ + ret = burn_read_data(drive, (off_t) 0, (char*)o->target_iso_head, + (off_t) Libisoburn_target_head_sizE, &data_count, 2); + + /* an error means an empty disc */ + if (ret <= 0) { + o->fabricated_disc_status= BURN_DISC_BLANK; + return 1; + } + + /* check first 64K. If 0's, the disc is treated as a blank disc, and thus + overwritten without extra check. */ + i = Libisoburn_target_head_sizE; + while (i && !o->target_iso_head[i-1]) + --i; + + if (!i) { + o->fabricated_disc_status= BURN_DISC_BLANK; + return 1; + } + + pvm = (struct ecma119_pri_vol_desc *)(o->target_iso_head + 16 * 2048); + + if (!strncmp((char*)pvm->std_identifier, "CD001", 5)) { + off_t size; + + /* sanity check */ + if (pvm->vol_desc_type[0] != 1 || pvm->vol_desc_version[0] != 1 + || pvm->file_structure_version[0] != 1 ) { + /* TODO for now I treat this as a full disc */ + o->fabricated_disc_status= BURN_DISC_FULL; + return 1; + } + + /* ok, PVM found, set size */ + size = (off_t) iso_read_lsb(pvm->vol_space_size, 4); + size *= (off_t) 2048; /* block size in bytes */ + isoburn_set_start_byte(o, size, 0); + o->fabricated_disc_status= BURN_DISC_APPENDABLE; + } else if (!strncmp((char*)pvm->std_identifier, "CDXX1", 5)) { + + /* empty image */ + isoburn_set_start_byte(o, o->zero_nwa * 2048, 0); + o->fabricated_disc_status= BURN_DISC_BLANK; + } else { + /* treat any disc in an unknown format as full */ + o->fabricated_disc_status= BURN_DISC_FULL; + } + return 1; +} + + +/** Alters and writes the first 64 kB of a "media" to invalidate + an ISO image. (It shall stay restorable by skilled humans, though). + The result shall especially keep libisoburn from accepting the media + image as ISO filesystem. + @param o A fully activated isoburn object. isoburn_start_emulation() + was already called. + @return <=0 error , 1 = success +*/ +int isoburn_invalidate_iso(struct isoburn *o, int flag) +{ + /* + * replace CD001 with CDXX1 in PVM. + * I think this is enought for invalidating an iso image + */ + strncpy((char*)o->target_iso_head + 16 * 2048 + 1, "CDXX1", 5); + return isoburn_activate_session(o->drive); +} + + +/* API @since 0.1.0 */ +int isoburn_set_read_pacifier(struct burn_drive *drive, + int (*read_pacifier)(IsoImage*, IsoFileSource*), + void *read_handle) +{ + int ret; + struct isoburn *o; + + ret = isoburn_find_emulator(&o, drive, 0); + if(ret < 0 || o == NULL) + return -1; + o->read_pacifier_handle= read_handle; + o->read_pacifier= read_pacifier; + return(1); +} + diff --git a/libisoburn/branches/ZeroThreeTwo/libisoburn/libisoburn.h b/libisoburn/branches/ZeroThreeTwo/libisoburn/libisoburn.h new file mode 100644 index 00000000..e16234d3 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/libisoburn/libisoburn.h @@ -0,0 +1,1367 @@ + +/* + API definition of libisoburn. + + Copyright 2007-2008 Vreixo Formoso Lopes + and Thomas Schmitt +*/ + +/** Overview + +libisoburn is a frontend for libraries libburn and libisofs which enables +creation and expansion of ISO-9660 filesystems on all CD/DVD media supported +by libburn. This includes media like DVD+RW, which do not support multi-session +management on media level and even plain disk files or block devices. + +The price for that is thorough specialization on data files in ISO-9660 +filesystem images. So libisoburn is not suitable for audio (CD-DA) or any +other CD layout which does not entirely consist of ISO-9660 sessions. + + + Connector functions + +libisofs and libburn do not depend on each other but share some interfaces +by which they can cooperate. +libisoburn establishes the connection between both modules by creating the +necessary interface objects and attaching them to the right places. + + + Wrapper functions + +The priciple of this frontend is that you may use any call of libisofs or +libburn unless it has a isoburn_*() wrapper listed in the following function +documentation. + +E.g. call isoburn_initialize() rather than iso_init(); burn_initialize(); +and call isoburn_drive_scan_and_grab() rather than burn_drive_scan_and_grab(). +But you may call burn_disc_get_profile() directly if you want to display +the media type. + +The wrappers will transparently provide the necessary emulations which +are appropriate for particular target drives and media states. +To learn about them you have to read both API descriptions: the one of +the wrapper and the one of the underlying libburn or libisofs call. + +Macros BURN_* and functions burn_*() are documented in +Macros ISO_* and functions iso_*() are documented in + + + Usage model + +There may be an input drive and an output drive. Either of them may be missing +with the consequence that no reading resp. writing is possible. +Both drive roles can be fulfilled by the same drive. + +Input can be a random access readable libburn drive: + optical media, regular files, block devices. +Output can be any writeable libburn drive: + writeable optical media in burner, writeable file objects (no directories). + +libburn demands rw-permissions to drive device file resp. file object. + +If the input drive provides a suitable ISO RockRidge image, then its tree +may be loaded into memory and can then be manipulated by libisofs API calls. +The loading is done by isoburn_read_image() under control of +struct isoburn_read_opts which the application obtains from libisoburn +and manipulates by the family of isoburn_ropt_set_*() functions. + +Writing of result images is controlled by libisofs related parameters +in a struct isoburn_imgen_opts which the application obtains from libisoburn +and manipulates by the family of isoburn_igopt_set_*() functions. + +All multi-session aspects are handled by libisoburn according to these +settings. The application does not have to analyze media state and write +job parameters. It rather states its desires which libisoburn tries to +fulfill, or else will refuse to start the write run. + + + Setup for Growing, Modifying or Blind Growing + +The connector function family offers alternative API calls for performing +the setup for several alternative image generation strategies. + +Growing: +If input and output drive are the same, then isoburn_prepare_disc() is to +be used. It will lead to an add-on session on appendable or overwriteable +media with existing ISO image. With blank media it will produce a first +session. + +Modifying: +If the output drive is not the input drive, and if it bears blank media +or overwriteable without a valid ISO image, then one may produce a consolidated +image with old and new data. This will copy file data from an eventual input +drive with valid image, add any newly introduced data from the local +filesystem, and produce a first session on output media. +To prepare for such an image generation run, use isoburn_prepare_new_image(). + +Blind Growing: +This method reads the old image from one drive and writes the add-on session +to a different drive. That output drive is nevertheless supposed to +finally lead to the same media from where the session was loaded. Usually it +will be stdio:/dev/fd/1 (i.e. stdout) being piped into some burn program +like with this classic gesture: + mkisofs -M $dev -C $msc1,$nwa | cdrecord -waiti dev=$dev +Blind growing is prepared by the call isoburn_prepare_blind_grow(). +The input drive should be released immediately after this call in order +to allow the consumer of the output stream to access that drive for writing. + +After either of these setups, some peripheral libburn drive parameter settings +like burn_write_opts_set_simulate(), burn_write_opts_set_multi(), + burn_drive_set_speed(), burn_write_opts_set_underrun_proof() should be made. +Do not set the write mode. It will be chosen by libisoburn so it matches job +and media state. + + Writing the image + +Then one may start image generation and write threads by isoburn_disc_write(). +Progress may be watched at the output drive by burn_drive_get_status() and +isoburn_get_fifo_status(). + +At some time, the output drive will be BURN_DRIVE_IDLE indicating that +writing has ended. +One should inquire isoburn_drive_wrote_well() to learn about overall success. + +Finally one must call isoburn_activate_session() which will complete any +eventual multi-session emulation. + +*/ + + + /* API functions */ + + +/** Initialize libisoburn, libisofs and libburn. + Wrapper for : iso_init() and burn_initialize() + @since 0.1.0 + @param msg A character array for eventual messages (e.g. with errors) + @param flag Bitfield for control purposes (unused yet, submit 0) + @return 1 indicates success, 0 is failure +*/ +int isoburn_initialize(char msg[1024], int flag); + + +/** Check whether all features of header file libisoburn.h from the given + major.minor.micro revision triple can be delivered by the library version + which is performing this call. + An application of libisoburn can easily memorize the version of the + libisofs.h header in its own code. Immediately after isoburn_initialize() + it should simply do this check: + if (! isoburn_is_compatible(isoburn_header_version_major, + isoburn_header_version_minor, + isoburn_header_version_micro, 0)) + ...refuse to start the program with this dynamic library version... + @since 0.1.0 + @param major obtained at build time + @param minor obtained at build time + @param micro obtained at build time + @param flag Bitfield for control purposes. Unused yet. Submit 0. + @return 1= library can work for caller + 0= library is not usable in some aspects. Caller must restrict + itself to an earlier API version or must not use this libray + at all. +*/ +int isoburn_is_compatible(int major, int minor, int micro, int flag); + + +/** Obtain the three release version numbers of the library. These are the + numbers encountered by the application when linking with libisoburn, + i.e. possibly not before run time. + Better do not base the fundamental compatibility decision of an application + on these numbers. For a reliable check use isoburn_is_compatible(). + @since 0.1.0 + @param major The maturity version (0 for now, as we are still learning) + @param minor The development goal version. + @param micro The development step version. This has an additional meaning: + + Pare numbers indicate a version with frozen API. I.e. you can + rely on the same set of features to be present in all + published releases with that major.minor.micro combination. + Features of a pare release will stay available and ABI + compatible as long as the SONAME of libisoburn stays "1". + Currently there are no plans to ever change the SONAME. + + Odd numbers indicate that API upgrades are in progress. + I.e. new features might be already present or they might + be still missing. Newly introduced features may be changed + incompatibly or even be revoked before release of a pare + version. + So micro revisions {1,3,5,7,9} should never be used for + dynamic linking unless the proper library match can be + guaranteed by external circumstances. + + @return 1 success, <=0 might in future become an error indication +*/ +void isoburn_version(int *major, int *minor, int *micro); + + +/** The minimum version of libisofs to be used with this version of libisoburn + at compile time. + @since 0.1.0 +*/ +#define isoburn_libisofs_req_major 0 +#define isoburn_libisofs_req_minor 6 +#define isoburn_libisofs_req_micro 12 + +/** The minimum version of libburn to be used with this version of libisoburn + at compile time. + @since 0.1.0 +*/ +#define isoburn_libburn_req_major 0 +#define isoburn_libburn_req_minor 5 +#define isoburn_libburn_req_micro 9 + + +/** The minimum version of libisofs to be used with this version of libisoburn + at runtime. This is checked already in isoburn_initialize() which will + refuse on outdated version. So this call is for information purposes after + successful startup only. + @since 0.1.0 + @param major isoburn_libisofs_req_major as seen at build time + @param minor as seen at build time + @param micro as seen at build time + @return 1 success, <=0 might in future become an error indication +*/ +int isoburn_libisofs_req(int *major, int *minor, int *micro); + + +/** The minimum version of libburn to be used with this version of libisoburn + at runtime. This is checked already in isoburn_initialize() which will + refuse on outdated version. So this call is for information purposes after + successful startup only. + @since 0.1.0 + @param major isoburn_libburn_req_major as seen at build time + @param minor as seen at build time + @param micro as seen at build time + @return 1 success, <=0 might in future become an error indication +*/ +int isoburn_libburn_req(int *major, int *minor, int *micro); + + +/** These three release version numbers tell the revision of this header file + and of the API it describes. They are memorized by applications at build + time. + @since 0.1.0 +*/ +#define isoburn_header_version_major 0 +#define isoburn_header_version_minor 3 +#define isoburn_header_version_micro 1 +/** Note: + Above version numbers are also recorded in configure.ac because libtool + wants them as parameters at build time. + For the library compatibility check, ISOBURN_*_VERSION in configure.ac + are not decisive. Only the three numbers here do matter. +*/ +/** Usage discussion: + +Some developers of the libburnia project have differing +opinions how to ensure the compatibility of libaries +and applications. + +It is about whether to use at compile time and at runtime +the version numbers isoburn_header_version_* provided here. +Thomas Schmitt advises to use them. +Vreixo Formoso advises to use other means. + +At compile time: + +Vreixo Formoso advises to leave proper version matching +to properly programmed checks in the the application's +build system, which will eventually refuse compilation. + +Thomas Schmitt advises to use the macros defined here +for comparison with the application's requirements of +library revisions and to eventually break compilation. + +Both advises are combinable. I.e. be master of your +build system and have #if checks in the source code +of your application, nevertheless. + +At runtime (via *_is_compatible()): + +Vreixo Formoso advises to compare the application's +requirements of library revisions with the runtime +library. This is to allow runtime libraries which are +young enough for the application but too old for +the lib*.h files seen at compile time. + +Thomas Schmitt advises to compare the header +revisions defined here with the runtime library. +This is to enforce a strictly monotonous chain +of revisions from app to header to library, +at the cost of excluding some older libraries. + +These two advises are mutually exclusive. + +----------------------------------------------------- + +For an implementation of the Thomas Schmitt approach, +see libisoburn/burn_wrap.c : isoburn_initialize() +This connects libisoburn as "application" with libisofs +as "library". + +The compatible part of Vreixo Formoso's approach is implemented +in configure.ac LIBBURN_REQUIRED, LIBISOFS_REQUIRED. +In isoburn_initialize() it would rather test by + iso_lib_is_compatible(isoburn_libisofs_req_major,... +than by + iso_lib_is_compatible(iso_lib_header_version_major,... +and would leave out the ugly compile time traps. + +*/ + + +/** Announce to the library an application provided method for immediate + delivery of messages. It is used when no drive is affected directly or + if the drive has no own msgs_submit() method attached by + isoburn_drive_set_msgs_submit. + If no method is preset or if the method is set to NULL then libisoburn + delivers its messages through the message queue of libburn. + @param msgs_submit The function call which implements the method + @param submit_handle Handle to be used as first argument of msgs_submit + @param submit_flag Flag to be used as last argument of msgs_submit + @param flag Unused yet, submit 0 + @since 0.2.0 +*/ +int isoburn_set_msgs_submit(int (*msgs_submit)(void *handle, int error_code, + char msg_text[], int os_errno, + char severity[], int flag), + void *submit_handle, int submit_flag, int flag); + + +/** Aquire a target drive by its filesystem path resp. libburn persistent + address. + Wrapper for: burn_drive_scan_and_grab() + @since 0.1.0 + @param drive_infos On success returns a one element array with the drive + (cdrom/burner). Thus use with driveno 0 only. On failure + the array has no valid elements at all. + The returned array should be freed via burn_drive_info_free() + when the drive is no longer needed. But before this is done + one has to call isoburn_drive_release(drive_infos[0].drive). + @param adr The persistent address of the desired drive. + @param load 1 attempt to load the disc tray. 0 no attempt,rather failure. + @return 1 = success , 0 = drive not found , <0 = other error +*/ +int isoburn_drive_scan_and_grab(struct burn_drive_info *drive_infos[], + char* adr, int load); + + +/** Aquire a target drive by its filesystem path resp. libburn persistent + address. This is a modern successor of isoburn_drive_scan_and_grab(). + Wrapper for: burn_drive_scan_and_grab() + @since 0.1.2 + @param drive_infos On success returns a one element array with the drive + (cdrom/burner). Thus use with driveno 0 only. On failure + the array has no valid elements at all. + The returned array should be freed via burn_drive_info_free() + when the drive is no longer needed. But before this is done + one has to call isoburn_drive_release(drive_infos[0].drive). + @param adr The persistent address of the desired drive. + @param flag bit0= attempt to load the disc tray. + Else: failure if not loaded. + bit1= regard overwriteable media as blank + bit2= if the drive is a regular disk file: truncate it to + the write start address + bit3= if the drive reports a read-only profile try to read + table of content by scanning for ISO image headers. + (depending on media type and drive this might + help or it might make the resulting toc even worse) + bit4= do not emulate table of content on overwriteable media + @return 1 = success , 0 = drive not found , <0 = other error +*/ +int isoburn_drive_aquire(struct burn_drive_info *drive_infos[], + char* adr, int flag); + +/** Aquire a drive from the burn_drive_info[] array which was obtained by + a previous call of burn_drive_scan(). + Wrapper for: burn_drive_grab() + @since 0.1.0 + @param drive The drive to grab. E.g. drive_infos[1].drive . + Call isoburn_drive_release(drive) when it it no longer needed. + @param load 1 attempt to load the disc tray. 0 no attempt, rather failure. + @return 1 success, <=0 failure +*/ +int isoburn_drive_grab(struct burn_drive *drive, int load); + + +/** Attach to a drive an application provided method for immediate + delivery of messages. + If no method is set or if the method is set to NULL then libisoburn + delivers messages of the drive through the global msgs_submit() method + set by isoburn_set_msgs_submiti() or by the message queue of libburn. + @since 0.2.0 + @param d The drive to which this function, handle and flag shall apply + @param msgs_submit The function call which implements the method + @param submit_handle Handle to be used as first argument of msgs_submit + @param submit_flag Flag to be used as last argument of msgs_submit + @param flag Unused yet, submit 0 +*/ +int isoburn_drive_set_msgs_submit(struct burn_drive *d, + int (*msgs_submit)(void *handle, int error_code, + char msg_text[], int os_errno, + char severity[], int flag), + void *submit_handle, int submit_flag, int flag); + + +/** Inquire the media status. Expect the whole spectrum of libburn BURN_DISC_* + with multi-session media. Emulated states with random access media are + BURN_DISC_BLANK and BURN_DISC_APPENDABLE. + Wrapper for: burn_disc_get_status() + @since 0.1.0 + @param drive The drive to inquire. + @return The status of the drive, or what kind of disc is in it. + Note: BURN_DISC_UNGRABBED indicates wrong API usage +*/ +enum burn_disc_status isoburn_disc_get_status(struct burn_drive *drive); + + +/** Tells whether the media can be treated by isoburn_disc_erase(). + Wrapper for: burn_disc_erasable() + @since 0.1.0 + @param drive The drive to inquire. + @return 0=not erasable , else erasable +*/ +int isoburn_disc_erasable(struct burn_drive *d); + + +/** Mark the media as blank. With multi-session media this will call + burn_disc_erase(). With random access media, an eventual ISO-9660 + filesystem will get invalidated by altering its start blocks on media. + In case of success, the media is in status BURN_DISC_BLANK afterwards. + Wrapper for: burn_disc_erase() + @since 0.1.0 + @param drive The drive with the media to erase. + @param fast 1=fast erase, 0=thorough erase + With DVD-RW, fast erase yields media incapable of multi-session. +*/ +void isoburn_disc_erase(struct burn_drive *drive, int fast); + + +/** Set up isoburn_disc_get_msc1() to return a fabricated value. + This makes only sense between aquiring the drive and reading the + image. After isoburn_read_image() it will confuse the coordination + of libisoburn and libisofs. + Note: Sessions and tracks are counted beginning with 1, not with 0. + @since 0.1.6 + @param drive The drive where msc1 is to be set + @param adr_mode Determines how to interpret adr_value and to set msc1. + If adr_value shall represent a number then decimal ASCII + digits are expected. + 0= start lba of last session in TOC, ignore adr_value + 1= start lba of session number given by adr_value + 2= start lba of track given number by adr_value + 3= adr_value itself is the lba to be used + 4= start lba of last session with volume id + given by adr_value + @param adr_value A string describing the value to be eventually used. + @param flag Bitfield for control purposes. + bit0= @since 0.2.2 + with adr_mode 3: adr_value might be 16 blocks too high + (e.g. -C stemming from growisofs). Probe for ISO head + at adr_value-16 and eventually adjust setting. + bit1= insist in seeing a disc object with at least one session + bit2= with adr_mode 4: use adr_value as regular expression +*/ +int isoburn_set_msc1(struct burn_drive *d, int adr_mode, char *adr_value, + int flag); + + +/* ----------------------------------------------------------------------- */ +/* + + Wrappers for emulation of TOC on overwriteable media + + Media which match the overwriteable usage model lack of a history of sessions + and tracks. libburn will not even hand out a burn_disc object for them and + always declare them blank. libisoburn checks for a valid ISO filesystem + header at LBA 0 and eventually declares them appendable. + Nevertheless one can only determine an upper limit of the size of the overall + image (by isoburn_get_min_start_byte()) but not a list of stored sessions + and their LBAs, as it is possible with true multi-session media. + + The following wrappers add the capability to obtain a session and track TOC + from emulated multi-session images on overwriteables if the first session + was written by libisoburn-0.1.6 or later (i.e. with a header copy at LBA 32). + + Be aware that the structs emitted by these isoburn calls are not compatible + with the libburn structs. I.e. you may use them only with isoburn_toc_* + calls. + isoburn_toc_disc needs to be freed after use. isoburn_toc_session and + isoburn_toc_track vanish together with their isoburn_toc_disc. +*/ + +/* Opaque handles to media, session, track */ +struct isoburn_toc_disc; +struct isoburn_toc_session; +struct isoburn_toc_track; + + +/** Obtain a master handle for the table of content. + This handle governs allocated resources which have to be released by + isoburn_toc_disc_free() when no longer needed. + Wrapper for: burn_drive_get_disc() + @since 0.1.6 + @param drive The drive with the media to inspect + @return NULL in case there is no content info, else it is a valid handle +*/ +struct isoburn_toc_disc *isoburn_toc_drive_get_disc(struct burn_drive *d); + + +/** Tell the number of 2048 byte blocks covered by the table of content. + This number includes the eventual gaps between sessions and tracks. + So this call is not really a wrapper for burn_disc_get_sectors(). + @since 0.1.6 + @param disc The master handle of the media + @return number of blocks, <=0 indicates unknown or unreadable state +*/ +int isoburn_toc_disc_get_sectors(struct isoburn_toc_disc *disc); + + +/** Get the array of session handles from the table of content. + Wrapper for: burn_disc_get_sessions() + @since 0.1.6 + @param disc The master handle of the media + @param num returns the number of sessions in the array + @return the address of the array of session handles +*/ +struct isoburn_toc_session **isoburn_toc_disc_get_sessions( + struct isoburn_toc_disc *disc, int *num); + + +/** Tell the number of 2048 byte blocks covered by a particular session. + Wrapper for: burn_session_get_sectors() + @since 0.1.6 + @param s The session handle + @return number of blocks, <=0 indicates unknown or unreadable state +*/ +int isoburn_toc_session_get_sectors(struct isoburn_toc_session *s); + + +/** Obtain a copy of the entry which describes the end of a particular session. + Wrapper for: burn_session_get_leadout_entry() + @since 0.1.6 + @param s The session handle + @param entry A pointer to memory provided by the caller. It will be filled + with info according to struct burn_toc_entry as defined + in libburn.h +*/ +void isoburn_toc_session_get_leadout_entry(struct isoburn_toc_session *s, + struct burn_toc_entry *entry); + + +/** Get the array of track handles from a particular session. + Wrapper for: burn_session_get_tracks() + @since 0.1.6 + @param s The session handle + @param num returns the number of tracks in the array + @return the address of the array of track handles +*/ +struct isoburn_toc_track **isoburn_toc_session_get_tracks( + struct isoburn_toc_session *s, int *num); + + +/** Obtain a copy of the entry which describes a particular track. + Wrapper for: burn_track_get_entry() + @since 0.1.6 + @param s The track handle + @param entry A pointer to memory provided by the caller. It will be filled + with info according to struct burn_toc_entry as defined + in libburn.h +*/ +void isoburn_toc_track_get_entry(struct isoburn_toc_track *t, + struct burn_toc_entry *entry); + + +/** Release the memory associated with a master handle of media. + The handle is invalid afterwards and may not be used any more. + Wrapper for: burn_disc_free() + @since 0.1.6 + @param disc The master handle of the media +*/ +void isoburn_toc_disc_free(struct isoburn_toc_disc *disc); + + +/** Try whether the data at the given address look like a ISO 9660 + image header and obtain its alleged size. Depending on the info mode + one other string of text information can be retrieved too. + @since 0.1.6 + @param drive The drive with the media to inspect + @param lba The block number from where to read + @param image_blocks The number of 2048 bytes blocks + @param info Caller provided memory, enough to take eventual info reply + @param flag bit0-7: info return mode + 0= do not return anything in info (do not even touch it) + 1= copy volume id to info (info needs 33 bytes) + 2= @since 0.2.2 : + copy 64 kB header to info (needs 65536 bytes) + bit13= @since 0.2.2: + do not read head from media but use first 64 kB from info + bit14= check both half buffers (not only second) + return 2 if found in first block + bit15= return-1 on read error + @return >0 seems to be a valid ISO image, 0 format not recognized, <0 error +*/ +int isoburn_read_iso_head(struct burn_drive *d, int lba, + int *image_blocks, char *info, int flag); + + +/** Try to convert the given entity address into various entity addresses + which would describe it. + Note: Sessions and tracks are counted beginning with 1, not with 0. + @since 0.3.2 + @param drive The drive where msc1 is to be set + @param adr_mode Determines how to interpret the input adr_value. + If adr_value shall represent a number then decimal ASCII + digits are expected. + 0= start lba of last session in TOC, ignore adr_value + 1= start lba of session number given by adr_value + 2= start lba of track given number by adr_value + 3= adr_value itself is the lba to be used + 4= start lba of last session with volume id + given by adr_value + @param adr_value A string describing the value to be eventually used. + @param lba returns the block address of the entity, -1 means invalid + @param track returns the track number of the entity, -1 means invalid + @param session returns the session number of the entity, -1 means invalid + @param volid returns the volume id of the entity if it is a ISO session + @param flag Bitfield for control purposes. + bit2= with adr_mode 4: use adr_value as regular expression + @return <=0 error , 1 ok, ISO session, 2 ok, not an ISO session +*/ +int isoburn_get_mount_params(struct burn_drive *d, + int adr_mode, char *adr_value, + int *lba, int *track, int *session, + char volid[33], int flag); + + +/* ----------------------------------------------------------------------- */ +/* + + Options for image reading. + + An application shall create an option set object by isoburn_ropt_new(), + program it by isoburn_ropt_set_*(), use it with isoburn_read_image(), + and finally delete it by isoburn_ropt_destroy(). + +*/ +/* ----------------------------------------------------------------------- */ + +struct isoburn_read_opts; + +/** Produces a set of image read options, initialized with default values. + @since 0.1.0 + @param o the newly created option set object + @param flag Bitfield for control purposes. Submit 0 for now. + @return 1=ok , <0 = failure +*/ +int isoburn_ropt_new(struct isoburn_read_opts **o, int flag); + + +/** Deletes an option set which was created by isoburn_ropt_new(). + @since 0.1.0 + @param o The option set to work on + @param flag Bitfield for control purposes. Submit 0 for now. + @return 1= **o destroyed , 0= *o was already NULL (harmless) +*/ +int isoburn_ropt_destroy(struct isoburn_read_opts **o, int flag); + + +/** Which existing ISO 9660 extensions in the image to read or not to read. + Whether to read the content of an existing image at all. + The bits can be combined by | resp. inquired by &. + @since 0.1.0 + @param ext Bitfield: + bit0= norock + Do not read Rock Ridge extensions + bit1= nojoliet + Do not read Joliet extensions + bit2= noiso1999 + Do not read ISO 9660:1999 enhanced tree + bit3= preferjoliet + When both Joliet and RR extensions are present, the RR + tree is used. If you prefer using Joliet, set this to 1. + bit4= pretend_blank + Always create empty image.Ignore any image on input drive. + @return 1 success, <=0 failure +*/ +#define isoburn_ropt_norock 1 +#define isoburn_ropt_nojoliet 2 +#define isoburn_ropt_noiso1999 4 +#define isoburn_ropt_preferjoliet 8 +#define isoburn_ropt_pretend_blank 16 +int isoburn_ropt_set_extensions(struct isoburn_read_opts *o, int ext); +int isoburn_ropt_get_extensions(struct isoburn_read_opts *o, int *ext); + + +/** Default attributes to use if no RockRidge extension gets loaded. + @since 0.1.0 + @param o The option set to work on + @param uid user id number (see /etc/passwd) + @param gid group id number (see /etc/group) + @param mode permissions (not file type) as of man 2 stat. + With directories, r-permissions will automatically imply + x-permissions. See isoburn_ropt_set_default_dirperms() below. + @return 1 success, <=0 failure +*/ +int isoburn_ropt_set_default_perms(struct isoburn_read_opts *o, + uid_t uid, gid_t gid, mode_t mode); +int isoburn_ropt_get_default_perms(struct isoburn_read_opts *o, + uid_t *uid, gid_t *gid, mode_t *mode); + +/** Default attributes to use on directories if no RockRidge extension + gets loaded. + Above call isoburn_ropt_set_default_perms() automatically adds + x-permissions to r-permissions for directories. This call here may + be done afterwards to set independend permissions for directories, + especially to override the automatically added x-permissions. + @since 0.1.0 + @param o The option set to work on + @param mode permissions (not file type) as of man 2 stat. + @return 1 success, <=0 failure +*/ +int isoburn_ropt_set_default_dirperms(struct isoburn_read_opts *o, + mode_t mode); +int isoburn_ropt_get_default_dirperms(struct isoburn_read_opts *o, + mode_t *mode); + + + +/** Set the character set for reading RR file names from ISO images. + @since 0.1.0 + @param o The option set to work on + @param input_charset Set this to NULL to use the default locale charset. + For selecting a particular character set, submit its + name, e.g. as listed by program iconv -l. + Example: "UTF-8". + @return 1 success, <=0 failure +*/ +int isoburn_ropt_set_input_charset(struct isoburn_read_opts *o, + char *input_charset); +int isoburn_ropt_get_input_charset(struct isoburn_read_opts *o, + char **input_charset); + + +/** After calling function isoburn_read_image() there are informations + available in the option set. + This info can be obtained as bits in parameter has_what. Like: + joliet_available = (has_what & isoburn_ropt_has_joliet); + @since 0.1.0 + @param o The option set to work on + @param size Number of image data blocks, 2048 bytes each. + @param has_what Bitfield: + bit0= has_rockridge + RockRidge extension info is available (POSIX filesystem) + bit1= has_joliet + Joliet extension info is available (suitable for MS-Windows) + bit2= has_iso1999 + ISO version 2 Enhanced Volume Descriptor is available. + This is rather exotic. + bit3= has_el_torito + El-Torito boot record is present + @return 1 success, <=0 failure +*/ +#define isoburn_ropt_has_rockridge 1 +#define isoburn_ropt_has_joliet 2 +#define isoburn_ropt_has_iso1999 4 +#define isoburn_ropt_has_el_torito 8 +int isoburn_ropt_get_size_what(struct isoburn_read_opts *o, + uint32_t *size, int *has_what); + + +/* ----------------------------------------------------------------------- */ +/* End of Options for image reading */ +/* ----------------------------------------------------------------------- */ + +/* ----------------------------------------------------------------------- */ +/* + + Options for image generation by libisofs and image transport to libburn. + + An application shall create an option set by isoburn_igopt_new(), + program it by isoburn_igopt_set_*(), use it with either + isoburn_prepare_new_image() or isoburn_prepare_disc(), and finally delete + it by isoburn_igopt_destroy(). + +*/ +/* ----------------------------------------------------------------------- */ + +struct isoburn_imgen_opts; + +/** Produces a set of generation and transfer options, initialized with default + values. + @since 0.1.0 + @param o the newly created option set object + @param flag Bitfield for control purposes. Submit 0 for now. + @return 1=ok , <0 = failure +*/ +int isoburn_igopt_new(struct isoburn_imgen_opts **o, int flag); + + +/** Deletes an option set which was created by isoburn_igopt_new(). + @since 0.1.0 + @param o The option set to give up + @param flag Bitfield for control purposes. Submit 0 for now. + @return 1= **o destroyed , 0= *o was already NULL (harmless) +*/ +int isoburn_igopt_destroy(struct isoburn_imgen_opts **o, int flag); + + +/** ISO level to write at. + @since 0.1.0 + @param o The option set to work on + @param level is a term of the ISO 9660 standard. It should be one of: + 1= filenames restricted to form 8.3 + 2= filenames allowed up to 31 characters + @return 1 success, <=0 failure +*/ +int isoburn_igopt_set_level(struct isoburn_imgen_opts *o, int level); +int isoburn_igopt_get_level(struct isoburn_imgen_opts *o, int *level); + + +/** Which extensions to support. + @since 0.1.0 + @param o The option set to work on + @param ext Bitfield: + bit0= rockridge + Rock Ridge extensions add POSIX file attributes like + owner, group, access permissions, long filenames. Very + advisable if the designed audience has Unix style systems. + bit1= joliet + Longer filenames for Windows systems. + Weaker than RockRidge, but also readable with Linux. + bit2= iso1999 + This is rather exotic. Better do not surprise the readers. + @return 1 success, <=0 failure +*/ +#define isoburn_igopt_rockridge 1 +#define isoburn_igopt_joliet 2 +#define isoburn_igopt_iso1999 4 +int isoburn_igopt_set_extensions(struct isoburn_imgen_opts *o, int ext); +int isoburn_igopt_get_extensions(struct isoburn_imgen_opts *o, int *ext); + +/** Relaxed constraints. Setting any of the bits to 1 break the specifications, + but it is supposed to work on most moderns systems. Use with caution. + @since 0.1.0 + @param o The option set to work on + @param relax Bitfield: + bit0= omit_version_numbers + Omit the version number (";1") at the end of the + ISO-9660 identifiers. Version numbers are usually + not used. + bit1= allow_deep_paths + Allow ISO-9660 directory hierarchy to be deeper + than 8 levels. + bit2= allow_longer_paths + Allow path in the ISO-9660 tree to have more than + 255 characters. + bit3= max_37_char_filenames + Allow a single file or directory hierarchy to have + up to 37 characters. This is larger than the 31 + characters allowed by ISO level 2, and the extra space + is taken from the version number, so this also forces + omit_version_numbers. + bit4= no_force_dots + ISO-9660 forces filenames to have a ".", that separates + file name from extension. libisofs adds it if original + filename has none. Set this to 1 to prevent this + behavior. + bit5= allow_lowercase + Allow lowercase characters in ISO-9660 filenames. + By default, only uppercase characters, numbers and + a few other characters are allowed. + bit6= allow_full_ascii + Allow all ASCII characters to be appear on an ISO-9660 + filename. Note * that "/" and "\0" characters are never + allowed, even in RR names. + bit7= joliet_longer_paths + Allow paths in the Joliet tree to have more than + 240 characters. + bit8= always_gmt + Write timestamps as GMT although the specs prescribe local + time with eventual non-zero timezone offset. Negative + timezones (west of GMT) can trigger bugs in some operating + systems which typically appear in mounted ISO images as if + the timezone shift from GMT was applied twice + (e.g. in New York 22:36 becomes 17:36). + bit9= rrip_version_1_10 + Write Rock Ridge info as of specification RRIP-1.10 rather + than RRIP-1.12: signature "RRIP_1991A" rather than + "IEEE_1282", field PX without file serial number. + bit10= dir_rec_mtime + Store as ECMA-119 Directory Record timestamp the mtime + of the source rather than the image creation time. + + @return 1 success, <=0 failure +*/ +#define isoburn_igopt_omit_version_numbers 1 +#define isoburn_igopt_allow_deep_paths 2 +#define isoburn_igopt_allow_longer_paths 4 +#define isoburn_igopt_max_37_char_filenames 8 +#define isoburn_igopt_no_force_dots 16 +#define isoburn_igopt_allow_lowercase 32 +#define isoburn_igopt_allow_full_ascii 64 +#define isoburn_igopt_joliet_longer_paths 128 +#define isoburn_igopt_always_gmt 256 +#define isoburn_igopt_rrip_version_1_10 512 +#define isoburn_igopt_dir_rec_mtime 1024 +int isoburn_igopt_set_relaxed(struct isoburn_imgen_opts *o, int relax); +int isoburn_igopt_get_relaxed(struct isoburn_imgen_opts *o, int *relax); + + +/** Whether and how files should be sorted. + @since 0.1.0 + @param o The option set to work on + @param value Bitfield: bit0= sort_files_by_weight + files should be sorted based on their weight. + Weight is attributed to files in the image + by libisofs call iso_node_set_sort_weight(). + @return 1 success, <=0 failure +*/ +#define isoburn_igopt_sort_files_by_weight 1 +int isoburn_igopt_set_sort_files(struct isoburn_imgen_opts *o, int value); +int isoburn_igopt_get_sort_files(struct isoburn_imgen_opts *o, int *value); + + +/** Set the override values for files and directory permissions. + The parameters replace_* these take one of three values: 0, 1 or 2. + If 0, the corresponding attribute will be kept as set in the IsoNode + at the time of image generation. + If set to 1, the corresponding attrib. will be changed by a default + suitable value. + With value 2, the attrib. will be changed with the value specified + in the corresponding *_mode options. Note that only the permissions + are set, the file type remains unchanged. + @since 0.1.0 + @param o The option set to work on + @param replace_dir_mode whether and how to override directories + @param replace_file_mode whether and how to override files of other type + @param dir_mode Mode to use on dirs with replace_dir_mode == 2. + @param file_mode; Mode to use on files with replace_file_mode == 2. + @return 1 success, <=0 failure +*/ +int isoburn_igopt_set_over_mode(struct isoburn_imgen_opts *o, + int replace_dir_mode, int replace_file_mode, + mode_t dir_mode, mode_t file_mode); +int isoburn_igopt_get_over_mode(struct isoburn_imgen_opts *o, + int *replace_dir_mode, int *replace_file_mode, + mode_t *dir_mode, mode_t *file_mode); + +/** Set the override values values for group id and user id. + The rules are like with above overriding of mode values. replace_* controls + whether and how. The other two parameters provide values for eventual use. + @since 0.1.0 + @param o The option set to work on + @param replace_uid whether and how to override user ids + @param replace_gid whether and how to override group ids + @param uid User id to use with replace_uid == 2. + @param gid Group id to use on files with replace_gid == 2. + @return 1 success, <=0 failure +*/ +int isoburn_igopt_set_over_ugid(struct isoburn_imgen_opts *o, + int replace_uid, int replace_gid, + uid_t uid, gid_t gid); +int isoburn_igopt_get_over_ugid(struct isoburn_imgen_opts *o, + int *replace_uid, int *replace_gid, + uid_t *uid, gid_t *gid); + +/** Set the charcter set to use for representing filenames in the image. + @since 0.1.0 + @param o The option set to work on + @param output_charset Set this to NULL to use the default output charset. + For selecting a particular character set, submit its + name, e.g. as listed by program iconv -l. + Example: "UTF-8". + @return 1 success, <=0 failure +*/ +int isoburn_igopt_set_out_charset(struct isoburn_imgen_opts *o, + char *output_charset); +int isoburn_igopt_get_out_charset(struct isoburn_imgen_opts *o, + char **output_charset); + + +/** The number of bytes to be used for the fifo which decouples libisofs + and libburn for better throughput and for reducing the risk of + interrupting signals hitting the libburn thread which operates the + MMC drive. + The size will be rounded up to the next full 2048. + Minimum is 64kiB, maximum is 1 GiB (but that is too much anyway). + @since 0.1.0 + @param o The option set to work on + @param fifo_size Number of bytes to use + @return 1 success, <=0 failure +*/ +int isoburn_igopt_set_fifo_size(struct isoburn_imgen_opts *o, int fifo_size); +int isoburn_igopt_get_fifo_size(struct isoburn_imgen_opts *o, int *fifo_size); + + +/** Obtain after image preparation the block address where the session will + start on media. + This value cannot be set by the application but only be inquired. + @since 0.1.4 + @param o The option set to work on + @param lba The block number of the session start on media. + <0 means that no address has been determined yet. + @return 1 success, <=0 failure +*/ +int isoburn_igopt_get_effective_lba(struct isoburn_imgen_opts *o, int *lba); + + +/* ----------------------------------------------------------------------- */ +/* End of Options for image generation */ +/* ----------------------------------------------------------------------- */ + + +/** Get the image attached to a drive, if any. + @since 0.1.0 + @param d The drive to inquire + @return A reference to attached image, or NULL if the drive has no image + attached. This reference needs to be released via iso_image_unref() + when it is not longer needed. +*/ +IsoImage *isoburn_get_attached_image(struct burn_drive *d); + + +/** Load the ISO filesystem directory tree from the media in the given drive. + This will give libisoburn the base on which it can let libisofs perform + image growing or image modification. The loaded volset gets attached + to the drive object and handed out to the application. + Not a wrapper, but peculiar to libisoburn. + @since 0.1.0 + @param d The drive which holds an existing ISO filesystem or blank media. + d is allowed to be NULL which produces an empty ISO image. In + this case one has to call before writing isoburn_attach_volset() + with the volset from this call and with the intended output + drive. + @param read_opts The read options which can be chosen by the application + @param image the image read, if the disc is blank it will have no files. + This reference needs to be released via iso_image_unref() when + it is not longer needed. The drive, if not NULL, will hold an + own reference which it will release when it gets a new volset + or when it gets released via isoburn_drive_release(). + You can pass NULL if you already have a reference or you plan to + obtain it later with isoburn_get_attached_image(). Of course, if + you haven't specified a valid drive (i.e., if d == NULL), this + parameter can't be NULL. + @return <=0 error , 1 = success +*/ +int isoburn_read_image(struct burn_drive *d, + struct isoburn_read_opts *read_opts, + IsoImage **image); + +/** Set a callback function for producing pacifier messages during the lengthy + process of image reading. The callback function and the application handle + are stored until they are needed for the underlying call to libisofs. + Other than with libisofs the handle is managed entirely by the application. + An idle .free() function is exposed to libisofs. The handle has to stay + valid until isoburn_read_image() is done. It has to be detached by + isoburn_set_read_pacifier(drive, NULL, NULL); + before it may be removed from memory. + @since 0.1.0 + @param drive The drive which will be used with isoburn_read_image() + It has to be aquired by an isoburn_* wrapper call. + @param read_pacifier The callback function + @param app_handle The app handle which the callback function can obtain + via iso_image_get_attached_data() from its IsoImage* + @return 1 success, <=0 failure +*/ +int isoburn_set_read_pacifier(struct burn_drive *drive, + int (*read_pacifier)(IsoImage*, IsoFileSource*), + void *app_handle); + + +/** Set the IsoImage to be used with a drive. This eventually releases + the reference to the old IsoImage attached to the drive. + Caution: Use with care. It hardly makes sense to replace an image that + reflects a valid ISO image on media. + This call is rather intended for writing a newly created and populated + image to blank media. The use case in xorriso is to let an image survive + the change or demise of the outdev target drive. + @since 0.1.0 + @param d The drive which shall be write target of the volset. + @param image The image that represents the image to be written. + This image pointer MUST already be a valid reference suitable + for iso_image_unref(). + It may have been obtained by appropriate libisofs calls or by + isoburn_read_image() with d==NULL. + @return <=0 error , 1 = success +*/ +int isoburn_attach_image(struct burn_drive *d, IsoImage *image); + + +/** Return the best possible estimation of the currently available capacity of + the media. This might depend on particular write option settings and on + drive state. + An eventual start address for emulated multi-session will be subtracted + from the capacity estimation given by burn_disc_available_space(). + Negative results get defaulted to 0. + Wrapper for: burn_disc_available_space() + @since 0.1.0 + @param d The drive to query. + @param o If not NULL: write parameters to be set on drive before query + @return number of most probably available free bytes +*/ +off_t isoburn_disc_available_space(struct burn_drive *d, + struct burn_write_opts *o); + + +/** Obtain the start block number of the most recent session on media. In + case of random access media this will normally be 0. Successfull return is + not a guarantee that there is a ISO-9660 image at all. The call will fail, + nevertheless,if isoburn_disc_get_status() returns not BURN_DISC_APPENDABLE + or BURN_DISC_FULL. + Note: The result of this call may be fabricated by a previous call of + isoburn_set_msc1() which can override the rule to load the most recent + session. + Wrapper for: burn_disc_get_msc1() + @since 0.1.0 + @param d The drive to inquire + @param start_lba Contains on success the start address in 2048 byte blocks + @return <=0 error , 1 = success +*/ +int isoburn_disc_get_msc1(struct burn_drive *d, int *start_lba); + + +/** Use this with trackno==0 to obtain the predicted start block number of the + new session. The interesting number is returned in parameter nwa. + Wrapper for: burn_disc_track_lba_nwa() + @since 0.1.0 + @param d The drive to inquire + @param o If not NULL: write parameters to be set on drive before query + @param trackno Submit 0. + @param lba return value: start lba + @param nwa return value: Next Writeable Address + @return 1=nwa is valid , 0=nwa is not valid , -1=error +*/ +int isoburn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o, + int trackno, int *lba, int *nwa); + + +/** Obtain the size which was attributed to an emulated appendable on actually + overwriteable media. This value is supposed to be <= 2048 * nwa as of + isoburn_disc_track_lba_nwa(). + @since 0.1.0 + @param drive The drive holding the media. + @param start_byte The reply value counted in bytes, not in sectors. + @param flag Unused yet. Submit 0. + @return 1=stat_byte is valid, 0=not an emulated appendable, -1=error +*/ +int isoburn_get_min_start_byte(struct burn_drive *d, off_t *start_byte, + int flag); + + +/** To choose the expansion method of Growing: + Create a disc object for writing the new session from the created or loaded + iso_volset which has been manipulated via libisofs, to the same media from + where the image was eventually loaded. This struct burn_disc is ready for + use by a subsequent call to isoburn_disc_write(). + After this asynchronous writing has ended and the drive is BURN_DRIVE_IDLE + again, the burn_disc object has to be disposed by burn_disc_free(). + @since 0.1.0 + @param drive The combined source and target drive, grabbed with + isoburn_drive_scan_and_grab(). . + @param disc Returns the newly created burn_disc object. + @param opts Image generation options, see isoburn_igopt_*() + @return <=0 error , 1 = success +*/ +int isoburn_prepare_disc(struct burn_drive *drive, struct burn_disc **disc, + struct isoburn_imgen_opts *opts); + + +/** To choose the expansion method of Modifying: + Create a disc object for producing a new image from a previous image + plus the changes made by user. The generated burn_disc is suitable + to be written to a grabbed drive with blank writeable media. + But you must not use the same drive for input and output, because data + will be read from the source drive while at the same time the target + drive is already writing. + The resulting burn_disc object has to be disposed when all its writing + is done and the drive is BURN_DRIVE_IDLE again after asynchronous + burn_disc_write(). + @since 0.1.0 + @param in_drive The input drive, grabbed with isoburn_drive_aquire() or + one of its alternatives. + @param disc Returns the newly created burn_disc object. + @param opts Options for image generation and data transport to media. + @param out_drive The output drive, from isoburn_drive_aquire() et.al.. + @return <=0 error , 1 = success +*/ +int isoburn_prepare_new_image(struct burn_drive *in_drive, + struct burn_disc **disc, + struct isoburn_imgen_opts *opts, + struct burn_drive *out_drive); + + +/** To choose the expansion method of Blind Growing: + Create a disc object for writing an add-on session from the created or + loaded IsoImage which has been manipulated via libisofs, to a different + drive than the one from where it was loaded. + Usually output will be stdio:/dev/fd/1 (i.e. stdout) being piped + into some burn program like with this classic gesture: + mkisofs -M $dev -C $msc1,$nwa | cdrecord -waiti dev=$dev + Parameter translation into libisoburn: + $dev is the address by which parameter in_drive of this call was aquired + $msc1 was set by isoburn_set_msc1() before image reading + or was detected from the in_drive media + $nwa is a parameter of this call + or can be used as detected from the in_drive media + + This call waits for libisofs output to become available and then detaches + the input drive object from the data source object by which libisofs was + reading from the input drive. + So, as far as libisofs is concerned, that drive may be released immediately + after this call in order to allow the consumer to access the drive for + writing. + The consumer should wait for input to become available and only then open + its burn drive. With cdrecord this is caused by option -waiti. + + The resulting burn_disc object has to be disposed when all its writing + is done and the drive is BURN_DRIVE_IDLE again after asynchronous + burn_disc_write(). + @since 0.2.2 + @param in_drive The input drive,grabbed with isoburn_drive_scan_and_grab(). + @param disc Returns the newly created burn_disc object. + @param opts Options for image generation and data transport to media. + @param out_drive The output drive, from isoburn_drive_aquire() et.al.. + typically stdio:/dev/fd/1 . + @param nwa The address (2048 byte block count) where the add-on + session will be finally stored on a mountable media + or in a mountable file. + If nwa is -1 then the address is used as determined from + the in_drive media. + @return <=0 error , 1 = success +*/ +int isoburn_prepare_blind_grow(struct burn_drive *d, struct burn_disc **disc, + struct isoburn_imgen_opts *opts, + struct burn_drive *out_drive, int nwa); + + +/** + Revoke isoburn_prepare_*() instead of running isoburn_disc_write(). + libisofs reserves resources and maybe already starts generating the + image stream when one of above three calls is performed. It is mandatory to + either run isoburn_disc_write() or to revoke the preparations by the + call described here. + @since 0.1.0 + @param input_drive The drive resp. in_drive which was used with the + preparation call. + @param output_drive The out_drive used with isoburn_prepare_new_image(), + NULL if none. + @param flag Bitfield, submit 0 for now. + bit0= -reserved for internal use- + @return <0 error, 0= no pending preparations detectable, 1 = canceled +*/ +int isoburn_cancel_prepared_write(struct burn_drive *input_drive, + struct burn_drive *output_drive, int flag); + + +/** Start writing of the new session. + This call is asynchrounous. I.e. it returns quite soon and the progress has + to be watched by a loop with call burn_drive_get_status() until + BURN_DRIVE_IDLE is returned. + Wrapper for: burn_disc_write() + @since 0.1.0 + @param o Options which control the burn process. See burnwrite_opts_*() + in libburn.h. + @param disc Disc object created either by isoburn_prepare_disc() or by + isoburn_prepare_new_image(). +*/ +void isoburn_disc_write(struct burn_write_opts *o, struct burn_disc *disc); + + +/** Inquire state and fill parameters of the fifo which is attached to + the emerging track. This should be done in the pacifier loop while + isoburn_disc_write() or burn_disc_write() are active. + This works only with drives obtained by isoburn_drive_scan_and_grab() + or isoburn_drive_grab(). If isoburn_prepare_new_image() was used, then + parameter out_drive must have announced the track output drive. + Hint: If only burn_write_opts and not burn_drive is known, then the drive + can be obtained by burn_write_opts_get_drive(). + @since 0.1.0 + @param d The drive to which the track with the fifo gets burned. + @param size The total size of the fifo + @param free_bytes The current free capacity of the fifo + @param status_text Returns a pointer to a constant text, see below + @return <0 reply invalid, >=0 fifo status code: + bit0+1=input status, bit2=consumption status, i.e: + 0="standby" : data processing not started yet + 1="active" : input and consumption are active + 2="ending" : input has ended without error + 3="failing" : input had error and ended, + 4="unused" : ( consumption has ended before processing start ) + 5="abandoned" : consumption has ended prematurely + 6="ended" : consumption has ended without input error + 7="aborted" : consumption has ended after input error +*/ +int isoburn_get_fifo_status(struct burn_drive *d, int *size, int *free_bytes, + char **status_text); + + +/** Inquire whether the most recent write run was successful. + Wrapper for: burn_drive_wrote_well() + @since 0.1.0 + @param d The drive to inquire + @return 1=burn seems to have went well, 0=burn failed +*/ +int isoburn_drive_wrote_well(struct burn_drive *d); + + +/** Call this after isoburn_disc_write has finished and burn_drive_wrote_well() + indicates success. It will eventually complete the emulation of + multi-session functionality, if needed at all. Let libisoburn decide. + Not a wrapper, but peculiar to libisoburn. + @since 0.1.0 + @param d The output drive to which the session was written + @return 1 success , <=0 failure +*/ +int isoburn_activate_session(struct burn_drive *drive); + + +/** Wait after normal end of operations until libisofs ended all write + threads and freed resource reservations. + This call is not mandatory. But without it, messages from the ending + threads might appear after the application ended its write procedure. + @since 0.1.0 + @param input_drive The drive resp. in_drive which was used with the + preparation call. + @param output_drive The out_drive used with isoburn_prepare_new_image(), + NULL if none. + @param flag Bitfield, submit 0 for now. + @return <=0 error , 1 = success +*/ +int isoburn_sync_after_write(struct burn_drive *input_drive, + struct burn_drive *output_drive, int flag); + + +/** Release an aquired drive. + Wrapper for: burn_drive_release() + @since 0.1.0 + @param drive The drive to be released + @param eject 1= eject media from drive , 0= do not eject +*/ +void isoburn_drive_release(struct burn_drive *drive, int eject); + + +/** Shutdown all three libraries. + Wrapper for : iso_finish() and burn_finish(). + @since 0.1.0 +*/ +void isoburn_finish(void); + + +/* + The following calls are for expert applications only. + An application should have a special reason to use them. +*/ + + +/** Inquire wether the media needs emulation or would be suitable for + generic multi-session via libburn. + @since 0.1.0 + @param d The drive to inquire + @return 0 is generic multi-session + 1 is emulated multi-session + -1 is not suitable for isoburn +*/ +int isoburn_needs_emulation(struct burn_drive *drive); + + diff --git a/libisoburn/branches/ZeroThreeTwo/test/aaip-os-freebsd.c b/libisoburn/branches/ZeroThreeTwo/test/aaip-os-freebsd.c new file mode 100644 index 00000000..caa28da5 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/test/aaip-os-freebsd.c @@ -0,0 +1,283 @@ + +/* + + aaip-os-freebsd.c + Arbitrary Attribute Interchange Protocol , system adapter for getting and + setting of ACLs and XFS-style Extended Attributes. + + To be included by aaip_0_2.c +*/ + +#include +#include +#include +#include +#include +#include + +#include + + +/* ------------------------------ Getters --------------------------------- */ + +/* Obtain the ACL of the given file in long text form. + @param path Path to the file + @param text Will hold the result. This is a managed object which + finally has to be freed by a call to this function + with bit15 of flag. + @param flag Bitfield for control purposes + bit0= obtain default ACL rather than access ACL + bit15= free text and return 1 + @return > 0 ok + -1 failure of system ACL service (see errno) +*/ +int aaip_get_acl_text(char *path, char **text, int flag) +{ + acl_t acl= NULL; + + if(flag & (1 << 15)) { + if(*text != NULL) + acl_free(text); + *text= NULL; + return(1); + } + *text= NULL; + + /* Note: no ACL_TYPE_DEFAULT in FreeBSD */ + if(flag & 1) + return(0); + + acl= acl_get_file(path, ACL_TYPE_ACCESS); + + if(acl == NULL) + return(-1); + *text= acl_to_text(acl, NULL); + acl_free(acl); + if(*text == NULL) + return(-1); + return(1); +} + + +/* Obtain the Extended Attributes and/or the ACLs of the given file in a form + that is ready for aaip_encode(). + + Note: There are no Extended Attributes in FreeBSD. So only ACL will be + obtained. + + @param path Path to the file + @param num_attrs Will return the number of name-value pairs + @param names Will return an array of pointers to 0-terminated names + @param value_lengths Will return an arry with the lenghts of values + @param values Will return an array of pointers to 8-bit values + @param flag Bitfield for control purposes + bit0= obtain ACL (access and eventually default) + bit1= use numeric ACL qualifiers rather than names + bit2= do not encode attributes other than ACL + bit15= free memory of names, value_lengths, values + @return >0 ok + <=0 error +*/ +int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, + size_t **value_lengths, char ***values, int flag) +{ + int ret, retry= 0; + char *list= NULL; + ssize_t list_size= 0, i, num_names, value_ret; + size_t a_acl_len= 0, d_acl_len= 0, acl_len= 0; + unsigned char *a_acl= NULL, *d_acl= NULL, *acl= NULL; + char *acl_text= NULL; + + if(flag & (1 << 15)) { /* Free memory */ + if(*names != NULL) + list= (*names)[0]; + {ret= 1; goto ex;} + } + + *num_attrs= 0; + *names= NULL; + *value_lengths= NULL; + *values= NULL; + + if(flag & 1) + num_names++; + if(num_names == 0) + {ret= 1; goto ex;} + (*names)= calloc(num_names, sizeof(char *)); + (*value_lengths)= calloc(num_names, sizeof(size_t)); + (*values)= calloc(num_names, sizeof(char *)); + if(*names == NULL || *value_lengths == NULL || *values == NULL) + {ret= -1; goto ex;} + + for(i= *num_attrs; i < num_names; i++) + (*names)[i]= NULL; + for(i= 0; i < num_names; i++) { + (*values)[i]= NULL; + (*value_lengths)[i]= 0; + } + + if(flag & 1) { /* Obtain ACL */ + /* access-ACL */ + ret= aaip_get_acl_text(path, &acl_text, 0); + if(ret <= 0) + goto ex; + ret= aaip_encode_acl(acl_text, &a_acl_len, &a_acl, flag & 2); + if(ret <= 0) + goto ex; + aaip_get_acl_text("", &acl_text, 1 << 15); /* free */ + + /* Note: There are no default-ACL in FreeBSD */ + + /* Set as attribute with empty name */; + (*names)[*num_attrs]= strdup(""); + if((*names)[*num_attrs] == NULL) + {ret= -1; goto ex;} + (*values)[*num_attrs]= (char *) acl; + (*value_lengths)[*num_attrs]= acl_len; + (*num_attrs)++; + } + + ret= 1; +ex:; + if(a_acl != NULL) + free(a_acl); + if(d_acl != NULL) + free(d_acl); + if(acl_text != NULL) + aaip_get_acl_text("", &acl_text, 1 << 15); /* free */ + + if(ret <= 0 || (flag & (1 << 15))) { + if(list != NULL) + free(list); + if(*names != NULL) + free(*names); + *names= NULL; + if(*value_lengths != NULL) + free(*value_lengths); + *value_lengths= NULL; + if(*values != NULL) { + for(i= 0; i < *num_attrs; i++) + free((*values)[i]); + free(*values); + } + if(acl != NULL) + free(acl); + *values= NULL; + *num_attrs= 0; + } + return(ret); +} + + +/* ------------------------------ Setters --------------------------------- */ + + +/* Set the ACL of the given file to a given list in long text form. + @param path Path to the file + @param text The input text (0 terminated, ACL long text form) + @param flag Bitfield for control purposes + bit0= set default ACL rather than access ACL + @return > 0 ok + -1 failure of system ACL service (see errno) +*/ +int aaip_set_acl_text(char *path, char *text, int flag) +{ + int ret; + acl_t acl= NULL; + + acl= acl_from_text(text); + if(acl == NULL) { + ret= -1; goto ex; + } + + /* Note: no ACL_TYPE_DEFAULT in FreeBSD */ + if(flag & 1) + {ret= 0; goto ex;} + + ret= acl_set_file(path, ACL_TYPE_ACCESS, acl); + + if(ret == -1) + goto ex; + ret= 1; +ex: + if(acl != NULL) + acl_free(acl); + return(ret); +} + + +/* Bring the given attributes and/or ACLs into effect with the given file. + + Note: There are no Extended Attributes in FreeBSD. So only ACL get set. + + @param flag Bitfield for control purposes + bit0= decode and set ACLs + ( bit1= first clear all existing attributes of the file ) + ( bit2= do not set attributes other than ACLs ) + @return 1 success + -1 error memory allocation + -2 error with decoding of ACL + -3 error with setting ACL + ( -4 error with setting attribute ) + ( -5 error with deleting attribute ) + +*/ +int aaip_set_attr_list(char *path, size_t num_attrs, char **names, + size_t *value_lengths, char **values, int flag) +{ + int ret, has_default_acl= 0; + size_t i, consumed, acl_text_fill, list_size= 0; + char *acl_text= NULL, *list= NULL; + + for(i= 0; i < num_attrs; i++) { + if(names[i] == NULL || values[i] == NULL) + continue; + if(names[i][0] == 0) { /* Decode ACLs */ + /* access ACL */ + ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i], + &consumed, NULL, 0, &acl_text_fill, 1); + if(ret <= 0) + {ret= -2; goto ex;} + acl_text= calloc(acl_text_fill, 1); + if(acl_text == NULL) + {ret= -1; goto ex;} + ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i], + &consumed, acl_text, acl_text_fill, &acl_text_fill, 0); + if(ret <= 0) + {ret= -2; goto ex;} + has_default_acl= (ret == 2); + ret= aaip_set_acl_text(path, acl_text, 0); + if(ret <= 0) + {ret= -3; goto ex;} + if(has_default_acl) { + free(acl_text); + acl_text= NULL; + ret= aaip_decode_acl((unsigned char *) (values[i] + consumed), + value_lengths[i] - consumed, &consumed, + NULL, 0, &acl_text_fill, 1); + if(ret <= 0) + {ret= -2; goto ex;} + acl_text= calloc(acl_text_fill, 1); + if(acl_text == NULL) + {ret= -1; goto ex;} + ret= aaip_decode_acl((unsigned char *) (values[i] + consumed), + value_lengths[i] - consumed, &consumed, + acl_text, acl_text_fill, &acl_text_fill, 0); + if(ret <= 0) + {ret= -2; goto ex;} + ret= aaip_set_acl_text(path, acl_text, 1); + if(ret <= 0) + {ret= -3; goto ex;} + } + } + } + ret= 1; +ex:; + if(acl_text != NULL) + free(acl_text); + if(list != NULL) + free(list); + return(ret); +} + + diff --git a/libisoburn/branches/ZeroThreeTwo/test/aaip-os-linux.c b/libisoburn/branches/ZeroThreeTwo/test/aaip-os-linux.c new file mode 100644 index 00000000..c0e36e93 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/test/aaip-os-linux.c @@ -0,0 +1,371 @@ + +/* + + aaip-os-linux.c + Arbitrary Attribute Interchange Protocol , system adapter for getting and + setting of ACLs and XFS-style Extended Attributes. + + To be included by aaip_0_2.c +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define Aaip_acl_attrnamE "system.posix_acl_access" + + +/* ------------------------------ Getters --------------------------------- */ + +/* Obtain the ACL of the given file in long text form. + @param path Path to the file + @param text Will hold the result. This is a managed object which + finally has to be freed by a call to this function + with bit15 of flag. + @param flag Bitfield for control purposes + bit0= obtain default ACL rather than access ACL + bit15= free text and return 1 + @return > 0 ok + -1 failure of system ACL service (see errno) +*/ +int aaip_get_acl_text(char *path, char **text, int flag) +{ + acl_t acl= NULL; + + if(flag & (1 << 15)) { + if(*text != NULL) + acl_free(text); + *text= NULL; + return(1); + } + *text= NULL; + acl= acl_get_file(path, (flag & 1) ? ACL_TYPE_DEFAULT : ACL_TYPE_ACCESS); + if(acl == NULL) + return(-1); + *text= acl_to_text(acl, NULL); + acl_free(acl); + if(*text == NULL) + return(-1); + return(1); +} + + +/* Obtain the Extended Attributes and/or the ACLs of the given file in a form + that is ready for aaip_encode(). + @param path Path to the file + @param num_attrs Will return the number of name-value pairs + @param names Will return an array of pointers to 0-terminated names + @param value_lengths Will return an arry with the lenghts of values + @param values Will return an array of pointers to 8-bit values + @param flag Bitfield for control purposes + bit0= obtain ACL (access and eventually default) + bit1= use numeric ACL qualifiers rather than names + bit2= do not obtain attributes other than ACL + bit3= do not ignore eventual local ACL attribute + (e.g. system.posix_acl_access) + bit15= free memory of names, value_lengths, values + @return >0 ok + <=0 error +*/ +int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, + size_t **value_lengths, char ***values, int flag) +{ + int ret, retry= 0; + char *list= NULL; + ssize_t list_size= 0, i, num_names= 0, value_ret; + size_t a_acl_len= 0, d_acl_len= 0, acl_len= 0; + unsigned char *a_acl= NULL, *d_acl= NULL, *acl= NULL; + char *acl_text= NULL; + + if(flag & (1 << 15)) { /* Free memory */ + if(*names != NULL) + list= (*names)[0]; + {ret= 1; goto ex;} + } + + *num_attrs= 0; + *names= NULL; + *value_lengths= NULL; + *values= NULL; + + /* Set up arrays */ + if(!(flag & 4)) { /* Get xattr names */ + list_size= listxattr(path, list, 0); + if(list_size == -1) + {ret= -1; goto ex;} + list= calloc(list_size, 1); + if(list == NULL) + {ret= -1; goto ex;} + list_size= listxattr(path, list, list_size); + if(list_size == -1) + {ret= -1; goto ex;} + for(i= 0; i < list_size; i+= strlen(list + i) + 1) + num_names++; + } + if(flag & 1) + num_names++; + if(num_names == 0) + {ret= 1; goto ex;} + (*names)= calloc(num_names, sizeof(char *)); + (*value_lengths)= calloc(num_names, sizeof(size_t)); + (*values)= calloc(num_names, sizeof(char *)); + if(*names == NULL || *value_lengths == NULL || *values == NULL) + {ret= -1; goto ex;} + + if(!(flag & 4)) + for(i= 0; i < list_size && num_names > *num_attrs; + i+= strlen(list + i) + 1) { + if(!(flag & 8)) + if(strcmp(list + i, Aaip_acl_attrnamE) == 0) + continue; + (*names)[(*num_attrs)++]= list + i; + } + for(i= *num_attrs; i < num_names; i++) + (*names)[i]= NULL; + for(i= 0; i < num_names; i++) { + (*values)[i]= NULL; + (*value_lengths)[i]= 0; + } + + if(!(flag & 4)) { /* Get xattr values */ + for(i= 0; i < *num_attrs; i++) { + if(!(flag & 8)) + if(strcmp((*names)[i], Aaip_acl_attrnamE) == 0) + continue; + value_ret= getxattr(path, (*names)[i], NULL, 0); + if(value_ret == -1) + continue; + (*values)[i]= calloc(value_ret + 1, 1); + if((*values)[i] == NULL) + {ret= -1; goto ex;} + (*value_lengths)[i]= getxattr(path, (*names)[i], (*values)[i], value_ret); + if(value_ret == -1) { /* there could be a race condition */ + if(retry++ > 5) + {ret= -1; goto ex;} + i--; + continue; + } + (*value_lengths)[i]= value_ret; + retry= 0; + } + } + + if(flag & 1) { /* Obtain ACL */ + /* access-ACL */ + ret= aaip_get_acl_text(path, &acl_text, 0); + if(ret <= 0) + goto ex; + ret= aaip_encode_acl(acl_text, &a_acl_len, &a_acl, flag & 2); + if(ret <= 0) + goto ex; + aaip_get_acl_text("", &acl_text, 1 << 15); /* free */ + + /* eventually default-ACL */ + ret= aaip_get_acl_text(path, &acl_text, 1); + if(ret > 0) { + /* encode and append to a_acl */; + ret= aaip_encode_acl(acl_text, &d_acl_len, &d_acl, (flag & 2) | 4); + if(ret <= 0) + goto ex; + acl= calloc(a_acl_len + d_acl_len + 1, 1); + if(acl == NULL) + {ret= -1; goto ex;} + if(a_acl_len) + memcpy(acl, a_acl, a_acl_len); + if(d_acl_len) + memcpy(acl + a_acl_len, d_acl, d_acl_len); + acl_len= a_acl_len + d_acl_len; + } else { + acl= a_acl; + a_acl= NULL; + acl_len= a_acl_len; + } + + /* Set as attribute with empty name */; + (*names)[*num_attrs]= strdup(""); + if((*names)[*num_attrs] == NULL) + {ret= -1; goto ex;} + (*values)[*num_attrs]= (char *) acl; + (*value_lengths)[*num_attrs]= acl_len; + (*num_attrs)++; + } + + ret= 1; +ex:; + if(a_acl != NULL) + free(a_acl); + if(d_acl != NULL) + free(d_acl); + if(acl_text != NULL) + aaip_get_acl_text("", &acl_text, 1 << 15); /* free */ + + if(ret <= 0 || (flag & (1 << 15))) { + if(list != NULL) + free(list); + if(*names != NULL) + free(*names); + *names= NULL; + if(*value_lengths != NULL) + free(*value_lengths); + *value_lengths= NULL; + if(*values != NULL) { + for(i= 0; i < *num_attrs; i++) + free((*values)[i]); + free(*values); + } + if(acl != NULL) + free(acl); + *values= NULL; + *num_attrs= 0; + } + return(ret); +} + + +/* ------------------------------ Setters --------------------------------- */ + + +/* Set the ACL of the given file to a given list in long text form. + @param path Path to the file + @param text The input text (0 terminated, ACL long text form) + @param flag Bitfield for control purposes + bit0= set default ACL rather than access ACL + @return > 0 ok + -1 failure of system ACL service (see errno) +*/ +int aaip_set_acl_text(char *path, char *text, int flag) +{ + int ret; + acl_t acl= NULL; + + acl= acl_from_text(text); + if(acl == NULL) { + ret= -1; goto ex; + } + ret= acl_set_file(path, (flag & 1) ? ACL_TYPE_DEFAULT : ACL_TYPE_ACCESS, acl); + if(ret == -1) + goto ex; + ret= 1; +ex: + if(acl != NULL) + acl_free(acl); + return(ret); +} + + +/* Bring the given attributes and/or ACLs into effect with the given file. + @param flag Bitfield for control purposes + bit0= decode and set ACLs + bit1= first clear all existing attributes of the file + bit2= do not set attributes other than ACLs + bit3= do not ignore eventual ACL attribute + (e.g. system.posix_acl_access) + @return 1 success + -1 error memory allocation + -2 error with decoding of ACL + -3 error with setting ACL + -4 error with setting attribute + -5 error with deleting attributes + +*/ +int aaip_set_attr_list(char *path, size_t num_attrs, char **names, + size_t *value_lengths, char **values, int flag) +{ + int ret, has_default_acl= 0; + size_t i, consumed, acl_text_fill, list_size= 0, acl_idx= 0; + char *acl_text= NULL, *list= NULL; + + if(flag & 2) /* Delete all file attributes */ + list_size= listxattr(path, list, 0); + if(list_size > 0) { /* Delete all file attributes */ + list= calloc(list_size, 1); + if(list == NULL) + {ret= -5; goto ex;} + list_size= listxattr(path, list, list_size); + if(list_size == -1) + {ret= -5; goto ex;} + for(i= 0; i < list_size; i+= strlen(list + i) + 1) { + if(!(flag & 8)) + if(strcmp(list + i, Aaip_acl_attrnamE) == 0) + continue; + ret= removexattr(path, list + i); + if(ret == -1) + {ret= -5; goto ex;} + } + free(list); list= NULL; + } + + for(i= 0; i < num_attrs; i++) { + if(names[i] == NULL || values[i] == NULL) + continue; + if(names[i][0] == 0) { /* ACLs */ + if(flag & 1) + acl_idx= i + 1; + continue; + } + /* Extended Attribute */ + if((flag & 1) && !(flag & 8)) + if(strcmp(names[i], Aaip_acl_attrnamE) == 0) + continue; + ret= setxattr(path, names[i], values[i], value_lengths[i], 0); + if(ret == -1) + {ret= -4; goto ex;} + } + +/* Decode ACLs */ + if(acl_idx == 0) + {ret= 1; goto ex;} + i= acl_idx - 1; + /* "access" ACL */ + ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i], + &consumed, NULL, 0, &acl_text_fill, 1); + if(ret <= 0) + {ret= -2; goto ex;} + acl_text= calloc(acl_text_fill, 1); + if(acl_text == NULL) + {ret= -1; goto ex;} + ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i], + &consumed, acl_text, acl_text_fill, &acl_text_fill, 0); + if(ret <= 0) + {ret= -2; goto ex;} + has_default_acl= (ret == 2); + ret= aaip_set_acl_text(path, acl_text, 0); + if(ret <= 0) + {ret= -3; goto ex;} + /* "default" ACL */ + if(has_default_acl) { + free(acl_text); + acl_text= NULL; + ret= aaip_decode_acl((unsigned char *) (values[i] + consumed), + value_lengths[i] - consumed, &consumed, + NULL, 0, &acl_text_fill, 1); + if(ret <= 0) + {ret= -2; goto ex;} + acl_text= calloc(acl_text_fill, 1); + if(acl_text == NULL) + {ret= -1; goto ex;} + ret= aaip_decode_acl((unsigned char *) (values[i] + consumed), + value_lengths[i] - consumed, &consumed, + acl_text, acl_text_fill, &acl_text_fill, 0); + if(ret <= 0) + {ret= -2; goto ex;} + ret= aaip_set_acl_text(path, acl_text, 1); + if(ret <= 0) + {ret= -3; goto ex;} + } + ret= 1; +ex:; + if(acl_text != NULL) + free(acl_text); + if(list != NULL) + free(list); + return(ret); +} + + diff --git a/libisoburn/branches/ZeroThreeTwo/test/aaip_0_2.c b/libisoburn/branches/ZeroThreeTwo/test/aaip_0_2.c new file mode 100644 index 00000000..b550e92f --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/test/aaip_0_2.c @@ -0,0 +1,1687 @@ + +/* + + Arbitrary Attribute Interchange Protocol , AAIP version 0.2 + Demonstration implementation of encoding and decoding EA and ACL. + + See test/aaip_0_2.h + http://libburnia-project.org/wiki/AAIP + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* <<< */ +#define Aaip_encode_debuG 1 + +#include "aaip_0_2.h" + +#define Aaip_EXEC 1 +#define Aaip_WRITE 2 +#define Aaip_READ 4 + +#define Aaip_TRANSLATE 0 +#define Aaip_ACL_USER_OBJ 1 +#define Aaip_ACL_USER 2 +#define Aaip_ACL_GROUP_OBJ 3 +#define Aaip_ACL_GROUP 4 +#define Aaip_ACL_MASK 5 +#define Aaip_ACL_OTHER 6 +#define Aaip_SWITCH_MARK 8 +#define Aaip_ACL_USER_N 10 +#define Aaip_ACL_GROUP_N 12 +#define Aaip_FUTURE_VERSION 15 + +/* --------------------------------- Encoder ---------------------------- */ + + +static int aaip_encode_pair(char *name, size_t attr_length, char *attr, + unsigned int *num_recs, size_t *comp_size, + unsigned char *result, size_t result_fill, + int flag); + + +/* Convert an array of Arbitrary Attributes into a series of AAIP fields. + @param aa_name The 2 byte SUSP Signature Word of the fields + @param num_attrs Number of attributes + @param names Array of pointers to 0 terminated name strings + @param value_lengths Array of byte lengths for each value + @param values Array of pointers to the value bytes + @param result_len Number of bytes in the resulting SUSP field string + @param result *result will point to the start of the result string. + This is malloc() memory which needs to be freed when + no longer needed + @param flag Bitfield for control purposes + bit0= set CONTINUE bit of last AA field to 1 + @return >0 is the number of SUSP fields generated, + 0 means error +*/ +unsigned int aaip_encode(char aa_name[2], + unsigned int num_attrs, char **names, + size_t *value_lengths, char **values, + size_t *result_len, unsigned char **result, int flag) +{ + size_t mem_size= 0, comp_size; + unsigned int number_of_fields, i, num_recs, total_recs= 0, ret; + + /* Predict memory needs, number of SUSP fields and component records */ + *result_len= 0; + for(i= 0; i < num_attrs; i++) { + ret= aaip_encode_pair(names[i], value_lengths[i], values[i], + &num_recs, &comp_size, NULL, (size_t) 0, 1); + if(ret <= 0) + return(ret); + mem_size+= comp_size; + total_recs= num_recs; + } + number_of_fields= mem_size / 250 + !!(mem_size % 250); + mem_size+= number_of_fields * 5; + +#ifdef Aaip_encode_debuG + *result= (unsigned char *) calloc(1, mem_size + 1024000); + /* generous honeypot for overflows */ +#else + *result= (unsigned char *) calloc(1, mem_size); +#endif + + + /* Encode pairs into result */ + for(i= 0; i < num_attrs; i++) { + ret= aaip_encode_pair(names[i], value_lengths[i], values[i], + &num_recs, &comp_size, *result, *result_len, 0); + if(ret <= 0) + return(ret); + (*result_len)+= comp_size; + } + + /* write the field headers */ + for(i= 0; i < number_of_fields; i++) { + (*result)[i * 255 + 0]= aa_name[0]; + (*result)[i * 255 + 1]= aa_name[1]; + if(i < number_of_fields - 1 || (mem_size % 255) == 0) + (*result)[i * 255 + 2]= 255; + else + (*result)[i * 255 + 2]= mem_size % 255; + (*result)[i * 255 + 3]= 1; + (*result)[i * 255 + 4]= (flag & 1) || (i < number_of_fields - 1); + } + (*result_len)+= number_of_fields * 5; + +#ifdef Aaip_encode_debuG + if(*result_len != mem_size) { + fprintf(stderr, "aaip_encode(): MEMORY MISMATCH BY %d BYTES\n", + (int) (mem_size - *result_len)); + } + ret= 0; + for(i= 0; i < *result_len; i+= ((unsigned char *) (*result))[i + 2]) + ret++; + if(ret != number_of_fields) { + fprintf(stderr, "aaip_encode(): WRONG NUMBER OF FIELDS %d <> %d\n", + number_of_fields, ret); + } +#endif /* Aaip_encode_debuG */ + + return(number_of_fields); +} + + +static void aaip_encode_byte(unsigned char *result, size_t *result_fill, + unsigned char value) +{ + result[(*result_fill / 250) * 255 + 5 + (*result_fill % 250)]= value; + (*result_fill)++; +} + + +static int aaip_encode_comp(unsigned char *result, size_t *result_fill, + char *data, size_t l, int flag) +{ + size_t todo; + char *rpt, *comp_start; + + if(l == 0) { + aaip_encode_byte(result, result_fill, 0); + aaip_encode_byte(result, result_fill, 0); + return(1); + } + for(rpt= data; rpt - data < l;) { + todo= l - (rpt - data); + aaip_encode_byte(result, result_fill, (todo > 255)); + if(todo > 255) + todo= 255; + aaip_encode_byte(result, result_fill, todo); + for(comp_start= rpt; rpt - comp_start < todo; rpt++) + aaip_encode_byte(result, result_fill, *((unsigned char *) rpt)); + } + return(1); +} + + +/* Write the component records for name and attr. Skip the positions of + AA field headers. + @param flag bit0= only count but do not produce result +*/ +static int aaip_encode_pair(char *name, size_t attr_length, char *attr, + unsigned int *num_recs, size_t *comp_size, + unsigned char *result, size_t result_fill, + int flag) +{ + size_t l; + + l= strlen(name); + *num_recs= l / 255 + (!!(l % 255)) + (l == 0) + + attr_length / 255 + (!!(attr_length % 255)) + (attr_length == 0); + *comp_size= l + attr_length + 2 * *num_recs; + + if(flag & 1) + return(1); + + aaip_encode_comp(result, &result_fill, name, l, 0); + aaip_encode_comp(result, &result_fill, attr, attr_length, 0); + return(1); +} + + +/* ----------- Encoder for ACLs ----------- */ + +static ssize_t aaip_encode_acl_text(char *acl_text, + size_t result_size, unsigned char *result, int flag); + + +/* Convert an ACL text as of acl_to_text(3) into the value of an Arbitrary + Attribute. According to AAIP 0.2 this value is to be stored together with + an empty name. + @param acl_text The ACL in long text form + @param result_len Number of bytes in the resulting value + @param result *result will point to the start of the result string. + This is malloc() memory which needs to be freed when + no longer needed + @param flag Bitfield for control purposes + bit0= count only + bit1= use numeric qualifiers rather than names + bit2= this is a default ACL, prepend SWITCH_MARK + @return >0 means ok + 0 means error +*/ +int aaip_encode_acl(char *acl_text, + size_t *result_len, unsigned char **result, int flag) +{ + ssize_t bytes; + + *result= NULL; + *result_len= 0; + bytes= aaip_encode_acl_text(acl_text, (size_t) 0, NULL, 1 | (flag & 6)); + if(bytes < 0) + return(0); + if(flag & 1) { + *result_len= bytes; + return(1); + } + *result= calloc(bytes + 1, 1); + if(*result == NULL) + return(-1); + (*result)[bytes]= 0; + *result_len= bytes; + bytes= aaip_encode_acl_text(acl_text, *result_len, *result, (flag & 6)); + if(bytes != *result_len) { + *result_len= 0; + return(0); + } + return(1); +} + + +static double aaip_numeric_id(char *name, int flag) +{ + double num; + char *cpt; + + for(cpt= name; *cpt != 0; cpt++) + if(*cpt < '0' || *cpt >'9') + break; + if(*cpt != 0) + return(-1); + sscanf(name, "%lf", &num); + return(num); +} + + +/* + @param result_size Number of bytes to store result + @param result Pointer to the start of the result string. + @param flag Bitfield for control purposes + bit0= count only, do not really produce bytes + bit1= use numeric qualifiers + bit2= this is a default ACL, prepend SWITCH_MARK 1 + @return >=0 number of bytes produced resp. counted + <0 means error +*/ +static ssize_t aaip_encode_acl_text(char *acl_text, + size_t result_size, unsigned char *result, int flag) +{ + char *rpt, *npt, *cpt; + int qualifier= 0, perms, type, i, qualifier_len, num_recs; + uid_t uid, huid; + gid_t gid, hgid; + ssize_t count= 0; + struct passwd *pwd; + struct group *grp; + char name[1024]; + double num; + + if(flag & 4) { + /* set SWITCH_MARK to indicate a default ACL */; + if(!(flag & 1)) { + if(count >= result_size) + return(-1); + result[count]= (Aaip_SWITCH_MARK << 4) | Aaip_EXEC; + } + count++; + } + + for(rpt= acl_text; *rpt != 0; rpt= npt) { + npt= strchr(rpt, '\n'); + if(npt == 0) + npt= rpt + strlen(rpt); + else + npt++; + if(*rpt == '#') + continue; + cpt= strchr(rpt, ':'); + if(cpt == NULL) + continue; + cpt= strchr(cpt + 1, ':'); + if(cpt == NULL) + continue; + qualifier= 0; + if(strncmp(rpt, "user:", 5) == 0) { + if(cpt - rpt == 5) + type= Aaip_ACL_USER_OBJ; + else { + if(cpt - (rpt + 5) >= sizeof(name)) + continue; + strncpy(name, rpt + 5, cpt - (rpt + 5)); + name[cpt - (rpt + 5)]= 0; + if(flag & 2) { + type= Aaip_ACL_USER_N; + pwd= getpwnam(name); + if(pwd == NULL) { + num= aaip_numeric_id(name, 0); + if(num <= 0) + goto user_by_name; + uid= huid= num; + } else + uid= huid= pwd->pw_uid; + /* Convert uid into Qualifier Record */ + for(i= 0; huid != 0; i++) + huid= huid >> 8; + qualifier_len= i; + for(i= 0; i < qualifier_len ; i++) + name[i]= uid >> (8 * (qualifier_len - i - 1)); + } else { +user_by_name:; + type= Aaip_ACL_USER; + qualifier_len= strlen(name); + } + qualifier= 1; + } + } else if(strncmp(rpt, "group:", 6) == 0) { + if(cpt - rpt == 6) + type= Aaip_ACL_GROUP_OBJ; + else { + if(cpt - (rpt + 6) >= sizeof(name)) + continue; + strncpy(name, rpt + 6, cpt - (rpt + 6)); + if(flag & 2) { + type= Aaip_ACL_GROUP_N; + grp= getgrnam(name); + if(grp == NULL) { + num= aaip_numeric_id(name, 0); + if(num <= 0) + goto group_by_name; + gid= hgid= num; + } else + gid= hgid= grp->gr_gid; + /* Convert gid into Qualifier Record */ + for(i= 0; hgid != 0; i++) + hgid= hgid >> 8; + qualifier_len= i; + for(i= 0; i < qualifier_len ; i++) + name[i]= gid >> (8 * (qualifier_len - i - 1)); + + } else { +group_by_name:; + type= Aaip_ACL_GROUP; + qualifier_len= strlen(name); + } + qualifier= 1; + } + } else if(strncmp(rpt, "other:", 6) == 0) { + type= Aaip_ACL_OTHER; + } else if(strncmp(rpt, "mask:", 5) == 0) { + type= Aaip_ACL_MASK; + } else + continue; + + if(npt - cpt < 3) + continue; + perms= 0; + if(cpt[1] == 'r') + perms|= Aaip_READ; + if(cpt[2] == 'w') + perms|= Aaip_WRITE; + if(cpt[3] == 'x') + perms|= Aaip_EXEC; + + if(!(flag & 1)) { + if(count >= result_size) + return(-1); + result[count]= perms | ((!!qualifier) << 3) | (type << 4); + } + count++; + + if(qualifier) { + num_recs= (qualifier_len / 127) + !!(qualifier_len % 127); + if(!(flag & 1)) { + if(count + 1 > result_size) + return(-1); + for(i= 0; i < num_recs; i++) { + if(i < num_recs - 1) + result[count++]= 255; + else { + result[count++]= (qualifier_len % 127); + if(result[count - 1] == 0) + result[count - 1]= 127; + } + if(count + (result[count - 1] & 127) > result_size) + return(-1); + memcpy(result + count, name + i * 127, result[count - 1] & 127); + count+= result[count - 1] & 127; + } + } else + count+= qualifier_len + num_recs; + } + } + + return(count); +} + + +/* --------------------------------- Decoder ---------------------------- */ + +/* --- private --- */ + +/* Not less than 2 * 2048 */ +#define Aaip_buffer_sizE 4096 + +/* Enough for one full component record and three empty ones which might get + added in case of unclean end of attribute list. +*/ +#define Aaip_buffer_reservE (257 + 3 * 2) + + +struct aaip_state { + + /* AA field status */ + unsigned char aa_name[2]; + int aa_head_missing; /* number of bytes needed to complete AA field header */ + int aa_missing; /* number of bytes needed to complete current AA field */ + int aa_ends; /* 0= still AA fields expected, 1= last AA being processed, + 2= all AA fields processed, 3= all is delivered */ + + /* Buffer for component records */ + int recs_invalid; /* number of components to skip */ + unsigned char recs[Aaip_buffer_sizE + Aaip_buffer_reservE]; + size_t recs_fill; + unsigned char *recs_start; + int rec_head_missing; /* number of bytes needed to complete rec header */ + int rec_missing; /* number of bytes needed to complete current rec */ + int rec_ends; + + /* Counter for completed data */ + unsigned int num_recs; + size_t ready_bytes; + + /* Counter and meaning for completed components */ + unsigned int num_components; + size_t end_of_components; /* start index of eventual incomplete component */ + int first_is_name; + + /* Last return value of aaip_decode_pair() */ + int pair_status; + unsigned int pairs_skipped; + + /* status of aaip_decode_attrs() */ + size_t list_mem_used; + size_t list_size; + size_t list_num_attrs; + char **list_names; + size_t *list_value_lengths; + char **list_values; + char *name_buf; + size_t name_buf_size; + size_t name_buf_fill; + char *value_buf; + size_t value_buf_size; + size_t value_buf_fill; + int list_pending_pair; +}; + + +/* ------- functions ------ */ + + +size_t aaip_sizeof_aaip_state(void) +{ + return((size_t) sizeof(struct aaip_state)); +} + + +int aaip_init_aaip_state(struct aaip_state *aaip, char aa_name[2], int flag) +{ + aaip->aa_name[0]= aa_name[0]; + aaip->aa_name[1]= aa_name[1]; + aaip->aa_head_missing= 5; + aaip->aa_missing= 0; + + aaip->recs_invalid= 0; + memset(aaip->recs, 0, Aaip_buffer_sizE + Aaip_buffer_reservE); + aaip->recs_fill= 0; + aaip->recs_start= aaip->recs; + aaip->rec_head_missing= 2; + aaip->rec_missing= 0; + aaip->rec_ends= 0; + + aaip->num_recs= 0; + aaip->ready_bytes= 0; + + aaip->num_components= 0; + aaip->end_of_components= 0; + aaip->first_is_name= 1; + + aaip->pair_status= 2; + aaip->pairs_skipped= 0; + + aaip->list_mem_used= 0; + aaip->list_size= 0; + aaip->list_num_attrs= 0; + aaip->list_names= NULL; + aaip->list_value_lengths= NULL; + aaip->list_values= NULL; + aaip->name_buf= NULL; + aaip->name_buf_size= 0; + aaip->name_buf_fill= 0; + aaip->value_buf= NULL; + aaip->value_buf_size= 0; + aaip->value_buf_fill= 0; + aaip->list_pending_pair= 0; + return(1); +} + +/* +*/ +#define Aaip_with_ring_buffeR yes + +#ifdef Aaip_with_ring_buffeR + +/* Compute the one or two byte intervals in the ring buffer which form a + given byte interval in the virtual shift fifo. + @param idx The byte start index in the virtual shift fifo. + @param todo Number of bytes to cover + @param start_pt Will return the start address of the first interval + @param at_start_pt Will return the size of the first interval + @param at_recs Will return the size of the second interval which + always starts at aaip->recs + @param flag Bitfield for control purposes + @return 1= next start_pt is *start_pt + *at_start_pt + 2= next start_pt is aaip->recs + *at_recs +*/ +static int aaip_ring_adr(struct aaip_state *aaip, size_t idx, size_t todo, + unsigned char **start_pt, size_t *at_start_pt, + size_t *at_recs, int flag) +{ + size_t ahead; + + ahead= Aaip_buffer_sizE + Aaip_buffer_reservE + - (aaip->recs_start - aaip->recs); + if(idx < ahead) + *start_pt= (aaip->recs_start + idx); + else + *start_pt= aaip->recs + (idx - ahead); + ahead= Aaip_buffer_sizE + Aaip_buffer_reservE - (*start_pt - aaip->recs); + if(todo >= ahead) { + *at_start_pt= ahead; + *at_recs= todo - ahead; + return(2); + } + *at_start_pt= todo; + *at_recs= 0; + return(1); +} + + +/* + @param flag Bitfield for control purposes + bit0= count as ready_bytes +*/ +static int aaip_push_to_recs(struct aaip_state *aaip, unsigned char *data, + size_t todo, int flag) +{ + unsigned char *start_pt; + size_t at_start_pt, at_recs; + + aaip_ring_adr(aaip, aaip->recs_fill, todo, + &start_pt, &at_start_pt, &at_recs, 0); + if(at_start_pt > 0) + memcpy(start_pt, data, at_start_pt); + if(at_recs > 0) + memcpy(aaip->recs, data + at_start_pt, at_recs); + aaip->recs_fill+= todo; + if(flag & 1) + aaip->ready_bytes+= todo; + return(1); +} + + +static int aaip_read_from_recs(struct aaip_state *aaip, size_t idx, + unsigned char *data, size_t num_data, int flag) +{ + unsigned char *start_pt; + size_t at_start_pt, at_recs; + + aaip_ring_adr(aaip, idx, num_data, + &start_pt, &at_start_pt, &at_recs, 0); + if(at_start_pt > 0) + memcpy(data, start_pt, at_start_pt); + if(at_recs > 0) + memcpy(data + at_start_pt, aaip->recs, at_recs); + return(1); +} + + +static int aaip_set_buffer_byte(struct aaip_state *aaip, size_t idx, + unsigned char data, int flag) +{ + unsigned char *start_pt; + size_t at_start_pt, at_recs; + + aaip_ring_adr(aaip, idx, 1, + &start_pt, &at_start_pt, &at_recs, 0); + *start_pt= data; + return(1); +} + + +static int aaip_get_buffer_byte(struct aaip_state *aaip, size_t idx, int flag) +{ + unsigned char *start_pt; + size_t at_start_pt, at_recs; + + aaip_ring_adr(aaip, idx, 1, + &start_pt, &at_start_pt, &at_recs, 0); + return((int) *start_pt); +} + + +static int aaip_shift_recs(struct aaip_state *aaip, size_t todo, int flag) +{ + int ret; + unsigned char *start_pt; + size_t at_start_pt, at_recs; + + if(todo < aaip->recs_fill) { + ret= aaip_ring_adr(aaip, 0, todo, &start_pt, &at_start_pt, &at_recs, 0); + if(ret == 1) + aaip->recs_start= start_pt + todo; + else + aaip->recs_start= aaip->recs + at_recs; + } else { + aaip->recs_start= aaip->recs; + } + aaip->recs_fill-= todo; + if(aaip->end_of_components >= todo) + aaip->end_of_components-= todo; + else + aaip->end_of_components= 0; + return(1); +} + + +#else /* Aaip_with_ring_buffeR */ + + +/* + @param flag Bitfield for control purposes + bit0= count as ready_bytes +*/ +static int aaip_push_to_recs(struct aaip_state *aaip, unsigned char *data, + size_t todo, int flag) +{ + memcpy(aaip->recs + aaip->recs_fill, data, todo); + aaip->recs_fill+= todo; + if(flag & 1) + aaip->ready_bytes+= todo; + return(1); +} + + +static int aaip_read_from_recs(struct aaip_state *aaip, size_t idx, + unsigned char *data, size_t num_data, int flag) +{ + memcpy(data, aaip->recs + idx, num_data); + return(1); +} + + +static int aaip_set_buffer_byte(struct aaip_state *aaip, size_t idx, + unsigned char data, int flag) +{ + aaip->recs[idx]= data; + return(1); +} + + +static int aaip_get_buffer_byte(struct aaip_state *aaip, size_t idx, int flag) +{ + return((int) aaip->recs[idx]); +} + + +static int aaip_shift_recs(struct aaip_state *aaip, size_t todo, int flag) +{ + if(todo < aaip->recs_fill) + memmove(aaip->recs, aaip->recs + todo, aaip->recs_fill - todo); + aaip->recs_fill-= todo; + + if(aaip->end_of_components >= todo) + aaip->end_of_components-= todo; + else + aaip->end_of_components= 0; + return(1); +} + + +#endif /* ! Aaip_with_ring_buffeR */ + + +static int aaip_consume_rec_head(struct aaip_state *aaip, + unsigned char **data, size_t *num_data, int flag) +{ + size_t todo; + + todo= *num_data; + if(todo > aaip->aa_missing) + todo= aaip->aa_missing; + if(todo >= aaip->rec_head_missing) + todo= aaip->rec_head_missing; + if(!aaip->recs_invalid) + aaip_push_to_recs(aaip, *data, todo, 0); + aaip->rec_head_missing-= todo; + if(aaip->rec_head_missing == 0) { + aaip->rec_missing= aaip_get_buffer_byte(aaip, aaip->recs_fill - 1, 0); + aaip->rec_ends= !(aaip_get_buffer_byte(aaip, aaip->recs_fill - 2, 0) & 1); + } + aaip->aa_missing-= todo; + (*num_data)-= todo; + (*data)+= todo; + return(1); +} + + +static int aaip_consume_rec_data(struct aaip_state *aaip, + unsigned char **data, size_t *num_data, int flag) +{ + size_t todo; + + todo= *num_data; + if(todo > aaip->aa_missing) + todo= aaip->aa_missing; + if(todo > aaip->rec_missing) + todo= aaip->rec_missing; + if(!aaip->recs_invalid) + aaip_push_to_recs(aaip, *data, todo, 1); + aaip->rec_missing-= todo; + aaip->aa_missing-= todo; + (*num_data)-= todo; + (*data)+= todo; + if(aaip->rec_missing <= 0) { + if(aaip->recs_invalid > 0) { + if(aaip->rec_ends) + aaip->recs_invalid--; + } else { + aaip->num_recs++; + if(aaip->rec_ends) { + aaip->num_components++; + aaip->end_of_components= aaip->recs_fill; + } + } + aaip->rec_head_missing= 2; + } + return(0); +} + + +static int aaip_consume_aa_head(struct aaip_state *aaip, + unsigned char **data, size_t *num_data, int flag) +{ + size_t todo; + unsigned char aa_head[5]; + + todo= *num_data; + if(todo >= aaip->aa_head_missing) + todo= aaip->aa_head_missing; + aaip_push_to_recs(aaip, *data, todo, 0); + aaip->aa_head_missing-= todo; + if(aaip->aa_head_missing == 0) { + aaip_read_from_recs(aaip, aaip->recs_fill - 5, aa_head, 5, 0); + if(aa_head[0] != aaip->aa_name[0] || aa_head[1] != aaip->aa_name[1] || + aa_head[3] != 1) + return(-1); + aaip->aa_missing= aa_head[2]; + aaip->aa_ends= !(aa_head[4] & 1); + aaip->recs_fill-= 5; /* AA heads do not get delivered */ + if(aaip->aa_missing >= 5) + aaip->aa_missing-= 5; + else + aaip->aa_missing= 0; + } + (*num_data)-= todo; + (*data)+= todo; + return(1); +} + + +static int aaip_consume_aa_data(struct aaip_state *aaip, + unsigned char **data, size_t *num_data, int flag) +{ + size_t i; + static unsigned char zero_char[2]= {0, 0}; + + while(*num_data > 0 && aaip->aa_missing > 0) { + if(aaip->rec_head_missing > 0) { + aaip_consume_rec_head(aaip, data, num_data, 0); + if(*num_data == 0 || aaip->aa_missing <= 0) + return(1); + } + aaip_consume_rec_data(aaip, data, num_data, 0); + } + if(aaip->aa_missing <= 0) { + if(aaip->aa_ends) { + /* Check for incomplete pair and eventually make emergency closure */ + if(aaip->rec_head_missing != 2) { /* incomplete record detected */ + if(aaip->rec_head_missing) { + /* fake 0 length record */ + aaip_set_buffer_byte(aaip, aaip->recs_fill - 1, (unsigned char) 0, 0); + aaip_push_to_recs(aaip, zero_char, 1, 0); + } else { + /* fill in missing btes */ + for(i= 0; i < aaip->rec_missing; i++) + aaip_push_to_recs(aaip, zero_char, 1, 1); + } + aaip->rec_head_missing= 2; + aaip->rec_missing= 0; + aaip->num_recs++; + if(aaip->rec_ends) { + aaip->num_components++; + aaip->end_of_components= aaip->recs_fill; + } + } + if(aaip->end_of_components != aaip->recs_fill && + aaip->end_of_components != 0) { + /* incomplete component detected */ + /* add empty end record */ + aaip_push_to_recs(aaip, zero_char, 2, 0); + aaip->num_recs++; + aaip->num_components++; + aaip->end_of_components= aaip->recs_fill; + } + if(!(aaip->first_is_name ^ (aaip->num_components % 2))) { + /* value component is missing */ + /* add dummy component */ + aaip_push_to_recs(aaip, zero_char, 2, 0); + aaip->num_recs++; + aaip->num_components++; + aaip->end_of_components= aaip->recs_fill; + } + aaip->aa_ends= 2; + } else + aaip->aa_head_missing= 5; + } + return(0); +} + + +/* Submit small data chunk for decoding. + The return value will tell whether data are pending for being fetched. + @param aaip The AAIP decoder context + @param data Not more than 2048 bytes input for the decoder + @parm num_data Number of bytes in data + 0 inquires the buffer status avoiding replies <= 0 + @param ready_bytes Number of decoded bytes ready for delivery + @param flag Bitfield for control purposes + @return -1= non-AA field detected + *ready_bytes gives number of consumed bytes in data + 0= cannot accept data because buffer full + 1= no component record complete, submit more data + 2= component record complete, may be delivered + 3= component complete, may be delivered + 4= no component available, no more data expected, done +*/ +int aaip_submit_data(struct aaip_state *aaip, + unsigned char *data, size_t num_data, + size_t *ready_bytes, int flag) +{ + int ret; + unsigned char *in_data; + + if(aaip->aa_ends == 3) + return(4); + in_data= data; + if(num_data == 0) + goto ex; + if(aaip->recs_fill + num_data > Aaip_buffer_sizE) + return(0); + + while(num_data > 0) { + if(aaip->aa_head_missing > 0) { + ret= aaip_consume_aa_head(aaip, &data, &num_data, 0); + if(ret < 0) { + *ready_bytes= data - in_data; + return(-1); + } + if(num_data == 0 || aaip->aa_missing <= 0) + goto ex; + } + aaip_consume_aa_data(aaip, &data, &num_data, 0); + if(aaip->aa_missing) + break; + } +ex:; + *ready_bytes= aaip->ready_bytes; + if(aaip->num_components > 0) + return(3); + if(aaip->num_recs > 0) + return(2); + if(aaip->aa_ends && aaip->aa_head_missing == 0 && aaip->aa_missing == 0) + aaip->aa_ends= 2; + if(aaip->aa_ends == 2 && aaip->num_recs == 0) + aaip->aa_ends= 3; + if(aaip->aa_ends == 3) + return(4); + return(1); +} + + +/* Fetch the available part of current component. + The return value will tell whether it belongs to name or to value and + whether that name or value is completed now. + @param aaip The AAIP decoder context + @param result Has to point to storage for the component data + @param result_size Gives the amount of provided result storage + @param num_result Will tell the number of fetched result bytes + @param flag Bitfield for control purposes + bit0= discard data rather than copying to result + @return -2 = insufficient result_size + -1 = no data ready for delivery + 0 = result holds the final part of a name + 1 = result holds an intermediate part of a name + 2 = result holds the final part of a value + 3 = result holds an intermediate part of a value +*/ +int aaip_fetch_data(struct aaip_state *aaip, + char *result, size_t result_size, size_t *num_result, + int flag) +{ + int ret= -1, complete= 0, payload; + unsigned int i, num_bytes= 0, h; + + if(aaip->num_recs == 0) + return(-1); + + /* Copy data until end of buffer or end of component */ + h= 0; + for(i= 0; i < aaip->num_recs && !complete; i++) { + payload= aaip_get_buffer_byte(aaip, h + 1, 0); + if(!(flag & 1)) { + if(num_bytes + payload > result_size) + return(-2); + aaip_read_from_recs(aaip, h + 2, (unsigned char *) (result + num_bytes), + payload, 0); + *num_result= num_bytes + payload; + } + num_bytes+= payload; + if(!(aaip_get_buffer_byte(aaip, h, 0) & 1)) + complete= 1; + h+= payload + 2; + } + aaip->ready_bytes-= num_bytes; + aaip->num_recs-= i; + + /* Shift buffer */ + aaip_shift_recs(aaip, h, 0); + + /* Compute reply */ + ret= 2 * !aaip->first_is_name; + if(complete) { + aaip->first_is_name= !aaip->first_is_name; + if(aaip->num_components > 0) + aaip->num_components--; + } else + ret|= 1; + + return(ret); +} + + +/* Skip the current component and eventually the following value component. + This has to be called if fetching of a component shall be aborted + but the next component resp. pair shall be fetchable again. + aaip_submit_data() will not indicate readiness for fetching until all + bytes of the skipped components are submitted. Those bytes get discarded. + @param aaip The AAIP decoder context + @param flag Bitfield for control purposes + bit0= do not skip value if current component is name + @return <=0 error , 1= now in skip state, 2= not in skip state +*/ +int aaip_skip_component(struct aaip_state *aaip, int flag) +{ + int to_skip= 1; + + if(aaip->first_is_name && !(flag & 1)) + to_skip= 2; + if(aaip->recs_invalid) { + aaip->recs_invalid+= to_skip; + return(1); + } + + if(aaip->num_components) { + /* null-fetch */ + aaip_fetch_data(aaip, NULL, (size_t) 0, NULL, 1); + to_skip--; + } + if(aaip->num_components && to_skip) { + /* null-fetch */ + aaip_fetch_data(aaip, NULL, (size_t) 0, NULL, 1); + to_skip--; + } + if(to_skip) { + aaip->recs_fill= 0; + aaip->num_recs= 0; + aaip->ready_bytes= 0; + } + aaip->recs_invalid= to_skip; + if(aaip->aa_ends == 2 && aaip->num_recs == 0) + aaip->aa_ends= 3; + return(1 + (aaip->num_recs > 0)); +} + + +/* ------------------------- Pair Level Interface ------------------------ */ + +/* + @param flag Bitfield for control purposes + bit0= do not skip oversized component but return -2 + @return see aaip_decode_pair +*/ +static int aaip_advance_pair(struct aaip_state *aaip, + char *name, size_t name_size, size_t *name_fill, + char *value, size_t value_size, size_t *value_fill, + int flag) +{ + int ret; + char *wpt; + size_t size, num; + +retry:; + if(aaip->first_is_name) { + wpt= name + *name_fill; + size= name_size - *name_fill; + } else { + wpt= value + *value_fill; + size= value_size - *value_fill; + } + ret= aaip_fetch_data(aaip, wpt, size, &num, 0); + if(ret == -2) { /* insufficient result size */ + if(flag & 1) + return(-2); + ret= aaip_skip_component(aaip, 0); + *name_fill= *value_fill= 0; + aaip->pairs_skipped++; + if(ret == 2) /* Skip performed, valid data pending */ + goto retry; + } else if(ret == -1) { /* No data ready for delivery : may not happen */ + return(-1); + } else if(ret == 0) { /* result holds the final part of a name */ + (*name_fill)+= num; + /* peek for value data */ + ret= aaip_submit_data(aaip, NULL, (size_t) 0, &num, 0); + if(ret == 2 || ret == 3) { + /* fetch value data */; + ret= aaip_advance_pair(aaip, name, name_size, name_fill, + value, value_size, value_fill, flag); + return ret; + } else if(ret == 4) + return(5); + } else if(ret == 1) { /* result holds an intermediate part of a name */ + (*name_fill)+= num; + } else if(ret == 2) { /* result holds the final part of a value */ + (*value_fill)+= num; + if(aaip->num_components >= 2) + return(3); + if(aaip->aa_ends == 2 && aaip->num_recs == 0) + aaip->aa_ends= 3; + if(aaip->aa_ends == 3) + return(4); + return(2); + } else if(ret == 3) { + /* result holds an intermediate part of a value */; + (*value_fill)+= num; + } else { + return(-1); /* unknown reply from aaip_fetch_data() */ + } + return(1); +} + + +/* Accept raw input data and collect a pair of name and value. + The return value will indicate whether the pair is complete, whether more + pairs are complete or whether more data are desired. No input data will be + accepted as long as complete pairs are pending. The end of the attribute + list will be indicated. + @param aaip The AAIP decoder context + @param data The raw data to decode + @param num_data Number of data bytes provided + @param consumed Returns the number of consumed data bytes + @param name Buffer to build the name string + @param name_size Maximum number of bytes in name + @param name_fill Holds the current buffer fill of name + @param value Buffer to build the value string + @param value_size Maximum number of bytes in value + @param value_fill Holds the current buffer fill of value + @param flag Bitfield for control purposes + bit0= do not skip oversized pair but return -2 + @return <0 error + -3 buffer full (program error) + -2 insufficient result_size (only with flag bit0) + -1 non-AA field detected + 0 data not accepted, first fetch pending pairs with num_data == 0 + 1 name and value are not valid yet, submit more data + 2 name and value are valid, submit more data + 3 name and value are valid, pairs pending, fetch with num_data == 0 + 4 name and value are valid, no more data expected + 5 name and value are not valid, no more data expected +*/ +int aaip_decode_pair(struct aaip_state *aaip, + unsigned char *data, size_t num_data, size_t *consumed, + char *name, size_t name_size, size_t *name_fill, + char *value, size_t value_size, size_t *value_fill, + int flag) +{ + int ret; + size_t ready_bytes; + + *consumed= 0; + if((aaip->pair_status < 0 && aaip->pair_status != -2) || + aaip->pair_status == 4 || + aaip->pair_status == 5) { /* dead ends */ + ret= aaip->pair_status; + goto ex; + } else if(aaip->pair_status == 2 || aaip->pair_status == 3) { + if(aaip->pair_status == 3 && num_data > 0) + {ret= 0; goto ex;} + /* Start a new pair */ + if(!aaip->first_is_name) /* Eventually skip orphaned value */ + aaip_fetch_data(aaip, NULL, (size_t) 0, NULL, 1); + *name_fill= *value_fill= 0; + } + + if(num_data > 0) { + ret= aaip_submit_data(aaip, data, num_data, &ready_bytes, 0); + } else { + ret= 1; + if(aaip->num_components) + ret= 3; + else if(aaip->num_recs) + ret= 2; + } + if(ret < 0) { /* non-AA field detected */ + *consumed= ready_bytes; + {ret= -1; goto ex;} + } else if(ret == 0) { /* buffer overflow */; + /* should not happen with correct usage */ + {ret= -3; goto ex;} + } else if(ret == 1) { /* no component record complete */ + goto ex; + } else if(ret == 2) { /* component record complete, may be delivered */ + ; + } else if(ret == 3) { /* component complete, may be delivered */ + ; + } else if(ret == 4) { /* no component available, no more data expected */ + {ret= 5; goto ex;} + } else + {ret= -1; goto ex;} /* unknown reply from aaip_submit_data() */ + + *consumed= num_data; + ret= aaip_advance_pair(aaip, name, name_size, name_fill, + value, value_size, value_fill, flag & 1); + if(aaip->aa_ends == 3) { + if(ret >= 2 && ret <= 4) + ret= 4; + else + ret= 5; + } +ex:; + aaip->pair_status= ret; + return(ret); +} + + +unsigned int aaip_get_pairs_skipped(struct aaip_state *aaip, int flag) +{ + return(aaip->pairs_skipped); +} + + +/* ------------------------- List Level Interface ------------------------ */ + + +#define Aaip_initial_name_leN 256 +#define Aaip_initial_value_leN 256 +#define Aaip_initial_list_sizE 2 +#define Aaip_list_enlargeR 1.5 + + +/* + @param flag Bitfield for control purposes + bit0= do not update *buf_size +*/ +static int aaip_enlarge_buf(struct aaip_state *aaip, size_t memory_limit, + size_t item_size, char **buf, size_t *buf_size, int flag) +{ + size_t new_size; + char *new_buf; + + new_size= *buf_size * Aaip_list_enlargeR; + if(aaip->list_mem_used + (new_size - *buf_size) * item_size >= memory_limit) + return(3); + aaip->list_mem_used+= (new_size - *buf_size) * item_size; + new_buf= realloc(*buf, new_size * item_size); + if(new_buf == NULL) + return(-1); + *buf= new_buf; + if(!(flag & 1)) + *buf_size= new_size; + return(1); +} + + +/* Accept raw input data and collect arrays of name pointers, value lengths + and value pointers. A handle object will emerge which finally has to be + be freed by a call with bit 15. + @param handle The decoding context. + It will be created by this call with flag bit 0 or if + *handle == NULL. This handle has to be the same as long + as decoding goes on and finally has to be freed by a + call with bit15. + @param aa_name The Signature Word (advised is "AA") + @param memory_limit Maximum number of bytes to allocate + @param num_attr_limit Maximum number of name-value pairs to allocate + @param data The raw data to decode + @param num_data Number of data bytes provided + @param consumed Returns the number of consumed data bytes + @param flag Bitfield for control purposes + bit0= this is the first call with the given handle + (also in effect if *handle is NULL) + bit15= end decoding : + Free handle and its intermediate list memory. + @return <=0 error + -3 program error, unexpected reply from lower layers + -2 non-AA-field detected, arrays are complete, + call aaip_get_decoded_attrs() + -1 out of memory + 1 not complete yet, submit more data + 2 arrays are complete, call aaip_get_decoded_attrs() + 3 limit exceeded, not complete yet, + enlarge memory_limit or call with bit15 and give up + 4 limit exceeded, call aaip_get_decoded_attrs() and try again +*/ +int aaip_decode_attrs(struct aaip_state **handle, char aa_name[2], + size_t memory_limit, size_t num_attr_limit, + unsigned char *data, size_t num_data, size_t *consumed, + int flag) +{ + int ret, was_non_aa= 0; + struct aaip_state *aaip; + size_t h_num, *h_lengths, i, new_mem, pair_consumed= 0; + char **h_names, **h_values; + + *consumed= 0; + if(flag & (1 << 15)) { + if(*handle == NULL) + return(0); + ret= aaip_get_decoded_attrs(handle, &h_num, &h_names, &h_lengths, &h_values, + 0); + if(ret > 0) + aaip_get_decoded_attrs(handle, &h_num, &h_names, &h_lengths, &h_values, + 1 << 15); + if((*handle)->name_buf != NULL) + free((*handle)->name_buf); + if((*handle)->value_buf != NULL) + free((*handle)->value_buf); + free((char *) *handle); + *handle= NULL; + return(1); + } + + aaip= *handle; + if(aaip == NULL || (flag & 1)) { + aaip= *handle= calloc(1, sizeof(struct aaip_state)); + if(*handle == NULL) + return(-1); + aaip_init_aaip_state(*handle, aa_name, 0); + } + if(aaip->list_names == NULL || aaip->list_values == NULL || + aaip->list_value_lengths == NULL) { + /* Initialize arrays */ + aaip->list_size= Aaip_initial_list_sizE; + if(num_attr_limit > 0 && num_attr_limit < aaip->list_size) + aaip->list_size= num_attr_limit; + new_mem= aaip->list_size * (2*sizeof(char *) + sizeof(size_t)) + + Aaip_initial_name_leN + Aaip_initial_value_leN; + if(aaip->list_mem_used + new_mem >= memory_limit) + return(3); + aaip->list_mem_used+= new_mem; + aaip->list_names= calloc(sizeof(char *), aaip->list_size); + aaip->list_value_lengths= calloc(sizeof(size_t), aaip->list_size); + aaip->list_values= calloc(sizeof(char *), aaip->list_size); + if(aaip->list_names == NULL || aaip->list_value_lengths == NULL || + aaip->list_values == NULL) + return(-1); + for(i= 0; i < aaip->list_size; i++) { + aaip->list_names[i]= NULL; + aaip->list_value_lengths[i]= 0; + aaip->list_values[i]= NULL; + } + } + if(aaip->name_buf == NULL || aaip->value_buf == NULL) { + new_mem= Aaip_initial_name_leN + Aaip_initial_value_leN; + if(aaip->list_mem_used >= memory_limit) + return(3); + aaip->list_mem_used+= new_mem; + aaip->name_buf= calloc(sizeof(char *), Aaip_initial_name_leN); + aaip->value_buf= calloc(sizeof(char *), Aaip_initial_value_leN); + if(aaip->name_buf == NULL || aaip->value_buf == NULL) + return(-1); + aaip->name_buf_size= Aaip_initial_name_leN; + aaip->value_buf_size= Aaip_initial_name_leN; + } + + while(1) { + if(aaip->list_pending_pair > 0) { + /* the buffer holds a complete pair from a previous memory limit refusal */ + ret= aaip->list_pending_pair; + aaip->list_pending_pair= 0; + } else { + ret= aaip_decode_pair(aaip, data, num_data, &pair_consumed, + aaip->name_buf, aaip->name_buf_size, &aaip->name_buf_fill, + aaip->value_buf, aaip->value_buf_size, &aaip->value_buf_fill, + 1); + *consumed+= pair_consumed; + } + if(ret == -2) { /* insufficient result_size */ + if(aaip->first_is_name) + ret= aaip_enlarge_buf(aaip, memory_limit, (size_t) 1, &(aaip->name_buf), + &(aaip->name_buf_size), 0); + else + ret= aaip_enlarge_buf(aaip, memory_limit, (size_t) 1, + &(aaip->value_buf), &(aaip->value_buf_size), 0); + if(ret != 1) + return(ret); + + } else if(ret == -1) { /* non-AA field detected */ + was_non_aa= 1; + + } else if(ret < 0) { /* other error */ + return(-3); + + } else if(ret == 0) { /* first fetch pending pairs with num_data == 0 */ + /* should not happen, fetch more pairs */; + + } else if(ret == 1) { + /* name and value are not valid yet, submit more data */ + return(1); + + } else if(ret == 2 || ret == 3 || ret == 4) { + /* name and value are valid, submit more data */ + /* name and value are valid, pairs pending, fetch with num_data == 0 */ + /* name and value are valid, no more data expected */ + aaip->list_pending_pair= ret; + + if(aaip->list_num_attrs >= aaip->list_size) { + ret= aaip_enlarge_buf(aaip, memory_limit, sizeof(char *), + (char **) &(aaip->list_names), &(aaip->list_size), 1); + if(ret != 1) + return(ret); + ret= aaip_enlarge_buf(aaip, memory_limit, sizeof(char *), + (char **) &(aaip->list_values), &(aaip->list_size), 1); + if(ret != 1) + return(ret); + ret= aaip_enlarge_buf(aaip, memory_limit, sizeof(size_t), + (char **) &(aaip->list_value_lengths), &(aaip->list_size), 0); + if(ret != 1) + return(ret); + } + + /* Allocate name and value in list */; + if(aaip->list_mem_used + aaip->name_buf_fill + aaip->value_buf_fill + 2 + > memory_limit) { + return(3); + } + aaip->list_mem_used+= aaip->name_buf_fill + aaip->value_buf_fill + 2; + i= aaip->list_num_attrs; + aaip->list_names[i]= calloc(aaip->name_buf_fill + 1, 1); + aaip->list_values[i]= calloc(aaip->value_buf_fill + 1, 1); + memcpy(aaip->list_names[i], aaip->name_buf, aaip->name_buf_fill); + aaip->list_names[i][aaip->name_buf_fill]= 0; + memcpy(aaip->list_values[i], aaip->value_buf, aaip->value_buf_fill); + aaip->list_values[i][aaip->value_buf_fill]= 0; + aaip->list_value_lengths[i]= aaip->value_buf_fill; + aaip->list_num_attrs++; + aaip->name_buf_fill= aaip->value_buf_fill= 0; + + ret= aaip->list_pending_pair; + aaip->list_pending_pair= 0; + + if(ret == 2) + return(1); + if(ret == 4) + break; + + } else if(ret == 5) + break; + else + return(-2); + + num_data= 0; /* consume pending pairs */ + } + aaip->list_pending_pair= 5; + return(2); +} + + +/* Obtain the resulting attributes when aaip_decode_attrs() indicates to + be done or to have the maximum possible amount of result ready. + The returned data objects finally have to be freed by a call with flag + bit 15. + @param handle The decoding context created by aaip_decode_attrs() + @param num_attrs Will return the number of name-value pairs + @param names Will return an array of pointers to 0-terminated names + @param value_lengths Will return an arry with the lenghts of values + @param values Will return an array of pointers to 8-bit values + @param flag Bitfield for control purposes + bit15= free memory of names, value_lengths, values + @return <0 error + 0 no attribute list ready + 1 ok +*/ +int aaip_get_decoded_attrs(struct aaip_state **handle, size_t *num_attrs, + char ***names, size_t **value_lengths, char ***values, + int flag) +{ + size_t i; + struct aaip_state *aaip; + + aaip= *((struct aaip_state **) handle); + if(flag & (1 << 15)) { + if(*names != NULL) { + for(i= 0; i < *num_attrs; i++) { + if((*names)[i] != NULL) + free((*names)[i]); + (*names)[i]= NULL; + } + free(*names); + *names= NULL; + } + if(*values != NULL) { + for(i= 0; i < *num_attrs; i++) { + if((*values)[i] != NULL) + free((*values)[i]); + (*values)[i]= NULL; + } + free(*values); + *values= NULL; + } + if(*value_lengths != NULL) + free(*value_lengths); + *value_lengths= NULL; + *num_attrs= 0; + return(1); + } + + /* Check whether decoding is finished yet */ + if(aaip->list_pending_pair != 5) + return(0); + + *num_attrs= aaip->list_num_attrs; + *names= aaip->list_names; + *value_lengths= aaip->list_value_lengths; + *values= aaip->list_values; + + /* Now the memory is owned by the caller */ + aaip->list_num_attrs= 0; + aaip->list_names= NULL; + aaip->list_value_lengths= NULL; + aaip->list_values= NULL; + aaip->list_size= 0; + aaip->list_pending_pair= 0; + return(1); +} + + +/* ------ Decoder for ACLs ------ */ + + +static int aaip_write_acl_line(char **result, size_t *result_size, + char *tag_type, char *qualifier, + char *permissions, int flag) +{ + size_t needed, tag_len, perm_len, qualifier_len; + + tag_len= strlen(tag_type); + qualifier_len= strlen(qualifier); + perm_len= strlen(permissions); + needed= tag_len + qualifier_len + perm_len + 3; + if((flag & 1)) { + (*result_size)+= needed; + return(1); + } + if(needed + 1 > *result_size) /* +1 : want to append a trailing 0 */ + return(-1); + memcpy((*result), tag_type, tag_len); + (*result)[tag_len]= ':'; + memcpy((*result) + tag_len + 1, qualifier, qualifier_len); + (*result)[tag_len + 1 + qualifier_len]= ':'; + memcpy((*result) + tag_len + 1 + qualifier_len + 1, permissions, perm_len); + (*result)[tag_len + 1 + qualifier_len + 1 + perm_len]= '\n'; + (*result)[tag_len + 1 + qualifier_len + 1 + perm_len + 1] = 0; + (*result)+= needed; + (*result_size)-= needed; + return(1); +} + + +static int aaip_read_qualifier(unsigned char *data, size_t num_data, + char *name, size_t name_size, size_t *name_fill, + int flag) +{ + int is_done= 0, rec_len= 0; + unsigned char *rpt; + + *name_fill= 0; + for(rpt= data; !is_done; rpt+= rec_len) { + rec_len= (*rpt) & 127; + is_done= !((*rpt) & 128); + if(*name_fill + rec_len >= name_size || rpt + 1 + rec_len - data > num_data) + return(-1); + memcpy(name + *name_fill, rpt + 1, rec_len); + rpt+= 1 + rec_len; + (*name_fill)+= rec_len; + name[*name_fill]= 0; + } + return(1); +} + + +/* Convert an AAIP ACL attribute value into the long text form of ACL. + @param data The raw data to decode + @param num_data Number of data bytes provided + @param consumed Returns the number of consumed data bytes + @param acl_text Will be filled with ACL long text form + @param acl_text_size Maximum number of bytes to be written to acl_text + @param acl_text_fill Will return the number of bytes in acl_text + @param flag Bitfield for control purposes + bit0= count only, do not really produce bytes: + acl_text will not be touched, + acl_text_size will be ignored, + *acl_text_fill will return the counted number + plus 1 for a trailing zero. + bit1= expected is a default ACL (see return value 2) + @return 1 success + 2 success, begin of default/access ACL encountered, + submit data + *consumed for access/default ACL + -1 error with reading of qualifier + -2 error with writing of ACL text line + -3 version mismatch + -4 unknown tag type encountered +*/ +int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed, + char *acl_text, size_t acl_text_size, + size_t *acl_text_fill, int flag) +{ + unsigned char *rpt; + char perm_text[4], *wpt, name[1024]; + int type, qualifier= 0, perm, ret, i, cnt; + size_t w_size, name_fill; + uid_t uid; + gid_t gid; + struct passwd *pwd; + struct group *grp; + + cnt= flag & 1; + *consumed= 0; + wpt= acl_text; + w_size= acl_text_size; + *acl_text_fill= 0; + for(rpt= data; rpt - data < num_data; ) { + perm= *rpt; + strcpy(perm_text, "---"); + if(perm & Aaip_READ) + perm_text[0]= 'r'; + if(perm & Aaip_WRITE) + perm_text[1]= 'w'; + if(perm & Aaip_EXEC) + perm_text[2]= 'x'; + + type= (*rpt) >> 4; + if(type == Aaip_FUTURE_VERSION) /* indicate to caller: version mismatch */ + return(-3); + + qualifier= !!((*rpt) & 8); + if(qualifier) { + ret= aaip_read_qualifier(rpt + 1, num_data - (rpt + 1 - data), + name, sizeof(name), &name_fill, 0); + if(ret <= 0) + return(-1); + } + + /* Advance read pointer */ + (*consumed)+= 1 + (qualifier ? name_fill + 1 : 0); + rpt+= 1 + (qualifier ? name_fill + 1 : 0); + + ret= 1; + if(type == Aaip_TRANSLATE) { + /* rightfully ignored yet */; + continue; + } else if(type == Aaip_ACL_USER_OBJ) { + /* user::rwx */ + ret= aaip_write_acl_line(&wpt, &w_size, "user", "", perm_text, cnt); + } else if(type == Aaip_ACL_USER) { + /* user::rwx */; + ret= aaip_write_acl_line(&wpt, &w_size, "user", name, perm_text, cnt); + } else if(type == Aaip_ACL_GROUP_OBJ) { + /* user::rwx */ + ret= aaip_write_acl_line(&wpt, &w_size, "group", "", perm_text, cnt); + } else if(type == Aaip_ACL_GROUP) { + /* group::rwx */; + ret= aaip_write_acl_line(&wpt, &w_size, "group", name, perm_text, cnt); + } else if(type == Aaip_ACL_MASK) { + /* mask::rwx */ + ret= aaip_write_acl_line(&wpt, &w_size, "mask", "", perm_text, cnt); + } else if(type == Aaip_ACL_OTHER) { + /* other::rwx */ + ret= aaip_write_acl_line(&wpt, &w_size, "other", "", perm_text, cnt); + } else if(type == Aaip_SWITCH_MARK) { + /* Indicate to caller: end of desired ACL type access/default */ + if((!(perm & Aaip_EXEC)) ^ (!!(flag & 2))) + return(2); + } else if(type == Aaip_ACL_USER_N) { + /* determine username from uid */ + uid= 0; + for(i= 0; i < name_fill; i++) + uid= (uid << 8) | ((unsigned char *) name)[i]; + pwd= getpwuid(uid); + if(pwd == NULL) + sprintf(name, "%.f", (double) uid); + else if(strlen(pwd->pw_name) >= sizeof(name)) + sprintf(name, "%.f", (double) uid); + else + strcpy(name, pwd->pw_name); + /* user::rwx */; + ret= aaip_write_acl_line(&wpt, &w_size, "user", name, perm_text, cnt); + } else if(type == Aaip_ACL_GROUP_N) { + /* determine username from gid */; + gid= 0; + for(i= 0; i < name_fill; i++) + gid= (gid << 8) | ((unsigned char *) name)[i]; + grp= getgrgid(gid); + if(grp == NULL) + sprintf(name, "%.f", (double) gid); + else if(strlen(grp->gr_name) >= sizeof(name)) + sprintf(name, "%.f", (double) gid); + else + strcpy(name, grp->gr_name); + /* user::rwx */; + ret= aaip_write_acl_line(&wpt, &w_size, "group", name, perm_text, cnt); + } else { + /* indicate to caller: unknown type */ + return(-4); + } + if(ret <= 0) + return(-2); + } + if(flag & 1) + *acl_text_fill= w_size + 1; + return(1); +} + + +/* ----------------------- Adapter for operating systems ----------------- */ + + +#ifdef __FreeBSD__ + +#include "aaip-os-freebsd.c" + +#else + +#include "aaip-os-linux.c" + +#endif + diff --git a/libisoburn/branches/ZeroThreeTwo/test/aaip_0_2.h b/libisoburn/branches/ZeroThreeTwo/test/aaip_0_2.h new file mode 100644 index 00000000..6a3fa7fe --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/test/aaip_0_2.h @@ -0,0 +1,381 @@ + +/* + + Arbitrary Attribute Interchange Protocol , AAIP version 0.2 + Demonstration program for encoding and decoding EA and ACL. + + See http://libburnia-project.org/wiki/AAIP + or doc/susp_aaip_0_2.txt + + test/aaip_0.2.h - Public declarations + +*/ + +#ifndef Aaip_h_is_includeD +#define Aaip_h_is_includeD yes + + +/* --------------------------------- Encoder ---------------------------- */ + +/* Convert an array of Arbitrary Attributes into a series of AAIP fields. + @param aa_name The 2 byte SUSP Signature Word of the fields + @param num_attrs Number of attributes + @param names Array of pointers to 0 terminated name strings + @param value_lengths Array of byte lengths for each value + @param values Array of pointers to the value bytes + @param result_len Number of bytes in the resulting SUSP field string + @param result *result will point to the start of the result string. + This is malloc() memory which needs to be freed when + no longer needed + @param flag Bitfield for control purposes + bit0= set CONTINUE bit of last AA field to 1 + @return >0 is the number of SUSP fields generated, + 0 means error +*/ +unsigned int aaip_encode(char aa_name[2], + unsigned int num_attrs, char **names, + size_t *value_lengths, char **values, + size_t *result_len, unsigned char **result, int flag); + + +/* ------ ACL representation ------ */ + +/* Convert an ACL from long text form into the value of an Arbitrary + Attribute. According to AAIP 0.2 this value is to be stored together with + an empty name. + @param acl_text The ACL in long text form + @param result_len Number of bytes in the resulting value + @param result *result will point to the start of the result string. + This is malloc() memory which needs to be freed when + no longer needed + @param flag Bitfield for control purposes + bit0= count only + bit1= use numeric qualifiers rather than names + @return >0 means ok + 0 means error +*/ +int aaip_encode_acl(char *acl_text, + size_t *result_len, unsigned char **result, int flag); + + +/* ------ OS interface ------ */ + +/* Obtain the ACL of the given file in long text form. + @param path Path to the file + @param text Will hold the result. This is a managed object which + finally has to be freed by a call to this function + with bit15 of flag. + @param flag Bitfield for control purposes + bit0= obtain default ACL rather than access ACL + bit15= free text and return 1 + @return > 0 ok + -1 failure of system ACL service (see errno) +*/ +int aaip_get_acl_text(char *path, char **text, int flag); + + +/* Obtain the Extended Attributes and/or the ACLs of the given file in a form + that is ready for aaip_encode(). The returned data objects finally have + to be freed by a call with flag bit 15. + @param path Path to the file + @param num_attrs Will return the number of name-value pairs + @param names Will return an array of pointers to 0-terminated names + @param value_lengths Will return an arry with the lenghts of values + @param values Will return an array of pointers to 8-bit values + @param flag Bitfield for control purposes + bit0= obtain ACLs (access and eventually default) via + system ACL API and encode + bit1= use numeric ACL qualifiers rather than names + bit2= do not obtain attributes other than ACLs + bit3= do not ignore eventual ACL attribute + (e.g. system.posix_acl_access) + bit15= free memory of names, value_lengths, values + @return >0 ok + <=0 error +*/ +int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, + size_t **value_lengths, char ***values, int flag); + + +/* --------------------------------- Decoder ---------------------------- */ + +/* + The AAIP decoder offers several levels of abstraction of which the + lower two avoid the use of dynamic memory. It provides a stateful decoding + context with a small buffer which delivers results to caller provided + memory locations. + + The lowest level is the stream-like Component Level Interface. It allows + to decode very many very long attributes. + + Next is the Pair Level Interface which delivers to fixly sized storage for + name and value. It allows to decode very many attributes. + + The List Level Interface uses dynamic memory allocation to provide arrays + of names, values and value lengths. It is intended for moderately sized + attribute lists but may also be used as alternative to Pair Level. +*/ + + +/* The AAIP decoder context. +*/ +struct aaip_state; + + +/* Obtain the size in bytes of an aaip_state object. +*/ +size_t aaip_sizeof_aaip_state(void); + + +/* Initialize a AAIP decoder context. + This has to be done before the first AA field of a node is processed. + The caller has to provide the storage of the struct aaip_state. + @param aaip The AAIP decoder context to be initialized + @param aa_name The Signature Word (advised is "AA") + @param flag Bitfield for control purposes + submit 0 + @return <=0 error , >0 ok +*/ +int aaip_init_aaip_state(struct aaip_state *aaip, char aa_name[2], int flag); + + +/* ------------------------- Component Level Interface ------------------- */ +/* + Provides support for unlimited component size but demands the caller + to have a growing storage facility resp. to do own oversize handling. + + This interface expects moderatly sized input pieces and will hand out + moderately sized result pieces. The number of transactions is virtually + unlimited. +*/ + +/* Submit small data chunk for decoding. + The return value will tell whether data are pending for being fetched. + @param aaip The AAIP decoder context + @param data Not more than 2048 bytes input for the decoder + @param num_data Number of bytes in data + 0 inquires the buffer status avoiding replies <= 0 + @param ready_bytes Number of decoded bytes ready for delivery + @param flag Bitfield for control purposes + @return -1= non-AA field detected + *ready_bytes gives number of consumed bytes in data + 0= cannot accept data because buffer full + 1= no component record complete, submit more data + 2= component record complete, may be delivered + 3= component complete, may be delivered + 4= no component available, no more data expected, done +*/ +int aaip_submit_data(struct aaip_state *aaip, + unsigned char *data, size_t num_data, + size_t *ready_bytes, int flag); + + +/* Fetch the available part of current component. + The return value will tell whether it belongs to name or to value and + whether that name or value is completed now. + @param aaip The AAIP decoder context + @param result Has to point to storage for the component data + @param result_size Gives the amount of provided result storage + @param num_result Will tell the number of fetched result bytes + @param flag Bitfield for control purposes + bit0= discard data rather than copying to result + @return -2 = insufficient result_size + -1 = no data ready for delivery + 0 = result holds the final part of a name + 1 = result holds an intermediate part of a name + 2 = result holds the final part of a value + 3 = result holds an intermediate part of a value +*/ +int aaip_fetch_data(struct aaip_state *aaip, + char *result, size_t result_size, size_t *num_result, + int flag); + + +/* Skip the current component and eventually the following value component. + This has to be called if fetching of a component shall be aborted + but the next component resp. pair shall be fetchable again. + aaip_submit_data() will not indicate readiness for fetching until all + bytes of the skipped components are submitted. Those bytes get discarded. + @param aaip The AAIP decoder context + @param flag Bitfield for control purposes + bit0= do not skip value if current component is name + @return <=0 error , 1= now in skip state, 2= not in skip state +*/ +int aaip_skip_component(struct aaip_state *aaip, int flag); + + +/* ------------------------- Pair Level Interface ------------------------ */ +/* + Provides support for names and values of limited size. The limits are + given by the caller who has to provide the storage for name and value. + + This interface expects moderatly sized input pieces. + The number of input transcations is virtually unlimited. + The number of pair transactions after aaip_init() should be limited + to 4 billion. +*/ + + +/* Accept raw input data and collect a pair of name and value. + The return value will indicate whether the pair is complete, whether more + pairs are complete or whether more data are desired. No input data will be + accepted as long as complete pairs are pending. The end of the attribute + list will be indicated. + @param aaip The AAIP decoder context + @param data The raw data to decode + @param num_data Number of data bytes provided + @param consumed Returns the number of consumed data bytes + @param name Buffer to build the name string + @param name_size Maximum number of bytes in name + @param name_fill Holds the current buffer fill of name + @param value Buffer to build the value string + @param value_size Maximum number of bytes in value + @param value_fill Holds the current buffer fill of value + @param flag Bitfield for control purposes - submit 0 for now + @return <0 error + 0 data not accepted, first fetch pending pairs with num_data == 0 + 1 name and value are not valid yet, submit more data + 2 name and value are valid, submit more data + 3 name and value are valid, pairs pending, fetch with num_data == 0 + 4 name and value are valid, no more data expected + 5 name and value are not valid, no more data expected + +*/ +int aaip_decode_pair(struct aaip_state *aaip, + unsigned char *data, size_t num_data, size_t *consumed, + char *name, size_t name_size, size_t *name_fill, + char *value, size_t value_size, size_t *value_fill, + int flag); + + +/* Inquire the number of pairs which were skipped because being oversized. + @param aaip The AAIP decoder context + @param flag Bitfield for control purposes - submit 0 for now + @return The number of pairs skipped since aaip_init() +*/ +unsigned int aaip_get_pairs_skipped(struct aaip_state *aaip, int flag); + + +/* ------------------------- List Level Interface ------------------------ */ +/* + Provides support for names and values of limited size. The limits are + given for total memory consumption and for number of attributes. + + Iterated decoding is supported as long as no single attribute exceeds + the memory limit. +*/ + +/* Accept raw input data and collect arrays of name pointers, value lengths + and value pointers. A handle object will emerge which finally has to be + be freed by a call with bit 15. + @param handle The decoding context. + It will be created by this call with flag bit 0 or if + *handle == NULL. This handle has to be the same as long + as decoding goes on and finally has to be freed by a + call with bit15. + @param aa_name The Signature Word (advised is "AA") + @param memory_limit Maximum number of bytes to allocate + @param num_attr_limit Maximum number of name-value pairs to allocate + @param data The raw data to decode + @param num_data Number of data bytes provided + @param consumed Returns the number of consumed data bytes + @param flag Bitfield for control purposes + bit0= this is the first call for a file object + bit15= end decoding : + Free handle and its intermediate list memory. + @return <=0 error + 1 not complete yet, submit more data + 2 arrays are complete, call aaip_get_decoded_attrs() + 3 limit exceeded, not complete yet, call with bit15 and give up + 4 limit exceeded, call aaip_get_decoded_attrs() and try again +*/ +int aaip_decode_attrs(struct aaip_state **handle, char aa_name[2], + size_t memory_limit, size_t num_attr_limit, + unsigned char *data, size_t num_data, size_t *consumed, + int flag); + + +/* Obtain the resulting attributes when aaip_decode_attrs() indicates to + be done or to have the maximum possible amount of result ready. + The returned data objects get detached from handle making it ready for + the next round of decoding with possibly a different input source. The + returned data objects finally have to be freed by a call with flag bit 15. + @param handle The decoding context created by aaip_decode_attrs() + @param num_attrs Will return the number of name-value pairs + @param names Will return an array of pointers to 0-terminated names + @param value_lengths Will return an arry with the lenghts of values + @param values Will return an array of pointers to 8-bit values + @param flag Bitfield for control purposes + bit15= free memory of names, value_lengths, values +*/ +int aaip_get_decoded_attrs(struct aaip_state **handle, size_t *num_attrs, + char ***names, size_t **value_lengths, char ***values, + int flag); + + +/* ------ ACL representation ------ */ + +/* Convert an AAIP 0.2 ACL attribute value into the long text form of ACL. + @param data The raw data to decode + @param num_data Number of data bytes provided + @param consumed Returns the number of consumed data bytes + @param acl_text Will be filled with ACL long text form + @param acl_text_size Maximum number of bytes to be written to acl_text + @param acl_text_fill Will return the number of bytes in acl_text + @param flag Bitfield for control purposes + bit0= count only, do not really produce bytes: + acl_text will not be touched, + acl_text_size will be ignored, + *acl_text_fill will return the counted number + bit1= expected is a default ACL (see return value 2) + @return 1 success + 2 success, begin of default/access ACL encountered, + submit data + *consumed for access/default ACL + -1 error with reading of qualifier + -2 error with writing of ACL text line + -3 version mismatch + -4 unknown tag type encountered +*/ +int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed, + char *acl_text, size_t acl_text_size, + size_t *acl_text_fill, int flag); + + +/* ------ OS interface ------ */ + +/* Set the ACL of the given file to a given list in long text form. + @param path Path to the file + @param text The input text (0 terminated, ACL long text form) + @param flag Bitfield for control purposes + bit0= set default ACL rather than access ACL + @return > 0 ok + -1 failure of system ACL service (see errno) +*/ +int aaip_set_acl_text(char *path, char *text, int flag); + + +/* Bring the given attributes and/or ACLs into effect with the given file. + @param path Path to the file + @param num_attrs Number of attributes + @param names Array of pointers to 0 terminated name strings + @param value_lengths Array of byte lengths for each attribute payload + @param values Array of pointers to the attribute payload bytes + @param flag Bitfield for control purposes + bit0= decode and set ACLs + bit1= first clear all existing attributes of the file + bit2= do not set attributes other than ACLs + bit3= do not ignore eventual ACL attribute + (e.g. system.posix_acl_access) + @return 1 success + -1 error memory allocation + -2 error with decoding of ACL + -3 error with setting ACL + -4 error with setting attribute + -5 error with deleting attributes + +*/ +int aaip_set_attr_list(char *path, size_t num_attrs, char **names, + size_t *value_lengths, char **values, int flag); + +#endif /* ! Aaip_h_is_includeD */ + diff --git a/libisoburn/branches/ZeroThreeTwo/test/aaip_0_2_test.c b/libisoburn/branches/ZeroThreeTwo/test/aaip_0_2_test.c new file mode 100644 index 00000000..bb708760 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/test/aaip_0_2_test.c @@ -0,0 +1,443 @@ + +/* + + Arbitrary Attribute Interchange Protocol , AAIP version 0.2 + Demonstration program for encoding and decoding EA and ACL. + + See http://libburnia-project.org/wiki/AAIP + + test/aaip_0_2_test.c - Main program for test binary + + Compile: + cc -g -Wall -o test/aaip test/aaip_0_2.c test/aaip_0_2_test.c -lacl + + Usage: ./aaip name value + Long parameters ./aaip -name"x100" -value"x100" + + >>> ACLs + +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "aaip_0_2.h" + +#define Aaip_test_name_sizE 1024 +#define Aaip_test_value_sizE 1024 + + +static int print_result(unsigned char *result, size_t result_len, int flag) +{ + int i; + + printf( + " - - - - - - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - - 7 - - 8 - - 9\n"); + printf("\n"); + printf("%4u : ", 0); + for(i= 0; i < result_len; i++) { + if(result[i] >= 32 && result[i] <= 126) + printf("'%c' ", result[i]); + else + printf("%3u ", (unsigned int) ((unsigned char *) result)[i]); + if((i % 10) == 9) + printf("\n%4u : ", (unsigned int) (i + 1)); + } + printf("\n\n"); + printf( + " - - - - - - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - - 7 - - 8 - - 9\n"); + printf("\n"); + return(1); +} + + +static int print_attrs(size_t num_attrs, char **names, size_t *value_lengths, + char **values, int flag) +{ + size_t i, j; + + for(i= 0; i < num_attrs; i++) { + printf("name='"); + for(j= 0; names[i][j] != 0; j++) { + if(names[i][j] >= 32 && names[i][j] <= 126 && + names[i][j] != '\\' && names[i][j] != '\'') + printf("%c", names[i][j]); + else + printf("\\%o", (unsigned int) ((unsigned char **) names)[i][j]); + } + printf("' (%d)\n", (int) j); + printf("value='"); + for(j= 0; j < value_lengths[i]; j++) { + if(values[i][j] >= 32 && values[i][j] <= 126 && + values[i][j] != '\\' && values[i][j] != '\'') + printf("%c", values[i][j]); + else + printf("\\%3.3o", (unsigned int) ((unsigned char **) values)[i][j]); + } + printf("' (%d)\n\n", (int) j); + } + return(1); +} + + +static int do_touch(char *path, int flag) +{ + FILE *fp; + + fp= fopen(path, "a"); + if(fp == NULL) { + fprintf(stderr, "fopen(\"%s\") failed: %d %s\n", + path, errno, errno != 0 ? strerror(errno) : ""); + return(0); + } + fclose(fp); + return(1); +} + + +static int decode_acl(unsigned char *result, size_t result_len, + char *out_path, int flag) +{ + int ret; + size_t consumed, text_fill; + char *text= NULL; + + ret= aaip_decode_acl(result, result_len, &consumed, NULL, 0, &text_fill, 1); + if(ret <= 0) { + fprintf(stderr, "aaip_decode_acl(,1) failed: ret= %d\n", ret); + ret= 0; goto ex; + } + text= calloc(text_fill, 1); + ret= aaip_decode_acl(result, result_len, &consumed, text, text_fill, + &text_fill, 0); + if(ret <= 0) { + fprintf(stderr, "aaip_decode_acl(,0) failed: ret= %d\n", ret); + ret= 0; goto ex; + } + printf("--- ret= %d , text=\n%s--- end of text\n\n", ret, text); + + if(out_path == NULL) + {ret= 1; goto ex;} + + ret= do_touch(out_path, 0); + if(ret <= 0) + goto ex; + + ret= aaip_set_acl_text(out_path, text, 0); + if(ret <= 0) { + fprintf(stderr, "aaip_set_acl_text() failed"); + if(ret == -1) + fprintf(stderr, ": %d %s\n", errno, errno != 0 ? strerror(errno) : ""); + else + fprintf(stderr, "\n"); + ret= 0; goto ex; + } + ret= 1; +ex: + if(text != NULL) + free(text); + return(ret); +} + + +static int test_acl(char *in_path, char *out_path, int flag) +{ + int ret; + char *acl_text= NULL; + unsigned char *result= NULL; + size_t result_len; + + ret= aaip_get_acl_text(in_path, &acl_text, 0); + if(ret <= 0) { + fprintf(stderr, "aaip_get_acl_text() failed"); + if(ret == -1) + fprintf(stderr, ": %d %s\n", errno, errno != 0 ? strerror(errno) : ""); + else + fprintf(stderr, "\n"); + ret= 6; goto ex; + } + printf("--- ACL:\n%s--- end of ACL\n\n", acl_text); + + ret= aaip_encode_acl(acl_text, &result_len, &result, 0); + if(ret <= 0) { + fprintf(stderr, "aaip_encode_acl(text) failed: ret= %d\n", ret); + ret= 7; goto ex; + } + print_result(result, result_len, 0); + ret= decode_acl(result, result_len, out_path, 0); + if(ret <= 0) + {ret= 8; goto ex;} + free(result); result= NULL; + + ret= aaip_encode_acl(acl_text, &result_len, &result, 2); + if(ret <= 0) { + fprintf(stderr, "aaip_encode_acl(num) failed: ret= %d\n", ret); + ret= 9; goto ex; + } + print_result(result, result_len, 0); + ret= decode_acl(result, result_len, out_path, 0); + if(ret <= 0) + {ret= 10; goto ex;} + + ret= 0; +ex:; + aaip_get_acl_text("", &acl_text, 1 << 15); + if(result != NULL) + free(result); + return(ret); +} + + +int synthetic_pairs(char *prog, int argc, char **argv, int flag) +{ + int ret, l, mult= 0, k; + size_t result_len, i; + unsigned char *result= NULL; + char **names= NULL, **values= NULL, *cpt, **param; + size_t *value_lengths= NULL; + + struct aaip_state *aaip; + size_t consumed= 0; + char name[Aaip_test_name_sizE + 1]; + size_t name_fill; + char value[Aaip_test_value_sizE + 1]; + size_t value_fill; + size_t todo; + int submit_data, is_done; + unsigned char *rpt; + unsigned int skipped, was_skipped= 0; + + aaip= (struct aaip_state *) calloc(aaip_sizeof_aaip_state(), 1); + names= calloc(sizeof(char *), argc / 2); + values= calloc(sizeof(char *), argc / 2); + value_lengths= calloc(sizeof(size_t), argc / 2); + + for(i= 0; i < argc; i++) { + if(i % 2) + param= values + i / 2; + else + param= names + i / 2; + (*param)= argv[i]; + if(argv[i][0] == '-') { + cpt= strchr(argv[i], 'x'); + if(cpt != NULL) { + l= cpt - argv[i] - 1; + if(l > 0) + sscanf(cpt + 1, "%d", &mult); + if(l > 0 && mult > 0) { + (*param)= calloc(1, l * mult + 1); + if((*param) != NULL) { + for(k= 0; k < mult; k++) + memcpy((*param) + k * l, argv[i] + 1, l); + (*param)[mult * l]= 0; + } else + (*param)= argv[i]; + } + } + } + if(i % 2) + value_lengths[i / 2]= strlen(values[i / 2]); + } + + ret= aaip_encode("AA", (unsigned int) (argc / 2), names, + value_lengths, values, + &result_len, &result, 0); + if(ret <= 0) { + fprintf(stderr, "%s : aaip_encode failed with ret= %d\n", prog, ret); + return(2); + } + print_result(result, result_len, 0); + + aaip_init_aaip_state(aaip, "AA", 0); + rpt= result; + submit_data= 1; + is_done= 0; + while(!is_done) { + if(submit_data) { + todo= result_len - (rpt - result); + if(todo > 2048) + todo= 2048; + if(todo == 0) { + fprintf(stderr, "%s : Out of data while still prompted to submit\n", + prog); + return(5); + } + } else + todo= 0; + ret= aaip_decode_pair(aaip, rpt, todo, &consumed, + name, Aaip_test_name_sizE, &name_fill, + value, Aaip_test_value_sizE, &value_fill, 0); + skipped= aaip_get_pairs_skipped(aaip, 0); + if(skipped > was_skipped) { + printf("- skipped %d pair%s -\n\n", skipped - was_skipped, + skipped - was_skipped > 1 ? "s" : ""); + was_skipped= skipped; + } + if(ret < 0) { + fprintf(stderr, "%s : aaip_decode_pair failed with ret= %d\n", prog, ret); + return(3); + } + rpt+= todo; + if(ret == 0) { + rpt-= todo; + submit_data= 0; + continue; + } else if(ret == 1) { + submit_data= 1; + continue; + } else if(ret == 2) { + submit_data= 1; + } else if(ret == 3) { + submit_data= 0; + } else if(ret == 4) { + is_done= 1; + } else if(ret == 5) { + is_done= 1; + break; + } else { + fprintf(stderr, "%s : Unknown return %d from aaip_decode_pair()\n", + prog, ret); + return(4); + } + name[name_fill]= 0; + value[value_fill]= 0; + if((name_fill < 1000 && value_fill < 1000)) { + printf("name = '%s' (%lu)\n", name, (unsigned long) name_fill); + printf("value= '%s' (%lu)\n", value, (unsigned long) value_fill); + } else { + printf("name = (%lu)\n", (unsigned long) name_fill); + printf("value= (%lu)\n", (unsigned long) value_fill); + } + printf("\n"); + } + + return(0); +} + + +/* + @param flag bit0= use numeric qualifiers +*/ +static int copy_all(char *in_path, char *out_path, int flag) +{ + int ret; + struct aaip_state *aaip= NULL; + size_t in_num_attrs, *in_value_lengths= NULL; + char **in_names= NULL, **in_values= NULL; + int is_done= 0, first_round= 1; + unsigned char *result= NULL, *rpt; + size_t result_len, todo, consumed; + size_t out_num_attrs, *out_value_lengths= NULL; + char **out_names= NULL, **out_values= NULL; + + ret= aaip_get_attr_list(in_path, &in_num_attrs, &in_names, &in_value_lengths, + &in_values, 1 | ((flag & 1) << 1)); + if(ret <= 0) + {ret= 11; goto ex;} + print_attrs(in_num_attrs, in_names, in_value_lengths, in_values, 0); + + ret= aaip_encode("AA", (unsigned int) in_num_attrs, in_names, + in_value_lengths, in_values, &result_len, &result, 0); + if(ret == 0) + {ret= 12; goto ex;} + + if(result_len <= 0) { + fprintf(stderr, "No result\n"); + ret= 13; goto ex; + } + print_result(result, result_len, 0); + + rpt= result; + while(!is_done) { + todo= result_len - (rpt - result); + if(todo > 2048) + todo= 2048; + if(todo == 0) { + fprintf(stderr, "Out of data while still prompted to submit\n"); + ret= 14; goto ex; + } + /* Allow 1 million bytes of memory consumption, 100,000 attributes */ + ret= aaip_decode_attrs(&aaip, "AA", (size_t) 1000000, (size_t) 100000, + rpt, todo, &consumed, first_round); + rpt+= consumed; + first_round= 0; + if(ret == 1) + continue; + if(ret == 2) + break; + fprintf(stderr, "aaip_decode_attrs() returns %d\n", ret); + ret= 15; goto ex; + } + if(rpt - result != result_len) { + fprintf(stderr, "aaip_decode_attrs() returns 2 but %d bytes are left\n", + (int) (result_len - (rpt - result))); + ret= 16; goto ex; + } + ret= aaip_get_decoded_attrs(&aaip, &out_num_attrs, &out_names, + &out_value_lengths, &out_values, 0); + + if(ret != 1) { + fprintf(stderr, "aaip_get_decoded_attrs() returns %d\n", ret); + ret= 17; goto ex; + } + print_attrs(out_num_attrs, out_names, out_value_lengths, out_values, 0); + + ret= do_touch(out_path, 0); + if(ret <= 0) + {ret= 19; goto ex;} + + ret= aaip_set_attr_list(out_path, out_num_attrs, out_names, out_value_lengths, + out_values, 1 | 2); + if(ret != 1) { + fprintf(stderr, "aaip_set_attr_list() returns %d\n", ret); + ret= 18; goto ex; + } + ret= 0; +ex:; + if(in_names != NULL || in_value_lengths != NULL || in_values != NULL) + aaip_get_attr_list(in_path, &in_num_attrs, &in_names, &in_value_lengths, + &in_values, 1 << 15); + if(out_names != NULL || out_value_lengths != NULL || out_values != NULL) + aaip_get_decoded_attrs(&aaip, &out_num_attrs, &out_names, + &out_value_lengths, &out_values, 15); + aaip_decode_attrs(&aaip, "AA", (size_t) 0, (size_t) 0, NULL, (size_t) 0, + &consumed, 1 << 15); + return(ret); +} + + +int main(int argc, char **argv) +{ + int ret; + + if(argc < 2) { +usage: + fprintf(stderr, "usage : %s options\n", argv[0]); + fprintf(stderr, " -pairs [-]name[xNNN] [-]value[xNNN] [...]\n"); + fprintf(stderr, " -copy_acl source_path target_path\n"); + fprintf(stderr, " -copy source_path target_path\n"); + exit(1); + } + if(strcmp(argv[1], "-pairs") == 0) { + if(argc < 4 || (argc % 2) != 0) + goto usage; + ret= synthetic_pairs(argv[0], argc - 2, argv + 2, 0); + } else if(strcmp(argv[1], "-copy_acl") == 0) { + if(argc != 4) + goto usage; + ret= test_acl(argv[2], argv[3], 0); + } else if(strcmp(argv[1], "-copy") == 0) { + if(argc != 4) + goto usage; + ret= copy_all(argv[2], argv[3], 1); + } else + goto usage; + exit(ret); +} diff --git a/libisoburn/branches/ZeroThreeTwo/test/compare_file.c b/libisoburn/branches/ZeroThreeTwo/test/compare_file.c new file mode 100644 index 00000000..2d460f54 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/test/compare_file.c @@ -0,0 +1,275 @@ +/* + Compare two copies of a file object in as many aspects as i can imagine + to make sense. (E.g.: comparing atime makes no sense.) + + To compare tree /media/dvd and /original/dir : + find /media/dvd -exec compare_file '{}' /media/dvd /original/dir ';' + + Copyright 2008 Thomas Schmitt, + + Provided under GPL version 2. + + + cc -g -o compare_file compare_file.c +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* @param flag bit0= single letters */ +char *Ftypetxt(mode_t st_mode, int flag) +{ + if(flag&1) + goto single_letters; + if(S_ISDIR(st_mode)) + return("directory"); + else if(S_ISREG(st_mode)) + return("regular_file"); + else if(S_ISLNK(st_mode)) + return("symbolic_link"); + else if(S_ISBLK(st_mode)) + return("block_device"); + else if(S_ISCHR(st_mode)) + return("char_device"); + else if(S_ISFIFO(st_mode)) + return("name_pipe"); + else if(S_ISSOCK(st_mode)) + return("unix_socket"); + return("unknown"); +single_letters:; + if(S_ISDIR(st_mode)) + return("d"); + else if(S_ISREG(st_mode)) + return("-"); + else if(S_ISLNK(st_mode)) + return("l"); + else if(S_ISBLK(st_mode)) + return("b"); + else if(S_ISCHR(st_mode)) + return("c"); + else if(S_ISFIFO(st_mode)) + return("p"); + else if(S_ISSOCK(st_mode)) + return("s"); + return("?"); +} + + +char *Ftimetxt(time_t t, char timetext[40], int flag) +{ + char *rpt; + struct tm tms, *tmpt; + static char months[12][4]= { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + + tmpt= localtime_r(&t, &tms); + rpt= timetext; + rpt[0]= 0; + if(tmpt==0) + sprintf(rpt+strlen(rpt), "%12.f", (double) t); + else if(time(NULL)-t < 180*86400 && time(NULL)-t >= 0) + sprintf(rpt+strlen(rpt), "%3s %2d %2.2d:%2.2d", + months[tms.tm_mon], tms.tm_mday, tms.tm_hour, tms.tm_min); + else + sprintf(rpt+strlen(rpt), "%3s %2d %4.4d", + months[tms.tm_mon], tms.tm_mday, 1900+tms.tm_year); + return(timetext); +} + + +/* @param flag bit0= compare atime + bit1= compare ctime +*/ +int Compare_2_files(char *adr1, char *adr2, char *adrc, int flag) +{ + struct stat s1, s2; + int ret, differs= 0, r1, r2, fd1= -1, fd2= -1, i, done; + char buf1[4096], buf2[4096], a[4096], ttx1[40], ttx2[40]; + off_t r1count= 0, r2count= 0, diffcount= 0, first_diff= -1; + + ret= lstat(adr1, &s1); + if(ret==-1) { + printf("? %s : cannot lstat() : %s\n", adr1, strerror(errno)); + return(0); + } + strcpy(a, Ftypetxt(s1.st_mode, 1)); + strcat(a, " "); + if(adrc[0]) + strcat(a, adrc); + else + strcat(a, "."); + + ret= lstat(adr2, &s2); + if(ret==-1) { + printf("? %s : cannot lstat() : %s\n", adr2, strerror(errno)); + return(0); + } + + /* Attributes */ + if(s1.st_mode != s2.st_mode) { + if((s1.st_mode&~S_IFMT)!=(s2.st_mode&~S_IFMT)) + printf("%s : st_mode : %7.7o <> %7.7o\n", a, s1.st_mode, s2.st_mode); + if((s1.st_mode&S_IFMT)!=(s2.st_mode&S_IFMT)) + printf("%s : type : %s <> %s\n", + a, Ftypetxt(s1.st_mode, 0), Ftypetxt(s2.st_mode, 0)); + differs= 1; + } + if(s1.st_uid != s2.st_uid) { + printf("%s : st_uid : %d <> %d\n", a, s1.st_uid, s2.st_uid); + differs= 1; + } + if(s1.st_gid != s2.st_gid) { + printf("%s : st_gid : %d <> %d\n", a, s1.st_gid, s2.st_gid); + differs= 1; + } + if((S_ISCHR(s1.st_mode) && S_ISCHR(s2.st_mode)) || + (S_ISBLK(s1.st_mode) && S_ISBLK(s2.st_mode))) { + if(s1.st_rdev != s2.st_rdev) { + printf("%s : %s st_rdev : %lu <> %lu\n", a, + (S_ISCHR(s1.st_mode) ? "S_IFCHR" : "S_IFBLK"), + (unsigned long) s1.st_rdev, (unsigned long) s1.st_rdev); + differs= 1; + } + } + if(S_ISREG(s2.st_mode) && s1.st_size != s2.st_size) { + printf("%s : st_size : %.f <> %.f diff= %.f\n", + a, (double) s1.st_size, (double) s2.st_size, + ((double) s1.st_size) - (double) s2.st_size); + differs= 1; + } + if(s1.st_mtime != s2.st_mtime) { + printf("%s : st_mtime : %s <> %s diff= %.f s\n", + a, Ftimetxt(s1.st_mtime, ttx1, 0), + Ftimetxt(s2.st_mtime, ttx2, 0), + ((double) s1.st_mtime) - (double) s2.st_mtime); + differs= 1; + } + if(flag&1) { + if(s1.st_atime != s2.st_atime) { + printf("%s : st_atime : %s <> %s diff= %.f s\n", + a, Ftimetxt(s1.st_atime, ttx1, 0), + Ftimetxt(s2.st_atime, ttx2, 0), + ((double) s1.st_atime) - (double) s2.st_atime); + differs= 1; + } + } + if(flag&2) { + if(s1.st_ctime != s2.st_ctime) { + printf("%s : st_ctime : %s <> %s diff= %.f s\n", + a, Ftimetxt(s1.st_ctime, ttx1, 0), + Ftimetxt(s2.st_ctime, ttx2, 0), + ((double) s1.st_ctime) - (double) s2.st_ctime); + differs= 1; + } + } + if(S_ISREG(s1.st_mode) && S_ISREG(s2.st_mode)) { + fd1= open(adr1, O_RDONLY); + if(fd1==-1) { + printf("- %s : cannot open() : %s\n", adr1, strerror(errno)); + return(0); + } + fd2= open(adr2, O_RDONLY); + if(fd2==-1) { + printf("- %s : cannot open() : %s\n", adr2, strerror(errno)); + close(fd1); + return(0); + } + + /* Content */ + done= 0; + while(!done) { + r1= read(fd1, buf1, sizeof(buf1)); + r2= read(fd2, buf2, sizeof(buf2)); + if((r1==EOF && r2==EOF) || (r1==0 && r2==0)) + break; + if(r1==EOF || r1==0) { + if(r1==EOF) + r1= 0; + if(s1.st_size > r1count + r1) + printf("- %s : early EOF after %.f bytes\n", adr1, (double) r1count); + differs= 1; + } + r1count+= r1; + if(r2==EOF || r2 r2count + r2) + printf("- %s : early EOF after %.f bytes\n", adr2, (double) r2count); + differs= 1; + done= 1; + } + if(r2>r1) { + if(s1.st_size > r1count + r1) + printf("- %s : early EOF after %.f bytes\n", adr1, (double) r1count); + differs= 1; + done= 1; + } + r2count+= r2; + if(r1>r2) + r1= r2; + for(i= 0; i0 || r1count!=r2count) { + if(first_diff<0) + first_diff= (r1count>r2count ? r2count : r1count); + printf("%s : %s : differs by at least %.f bytes. First at %.f\n", a, + (s1.st_mtime==s2.st_mtime ? "CONTENT":"content"), + (double) (diffcount + abs(r1count-r2count)), (double) first_diff); + differs= 1; + } + } + if(fd1!=-1) + close(fd1); + if(fd2!=-1) + close(fd2); + return(!differs); +} + + +int main(int argc, char **argv) +{ + int ret, i, with_ctime= 1; + char adr1[4096], adr2[4096], adrc[4096]; + + if(argc<4) { + fprintf(stderr, "usage: %s path prefix1 prefix2\n", argv[0]); + exit(2); + } + for(i= 4; i + and Thomas Schmitt +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include "../src/libisoburn.h" + +const char * const optstring = "JRh"; +extern char *optarg; +extern int optind; + + +/** Activates the usage of function graft_point() rather than + plain iso_tree_radd_dir() from libisofs +*/ +#define With_graft_poinT 1 + + +static int graft_point(struct iso_volume *volume, const char *disk_path, + const char *img_path, struct iso_tree_radd_dir_behavior *behav) +{ + char path[4096], *apt, *npt; + struct iso_tree_node_dir *dir; + struct iso_tree_node *node; + int done= 0, is_dir= 0; + struct stat stbuf; + + strncpy(path, img_path, sizeof(path)-1); + path[sizeof(path)-1]= 0; + apt= npt= path; + + if(lstat(disk_path, &stbuf) == -1) { + fprintf(stderr, "Cannot determine attributes of '%s' : %s (%d)\n", + disk_path, (errno > 0 ? strerror(errno) : "unknown error"), errno); + return(0); + } + if(S_ISDIR(stbuf.st_mode)) + is_dir= 1; + else if(!(S_ISREG(stbuf.st_mode) || S_ISLNK(stbuf.st_mode))) { + fprintf(stderr, "File object '%s' is of non-supported file type\n", + disk_path); + return(0); + } + + dir= iso_volume_get_root(volume); + if(dir==NULL) { + fprintf(stderr, "While grafting '%s' : no root node available\n", img_path); + return(0); + } + for(npt= apt; !done; apt= npt+1) { + npt= strchr(apt, '/'); + if(npt==NULL) { + npt= apt+strlen(apt); + done= 1; + } else + *npt= 0; + if(*apt==0) { + *apt= '/'; + apt++; + continue; + } + node= iso_tree_volume_path_to_node(volume,path); + if(node!=NULL) { + if(iso_tree_node_get_type(node)!=LIBISO_NODE_DIR) { + fprintf(stderr, "While grafting '%s' : '%s' is not a directory\n", + img_path, path); + return(0); + } + dir= (struct iso_tree_node_dir *) node; + } else { + dir= iso_tree_add_dir(dir, apt); + if(dir==NULL) { + fprintf(stderr, "While grafting '%s' : could not insert '%s'\n", + img_path, path); + return(0); + } + } + if(done) { + if(is_dir) { + iso_tree_radd_dir(dir, disk_path, behav); + } else { + node= iso_tree_add_node(dir, disk_path); + if(node == NULL) { + fprintf(stderr, "While grafting '%s'='%s' : libisofs_errno = %d\n", + img_path, disk_path, libisofs_errno); + } + } + } else + *npt= '/'; + } + fprintf(stderr, "NOTE: added %s '%s'='%s'\n", (is_dir ? "directory" : "node"), + img_path, disk_path); + return(1); +} + + +static +void usage() +{ + printf("test [OPTIONS] DRIVE DIRECTORY\n"); +} + +static +void help() +{ + printf( +"Options:\n" +" -J Add Joliet support\n" +" -R Add Rock Ridge support\n" +" -h Print this message\n" +); +} + +int main(int argc, char **argv) +{ + struct burn_drive_info *drives; + struct iso_volset *volset; + struct burn_drive *drive; + struct burn_disc *disc; + enum burn_disc_status state; + struct isoburn_read_opts ropts; + struct isoburn_source_opts sopts; + int c; + struct iso_tree_radd_dir_behavior behav = {0,0,0}; + int flags=0; + int ret=0, i; + int size, free_bytes; + char *status_text; + + while ((c = getopt(argc, argv, optstring)) != -1) { + switch(c) { + case 'h': + usage(); + help(); + exit(0); + break; + case 'J': + flags |= ECMA119_JOLIET; + break; + case 'R': + flags |= ECMA119_ROCKRIDGE; + break; + case '?': + usage(); + exit(1); + break; + } + } + + if (argc < optind + 1) { + fprintf(stderr, "Please supply device name\n"); + usage(); + exit(1); + } + if (argc < optind + 2) { + fprintf(stderr, "Please supply directory to add to disc\n"); + usage(); + exit(1); + } + + + if (!isoburn_initialize()) { + fprintf(stderr, "Can't init libisoburn\n"); + exit(1); + } + + /* TODO change this. maybe we can add wrapp in libisoburn */ + iso_msgs_set_severities("NEVER", "DEBUG", "libisofs : "); + burn_msgs_set_severities("NEVER", "DEBUG", "libburn : "); + burn_set_signal_handling("libisoburn/test/test : ", NULL, 0); + + printf("Growing drive %s\n", argv[optind]); + + if (isoburn_drive_scan_and_grab(&drives, argv[optind], 1) <= 0) { + fprintf(stderr, + "Can't open device. Are you sure it is a valid drive?\n"); + exit(1); + } + drive = drives[0].drive; + + /* check for invalid state */ + state = isoburn_disc_get_status(drive); + if (state != BURN_DISC_BLANK && state != BURN_DISC_APPENDABLE) { + fprintf(stderr, "Unsuitable disc status\n"); + goto exit_cleanup; + } + + /* fill read opts */ + memset(&ropts, sizeof(ropts), 0); + ropts.norock = 0; + ropts.nojoliet = 0; + ropts.preferjoliet = 0; + ropts.uid = 0; + ropts.gid = 0; + ropts.mode = 0555; + ropts.pretend_blank= 0; + + if (isoburn_read_volset(drive, &ropts, &volset) <= 0) { + fprintf(stderr, "Can't read volset\n"); + goto exit_cleanup; + } + + +#ifdef With_graft_poinT + for (i = optind + 1; i < argc; i++) { + if (graft_point(iso_volset_get_volume(volset, 0), + argv[i], argv[i], &behav) <= 0) { + fprintf(stderr, "Canot graft '%s'\n", argv[optind+1]); + goto exit_cleanup; + } + } + +#else + struct iso_tree_node_dir *root; + root = iso_volume_get_root(iso_volset_get_volume(volset, 0)); + /* add a new dir */ + iso_tree_radd_dir(root, argv[optind+1], &behav); +#endif /* ! With_graft_poinT */ + + + sopts.level = 2; + sopts.flags = flags; + sopts.relaxed_constraints = 0; + sopts.copy_eltorito = 1; + sopts.no_cache_inodes = 0; + sopts.sort_files = 1; + sopts.default_mode = 0; + sopts.replace_dir_mode = 0; + sopts.replace_file_mode = 0; + sopts.replace_uid = 0; + sopts.replace_gid = 0; + sopts.dir_mode = 0555; + sopts.file_mode = 0444; + sopts.gid = 0; + sopts.uid = 0; + sopts.input_charset = NULL; + sopts.ouput_charset = NULL; + + if (isoburn_prepare_disc(drive, &disc, &sopts) <= 0) { + fprintf(stderr, "Can't prepare disc\n"); + goto volset_cleanup; + } + + /* a. write the new image */ + printf("Adding new data...\n"); + { + struct burn_write_opts *burn_options; + struct burn_progress progress; + + burn_options = burn_write_opts_new(drive); + burn_drive_set_speed(drive, 0, 0); + burn_write_opts_set_underrun_proof(burn_options, 1); + + /* ok, write the new track */ + isoburn_disc_write(burn_options, disc); + burn_write_opts_free(burn_options); + + while (burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING) + usleep(100002); + + while (burn_drive_get_status(drive, &progress) + != BURN_DRIVE_IDLE) { + + printf("Writing: sector %d of %d", + progress.sector, progress.sectors); + ret = isoburn_get_fifo_status(drive, &size, + &free_bytes, &status_text); + if (ret > 0 ) + printf(" [fifo %s, %2d%% fill]", status_text, + (int) (100.0 - 100.0 * + ((double) free_bytes) / + (double) size)); + printf("\n"); + sleep(1); + } + } + + /* b. write the new vol desc */ + printf("Writing the new vol desc...\n"); + if (isoburn_activate_session(drive) <= 0) { + fprintf(stderr, "Ups, new vol desc write failed\n"); + } + + ret= 0; +volset_cleanup:; +/* + iso_volset_free(volset); +*/ + +exit_cleanup:; + isoburn_drive_release(drive, 0); + isoburn_finish(); + + exit(ret); +} + diff --git a/libisoburn/branches/ZeroThreeTwo/version.h.in b/libisoburn/branches/ZeroThreeTwo/version.h.in new file mode 100644 index 00000000..cf529233 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/version.h.in @@ -0,0 +1,6 @@ + +/* <<< this file is on its way out +#define ISOBURN_MAJOR_VERSION @ISOBURN_MAJOR_VERSION@ +#define ISOBURN_MINOR_VERSION @ISOBURN_MINOR_VERSION@ +#define ISOBURN_MICRO_VERSION @ISOBURN_MICRO_VERSION@ +*/ diff --git a/libisoburn/branches/ZeroThreeTwo/xorriso/README b/libisoburn/branches/ZeroThreeTwo/xorriso/README new file mode 100644 index 00000000..25a55cfd --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/xorriso/README @@ -0,0 +1,241 @@ +------------------------------------------------------------------------------ + libburnia-project.org scdbackup.sourceforge.net/xorriso_eng.html +------------------------------------------------------------------------------ +xorriso. By Thomas Schmitt +Integrated sub project of libburnia-project.org but also published via: +http://scdbackup.sourceforge.net/xorriso_eng.html +http://scdbackup.sourceforge.net/xorriso-0.3.1.tar.gz +Copyright (C) 2006-2008 Thomas Schmitt, provided under GPL version 2. +------------------------------------------------------------------------------ + + +xorriso is a program which maps file objects from POSIX compliant +filesystems into Rock Ridge enhanced ISO 9660 filesystems and allows +session-wise manipulation of such filesystems. It can load the management +information of existing ISO images and it writes the session results to +optical media or to filesystem objects. +Vice versa xorriso is able to restore file objects from ISO 9660 filesystems. + +Currently it is supported on Linux with kernels >= 2.4 and on FreeBSD versions +with ATAPI/CAM support enabled in the kernel, see atapicam(4). + +A special property of xorriso is that it needs neither an external ISO 9660 +formatter program nor an external burn program for CD or DVD but rather +incorporates the libraries of libburnia-project.org . + +By using this software you agree to the disclaimer at the end of this text: +"... without even the implied warranty ..." + + + Compilation, First Glimpse, Installation + +The most simple way to get xorriso from source code is the xorriso standalone +tarball. + +Prerequisites: +The tarball contains anything that is needed except libc and libpthread. +libreadline and the readline-dev headers will make dialog mode more convenient, +but are not mandatory. + +Obtain xorriso-0.3.1.tar.gz, take it to a directory of your choice and do: + + tar xzf xorriso-0.3.1.tar.gz + cd xorriso-0.3.1 + +Within that directory execute: + + ./configure --prefix=/usr + make + +This will produce a binary named + ./xorriso/xorriso + +which you may strip to reduce it in size + strip ./xorriso/xorriso + +You may copy or move it to a directory where it can be found by the shell, +or you may execute xorriso at the place where it was built, +or you may execute as superuser: + make install + +For general concepts, options and usage examples see + man 1 xorriso + +This man page is part of the tarball as + xorriso/xorriso.1 +You may get a first glimpse by + man ./xorriso/xorriso.1 + +It gets installed with "make install" but may also be placed manually in the +./man1 directory below one of the directories mentioned in environment +variable $MANPATH. + +The installation creates several alias links pointing to the xorriso binary: + xorrisofs starts xorriso with -as mkisofs emulation already enabled + xorrecord starts xorriso with -as cdrecord emulation already enabled + osirrox starts with -osirrox image-to-disk copying already enabled + +If you want to avoid dependecy on libreadline although the libreadline +development package is installed, then rather build xorriso by: + ./configure --prefix=/usr --disable-libreadline + make clean ; make +Never omit the "make clean" command after switching libreadline enabling. + +If you want xorriso to report a "Build timestamp" with its option -version: + make buildstamped + + + Drives and Disk File Objects + +The user of xorriso needs rw-permission for the CD burner device. +A list of rw-accessible drives can be obtained by + + xorriso -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. + +The output of xorriso -devices might look like + +0 -dev '/dev/sr0' rwrw-- : 'TSSTcorp' 'CDDVDW SH-S203B' +1 -dev '/dev/hda' rwrw-- : 'HL-DT-ST' 'DVD-ROM GDR8162B' + +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. + +I strongly discourage to run xorriso with setuid root or via sudo ! +It is not checked for the necessary degree of hacker safety. + +Consider to put all authorized users into group "floppy", to chgrp the +device file to that group and to disallow w-access to others. + + +A possible source of problems are hald or other automounters. +If you can spot a process "hald-addon-storage" with the address of +your desired drive, then consider to kill it. + +If you cannot get rid of the automounter that easily, try whether it helps +to always load the drive tray manually before starting a write run of +xorriso. Wait until the drive light is off. +Better try to unmount an eventually mounted media before a write run. + + +Besides true optical drives, xorriso can also address disk files as input or +output drives. By default paths to files under /dev are accepted only if the +device represents a real optical drive. Other device files may be addressed +by prepending "stdio:" to the path. +Like: + xorriso -dev stdio:/dev/sdb ...more arguments... +This rule may be changed by xorriso option -drive_class. +Prefix "mmc:" causes a path to be accepted only if it is a real optical drive. + + + Testing + +We are quite sure that libisofs produces accurate representations of the disk +files. This opinion is founded on a lot of test burns and checks by a little +test program which compares files from the mounted image with the orignals +on disk. It uses the normal POSIX filesystem calls, i.e. no libburnia stuff. + +This program is not installed systemwide but stays in the installation +directory of the xorriso tarball as test/compare_file . Usually it is +run as -exec payload of a find command. It demands at least three arguments: +The path of the first file to compare, the prefix1 to be cut off from path +and the prefix2 which gets prepended afterwards to obtain the path of the +second file to compare. +As further argument there can be -no_ctime which suppresses the comparison +of ctime date stamps. +The exit value is 0 if no difference was detected, non-0 else. + +Example: After + xorriso ... -pathspecs on -add /=/original/dir -- -commit_eject all + mount /media/dvd + cd test +compare tree /media/dvd with tree /original/dir : + find /original/dir -exec ./compare_file '{}' /original/dir /media/dvd ';' \ + | less +and vice versa: + find /media/dvd -exec ./compare_file '{}' /media/dvd /original/dir ';' \ + | less + + + File Formats + +Currently there is only one file format peculiar to xorriso : sector maps +which describe the valid and invalid blocks on a media or a disk copy of +a media. xorriso creates and reads these file with its option -check_media. + +The file begins with 32 bytes of cleartext of which the last one is a +newline character. The first 25 say "xorriso sector bitmap v2 ", the +remaining six characters give the size of the info text as decimal number. +This number of bytes follows the first 32 and will not be interpreted +by xorriso. They are rather to inform a human reader about the media type +and its track layout. +After the info text there are two 4 byte signed integers, most significant +byte first. The first one, N, gives the number of bits in the following bitmap +and the second number S gives the number of 2 KiB blocks governed by a single +bit in the map. Then come the bits in form of 8-bit bytes. +Data block M is covered by bit B=M/S in the map, bit number B is stored in +byte B/8 as bit B%8. A valid readable data block has its bit set to 1. + + + libisoburn + +xorriso is based on libisofs which does ISO 9600 filesystem aspects and on +libburn which does the input and output aspects. Parts of this foundation +are accessed via libisoburn, which is closely related to xorriso. + +libisoburn provides two services: +- Encapsulation of coordination between libisofs and libburn. +- Emulation of ISO 9660 multi-session on overwriteable media + or random access files. + +The sourcecode of all three libraries is included in the xorriso standalone +tarball. It is compiled with xorriso and linked statically. +But you may as well get and install releases of libburn and libisofs, in order +to be able to install a release of libisoburn which produces libisoburn.so.1 +and a matching dynamically linked xorriso binary. +This binary is leaner but depends on properly installed libraries of suitable +revision. + +Dynamic library and compile time header requirements for libisoburn-0.3.1 : +- libburn.so.4 , version libburn-0.5.8 or higher +- libisofs.so.6 , version libisofs-0.6.12 or higher +libisoburn and xorriso will not start with libraries which are older than their +headers seen at compile time. So compile in the oldest possible installation +setup unless you have reason to enforce a newer bug fix level. + +Standalone xorriso has less runtime dependencies and can be moved more freely. + + +------------------------------------------------------------------------------ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +------------------------------------------------------------------------------ +Based on and sub project of: +libburnia-project.org +By Mario Danic , + Vreixo Formoso + Thomas Schmitt +Copyright (C) 2006-2008 Mario Danic, Vreixo Formoso, Thomas Schmitt. + +libburnia-project.org is inspired by and in other components still containing +parts of old +Libburn. By Derek Foreman and + Ben Jansens +Copyright (C) 2002-2006 Derek Foreman and Ben Jansens + diff --git a/libisoburn/branches/ZeroThreeTwo/xorriso/changelog.txt b/libisoburn/branches/ZeroThreeTwo/xorriso/changelog.txt new file mode 100644 index 00000000..ffd8df69 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/xorriso/changelog.txt @@ -0,0 +1,4563 @@ +------------------------------------------------------------------------------ + libburnia-project.org libisoburn , xorriso +------------------------------------------------------------------------------ + +------------------------------------------------------------------------------ + Changelog +------------------------------------------------------------------------------ + + +1 Sep 2007 [983] +libisoburn/libisoburn.h +libisoburn/isoburn.h +libisoburn/isoburn.c +libisoburn/burn_wrap.c +libisoburn/isofs_wrap.c +Initial content of libisoburn + +1 Sep 2007 [985] +libisoburn/libisoburn.h +libisoburn/isoburn.h +libisoburn/isoburn.c +libisoburn/isofs_wrap.c +Should have used copy+paste when writing Vreixos name + +5 Sep 2007 [990] +libisoburn/isoburn.h +libisoburn/isoburn.c +libisoburn/burn_wrap.c +Implemented use of stdio-pseudo-drives + +5 Sep 2007 [993] +libisoburn/libisoburn.h +libisoburn/isoburn.h +libisoburn/isoburn.c +libisoburn/burn_wrap.c +Changes in plans as discussed up to Sep 5 2007 + +5 Sep 2007 [994] +libisoburn/libisoburn.h +Updated explanations about the usage principles of libisoburn + +6 Sep 2007 [998] +libisoburn/libisoburn.h +libisoburn/isoburn.h +libisoburn/isoburn.c +libisoburn/burn_wrap.c +Updated to state of discussion + +9 Sep 2007 [1025] +libisoburn/burn_wrap.c +New wrapper isoburn_disc_erasable() declares ISO DVD-RAM, DVD+RW erasable + +10 Sep 2007 [1027] +libisoburn/libisoburn.h +New wrapper isoburn_disc_erasable() declares ISO DVD-RAM, DVD+RW erasable + +11 Sep 2007 [1029] +libisoburn/burn_wrap.c +libisoburn/isoburn.h +New inner function isoburn_set_start_byte() + +12 Sep 2007 [1031] +libisoburn/libisoburn.h +libisoburn/burn_wrap.c +Removed isoburn_write_opts_set_start_byte() + +13 Sep 2007 [1043] +libisoburn/burn_wrap.c +Took into respect fabricated_disc_status + +21 Sep 2007 [1092] +Makefile.am +Removed libburn file addresses + +22 Sep 2007 [1093] ++ doc/doxygen.conf.in +Added file demanded by build system + +22 Sep 2007 [1094] +src/burn_wrap.c +Prevented SIGSEGV in isoburn_drive_scan_and_grab() + +22 Sep 2007 [1095] +src/burn_wrap.c +Enabled treatment==2 in isoburn_drive_scan_and_grab() + +22 Sep 2007 [1099] +src/burn_wrap.c +Made use of burn_msgs_submit() for error messages + +23 Sep 2007 [1102] +src/burn_wrap.c +Removed all references to isoburn.treatment from burn_wrap.c + +23 Sep 2007 [1105] +src/burn_wrap.c +Called isoburn_create_data_source() and isoburn_free_data_source() + +28 Sep 2007 [1129] libisofs +libisofs/libiso_msgs.h +Removed apostrophes which my compiler does not like + +29 Sep 2007 [1133] +src/burn_wrap.c +Added optional code for a pseudo CD-RW to test the code for MMC multi-session + +29 Sep 2007 [1134] +src/burn_wrap.c +Released drive in case welcome_media fails + +1 Oct 2007 [1141] +src/burn_wrap.c +Allowed isoburn_disc_get_msc1() for closed media + +2 Oct 2007 [1149] +test/test.c +Function graft_point(),some general polishing, call of iso_volset_free disabled + +8 Oct 2007 [1169] +src/libisoburn.h +src/isoburn.h +src/isoburn.c +src/burn_wrap.c +Introduced fifo reference into isoburn object + +8 Oct 2007 [1170] +test/test.c +Several directories and files in one session, added display of fifo + +12 Oct 2007 [1171] ++ test/xorriso.h ++ test/xorriso.c ++ test/xorriso.txt +The stub of new application xorriso + +12 Oct 2007 [1172] ++ test/compile_xorriso.sh ++ test/make_timestamp.sh ++ test/xorriso_timestamp.h +A build facility to circumvent autotools during development + +12 Oct 2007 [1173] +test/xorriso.c +Introduced version and build timestamps, library headers + +13 Oct 2007 [1174] +test/xorriso.c ++ test/changelog.txt +Made -dialog and -options_from_file work + +2007.10.13.141503 [1175] +test/xorriso.c +Implemented -speed and enlarged -status list + +2007.10.13.152252 [1176] +test/xorriso.c +test/xorriso.txt +Implemented xorriso setter level of -fs, -gid, -uid + +2007.10.14.110003 [1177] +test/xorriso.c +Implemented setter level of -abort_on, fixed bugs about -f,-no_rc,startup files + +2007.10.14.122456 [1178] +test/xorriso.c ++ test/xorriso_private.h ++ test/xorrisoburn.h ++ test/xorrisoburn.c +Began to implement interface to our libraries + +2007.10.15.152705 [1183] +test/xorriso.h +test/xorriso.c +test/xorriso_private.h +test/xorrisoburn.h +test/xorrisoburn.c +Implemented -dev, -add, -commit + +2007.10.15.160303 [1184] +test/xorriso.c +Made -end give up drives + +2007.10.15.203554 [1185] +test/xorriso.c +Some safety precautions against malicious input, enabled -cdx, -cdi for -add + +2007.10.15.203714 [1186] +test/xorrisoburn.c +Corrected image path bug with -add of regular files, and -add /=/some/dir + +2007.10.15.224005 [1187] +test/xorriso.c +test/xorrisoburn.c +Implemented -rollback + +2007.10.16.210911 [1188] +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +Worked on failure severities, message system, program abort decision + +2007.10.17.130041 [1190] [1191 +test/xorriso.h +test/xorriso_private.h +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +Worked on failure severities, message system, program abort decision + +2007.10.17.130311 [1192] +src/isofs_wrap.c +Told burn_read_data() to stay silent on non-existent drive or read error + +2007.10.17.150142 [1193] +test/xorriso.c +test/xorrisoburn.c +Reinstated the distinction of message sources, respected '#' in dialog + +2007.10.17.165352 [1194] +test/xorriso.c +Prepended a "-" to any input line if missing + +2007.10.17.183024 [1195] +test/xorriso_private.h +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +Implemented core of option -toc + +2007.10.17.200241 [1196] +test/xorrisoburn.c +Continued work with -toc + +2007.10.17.213852 [1197] +test/compile_xorriso.sh +Forgot to make off_t 64 bit + +2007.10.17.214228 [1198] +src/libisoburn.h +src/burn_wrap.c +test/xorrisoburn.c +Rounding up fabricated nwa to full 32k addresses, API call for exact image size + +2007.10.17.215809 [1199] +test/xorriso.c +Activated -ban_stdio_write + +2007.10.17.224924 [1200] +test/xorrisoburn.c +Fixed obvious bug with -J. (Still wondering wether it works) + +2007.10.17.225039 [1201] +test/xorriso.c +Fixed bug with -speed. + +2007.10.17.225837 [1202] +test/xorriso.c +Fixed bug with -prompt. Fixed bug with # comments. (of rev 1194) + +18 Oct 2007 [1203] +test/changelog.txt +Updated changelog and todo list + +2007.10.18.144841 [1205] +src/isofs_wrap.c +test/xorrisoburn.c +isoburn_read_volset() now hands out an official volset reference + +2007.10.18.171415 [1206] +test/xorriso.c +test/xorriso.txt +test/xorrisoburn.h +test/xorrisoburn.c +Implemented option -devices + +2007.10.18.183200 [1207] +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +Implemented option -tell_media_space + +2007.10.18.185731 [1208] +test/xorriso_private.h +test/xorriso.c +test/xorrisoburn.c +Fixed a SIGSEGV with xorriso -version run + +2007.10.18.221756 [1211] +test/xorrisoburn.c +src/libisoburn.h +Took care of disposal of burn_disc ovbject + +18 Oct 2007 [1212] +test/test.c +Silenced compile warning + +2007.10.18.225654 [1213] +src/isofs_wrap.c +test/xorriso.c +test/xorrisoburn.c +Fixed a SIGSEGV with empty drive + +2007.10.19.140031 [1218] +test/xorrisoburn.c +Made reports with -add normal infos (formerly NOTE events) + +2007.10.19.151339 [1219] +test/xorriso.c +test/xorrisoburn.c +test/xorriso.txt +Implemented -print-size + +2007.10.19.164957 [1220] +test/xorriso_private.h +test/xorriso.c +test/xorriso.h +test/xorrisoburn.c +test/xorriso.txt +Implemented verbosity control by option -report_about + +2007.10.19.173547 [1221] +test/xorriso.c +test/xorrisoburn.c +test/xorriso.txt +Implemented option -eject + +2007.10.19.204155 [1222] +test/xorriso_private.h +test/xorriso.h +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +Implemented option -blank + +2007.10.20.170731 [1223] +src/burn_wrap.c +Directed write mode failure message to libburn queue, repaired wrote_well + +2007.10.20.171046 [1224] +test/xorrisoburn.c +test/xorriso_private.h +test/xorriso.c +Implemented options -format and -blank deformat, -close and closed media + +20 Oct 2007 [1225] +test/xorriso.txt ++ test/xorriso.1 +test/changelog.txt +Splitted think text from emerging man page, formatted man page + +2007.10.20.194918 [1226] +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +Completed -tell_media_space, checked space before burn, failed -end exits >0 + +20 Oct 2007 [1227] +test/xorriso.1 +Polished man page + +2007.10.21.094818 [1228] +test/xorriso_private.h +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +test/xorriso.1 +Implemented -rm and -rm_r + +2007.10.21.105228 [1229] +src/data_source.c +Silenced compiler warning about C++ style comment + +2007.10.21.124315 [1230] +test/xorriso.c +test/xorrisoburn.c +test/xorrisoburn.h +Began to implement -ls and -ls_l, enhanced -cdi, not done yet + +2007.10.21.151124 [1231] +test/xorriso_private.h +test/xorriso.c +test/xorrisoburn.c +test/xorrisoburn.h +Hopefully completed -cd alias -cdi + +2007.10.21.185248 [1232] +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +test/xorriso.1 +Hopefully completed -cdx + +2007.10.21.213303 [1233] +test/xorriso_private.h +test/xorriso.c +test/xorrisoburn.c +test/xorriso.1 +Implemented sorting of -ls by node name, implemented leaf name search patterns + +2007.10.22.211928 [1237] +test/xorrisoburn.c +test/xorriso.1 +Implemented file size and mtime for -ls_l + +2007.10.23.122349 [1238] +src/libisoburn.h +src/isoburn.c +Added fifo_size to struct isoburn_source_opts + +2007.10.23.122753 [1239] +test/xorrisoburn.c +test/xorriso.c +test/xorriso.1 +Made use of isoburn_source_opts.fifo_size + +2007.10.24.100156 [1244] +test/xorriso.c +test/xorrisoburn.c +Normalized paths to target and source before adding or removing from image + +2007.10.24.105424 [1245] +test/xorriso.c +test/xorriso.h +Implemented option -path-list + +2007.10.24.175337 [1247] +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +Made -cd useable with no image loaded + +2007.10.27.224148 [1257] +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +test/xorriso.1 +Implemented option -mv + +2007.10.27.230512 [1258] +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +Bug fixes with option -mv + +2007.10.28.125501 [1260] +test/xorriso.c +test/xorrisoburn.c +Prevented some interesting pitfalls with -mv + +2007.10.28.165516 [1261] +test/xorriso.c +test/xorriso.1 +test/xorrisoburn.h +test/xorrisoburn.c +Implemented option -mkdir + +2007.10.28.174550 [1262] +test/xorriso.c +Warning of wildcards in paths + +28 Oct 2007 [1263] +test/xorriso.1 +Updated man page about -path-list + +2007.10.29.213920 [1273] +test/xorriso_private.h +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +test/xorriso.1 +Structured patterns for options -ls and -ls_l + +2007.10.30.214242 [1274] +test/xorriso_private.h +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +test/xorriso.1 +test/compile_xorriso.sh +Multiple structured patterns, changed option -ls from single to multi args + +2007.10.31.103338 [1275] +test/xorriso_private.h +test/xorriso.h +test/xorriso.c +test/xorrisoburn.c +test/xorriso.1 +Implemented new option -temp_mem_limit + +2007.10.31.165413 [1276] +test/xorriso.c +test/xorrisoburn.c +test/xorrisoburn.h +Gave simple -ls an implemention with minimal memory consumption + +31 Oct 2007 [1277] +test/xorriso.1 +Overhauled info paragraphs of man page + +2007.10.31.175916 [1278] +test/xorriso_private.h +Overhauled comments in struct XorrisO + +31 Oct 2007 [1279] +test/changelog.txt +Updating changelog + +2007.11.01.111351 [1280] +test/xorrisoburn.c +Got rid of bad pacifier text at end of CD writing + +2007.11.01.191106 [1281] +test/xorriso.h +test/xorriso.c +test/xorrisoburn.c +test/xorrisoburn.h +test/xorriso.1 +Implemented option -du + +2007.11.02.143549 [1282] +test/xorrisoburn.h +test/xorrisoburn.c +Clearer status messages after reading new volume and after burning + +2007.11.02.143658 [1283] +test/xorriso.c +Made -abort_on and -report_about complain with bad severity names + +2007.11.02.184705 [1284] +test/xorrisoburn.c +test/xorriso.1 +Polished write success message and man page + +2007.11.06.163305 [1285] +test/xorriso_private.h +test/xorriso.h +test/xorriso.c +test/xorrisoburn.c +test/xorriso.1 +Implemented -overwrite control + +2007.11.06.163929 [1286] +src/libisoburn.h +Corrected a typo in a comment + +2007.11.06.164029 [1287] +src/isoburn.c +Closed memory leak by freeing session and track in isoburn_prepare_disc_aux() + +2007.11.07.123744 [1288] +test/xorriso_private.h +test/xorriso.h +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +test/xorriso.1 +Implemented option -reassure + +2007.11.07.150157 [1289] +test/xorriso.h +test/xorriso.c +test/xorrisoburn.c +test/xorriso.1 +Implemented option -rmdir + +2007.11.07.191915 [1290] +test/xorriso.h +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +Implemented option -chmod (does not get written into image, though) + +2007.11.07.225624 [1291] +test/xorriso.c +test/xorrisoburn.c +test/xorrisoburn.h +Implemented options -chown and -chgrp (not written into image, though) + +2007.11.08.144451 [1292] +test/xorriso.c +test/xorrisoburn.c +test/xorrisoburn.h +test/xorriso.1 +Implemented option -alter_date, corrected write problem with mode and ownership + +2007.11.08.145016 [1293] +test/xorriso_private.h +Forgotten source file for rev 1292 + +8 Nov 2007 [1294] +test/xorriso.1 +Enhanced man page text for options -chmod, -chown, -chgrp + +2007.11.08.160302 [1295] +test/xorriso.c +Fixed bug with -chmod go=r + +2007.11.08.161215 [1296] +test/xorriso.c +test/xorrisoburn.c +Enlarged string size limit of Text_shellsafe() + +2007.11.09.193142 [1297] +test/xorriso_private.h +test/xorriso.h +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +test/xorriso.1 +New option -iso_rr_pattern, influencing several options with multiple args + +2007.11.11.112321 [1298] +test/xorriso.h +test/xorriso.c +test/xorrisoburn.c +Gave problem handling finer granularity within loops + +11 Nov 2007 [1299] +test/xorriso.1 +Clarified man page + +2007.11.11.154453 [1300] +test/xorriso.c +Added missing commit to normal end of program + +11 Nov 2007 [1301] +test/xorriso.1 +Added some examples to man page + +2007.11.14.142904 [1302] +src/libisoburn.h +src/isofs_wrap.c +src/isoburn.c +test/test.c +New API call isoburn_attach_volset(), changes with isoburn_read_volset() + +2007.11.14.143119 [1303] +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +test/xorriso.1 +Implemented options -outdev and -indev + +2007.11.14.175446 [1304] +test/xorriso.c +Corrected premature abort bug with misspelled command words + +14 Nov 2007 [1305] +test/xorriso.1 +Polished xorriso man page + +14 Nov 2007 [1306] +test/changelog.txt +Updated xorriso changelog + +2007.11.26.192113 [1311] +test/xorriso.c +test/xorrisoburn.c +Reacted on warnings on a 64 bit system + +2007.12.04.074340 [1314] +test/xorriso.h +test/xorriso_private.h +test/xorriso.c +test/xorrisoburn.c +test/xorriso.1 +Implemented -disk_pattern, -lsx, ls_lx, -dux, -du_lx + +2007.12.04.205919 [1315] +test/xorrisoburn.c +test/xorriso_private.h +test/xorriso.c +Removed some redundancy of disk_pattern and iso_rr_pattern matching + +4 Dec 2007 [1316] +test/xorriso.1 +Polished man page + +2007.12.05.090438 [1317] +test/xorriso.h +test/xorriso.c +test/xorriso.1 +Option -f-off as counterpart of option -f + +2007.12.05.143632 [1318] +test/xorriso.c +Made dashes at options optional + +5 Dec 2007 [1319] +test/xorriso.1 +Overhauled description of media types, states and expansion methods + +2007.12.06.150102 [1320] +test/xorriso.h +test/xorriso.c +test/xorriso.1 +Changed -f, -f-off to -follow, -graft-points, -graf-points-off to -pathspecs + +6 Dec 2007 [1321] +test/xorriso.1 +Removed references to option -graft-points + +2007.12.06.192437 [1322] +test/xorriso.c +Corrected warning function about wildcards + +8 Dec 2007 [1326] +test/xorriso.1 +Explained result pager + +2007.12.08.175117 [1327] +test/xorriso.c +test/xorriso_private.h +test/xorrisoburn.c +Removed more code redundancies and fd leak with Xorriso_obtain_pattern_files_x() + +2007.12.15.162039 [1328] +test/compile_xorriso.sh +Added -O0 to -g to get better gdb behavior on my new system + +2007.12.15.183022 [1329] +test/xorriso_private.h +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +test/xorriso.1 +Implemented option -follow + +2007.12.16.103456 [1330] +test/xorriso.c +test/xorriso.1 +Added link hop limit to option -follow + +2007.12.16.122626 [1331] +test/xorrisoburn.c +Added copying of attributes from symbolic link into image + +2007.12.16.144615 [1332] +test/xorrisoburn.c +Removed waste of time in Xorriso_show_du_subs() + +2007.12.18.175924 [1333] +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +test/xorriso.1 +Changed options -ls* to -lsd*, introduced new family of -ls* without d + +2007.12.20.111338 [1334] +test/xorriso.h +test/xorriso.c +test/xorrisoburn.c +test/xorriso.1 +Changed -du_s* into -dus* + +2007.12.21.131538 [1335] +test/xorriso.h +test/xorriso_private.h +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +test/xorriso.1 +Implemented option -find alias -findi + +2007.12.21.132017 [1336] +test/xorriso.c +test/xorriso.1 +Corrected documentation about -find + +2007.12.22.143803 [1337] +test/xorriso.h +test/xorriso.c +test/xorrisoburn.c +test/xorriso.1 +Implemented option -findx + +2007.12.24.161107 [1339] +test/xorriso.c +Repaired options -dus and -dusx + +24 Dec 2007 [1340] +test/changelog.txt +Updated changelog + +2007.12.25.160100 [1341] +test/xorriso.h +test/xorriso.c +test/xorriso.1 +Implemented option -cpr + +2007.12.26.160040 [1342] +test/xorriso.h +test/xorriso_private.h +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +test/xorriso.1 +Changed option -J to -joliet "on"|"off", implemented option -volid + +2007.12.28.132741 [1343] +test/xorriso_private.h +test/xorriso.c +test/xorrisoburn.c +Made leaner the local memory of recursive functions (because of ulimit -s) + +2007.12.30.190138 [1344] +test/xorriso.h +test/xorriso_private.h +test/xorriso.c +test/xorrisoburn.c +test/xorriso.1 +Implemented -find option -exec echo, chown, chgrp, chmod, alter_date, lsdl + +2007.12.30.203336 [1345] +test/xorriso.c +Corrected superuser behavior of Sfile_lookup_permissions() + +2007.12.31.095229 [1346] +test/xorriso.c +test/xorrisoburn.c +Repaired some bugs in -find and -findx + +2007.12.31.135237 [1347] +test/xorriso.h +test/xorriso.c +test/xorriso.1 +Implemented options -chown_r, -chgrp_r, -chmod_r, -alter_date_r + +2007.12.31.135330 [1348] +test/xorrisoburn.c +Repaired a bug in -find + +2008.01.01.123118 [1349] +test/xorriso.h +test/xorriso_private.h +test/xorriso.c +test/xorrisoburn.h +test/xorrisoburn.c +test/xorriso.1 +Implemented -find actions chown_r, chgrp_r, chmod_r, alter_date_r, find + +2008.01.02.175011 [1350] +test/xorriso.c +test/xorriso.1 +Implemented -find test -type + +2008.01.09.175418 [1351] +test/xorrisoburn.c +Corrections made during porting to nglibisofs + +2008.01.10.114451 [1352] ++ test/ng_xorrisoburn.h ++ test/ng_xorrisoburn.c +test/compile_xorriso.sh +Begin of porting to next generation libisofs + +2008.01.10.151924 [1353] +Makefile.am ++ ng_src ++ ng_src/libisoburn.h ++ ng_src/isoburn.h ++ ng_src/isoburn.c ++ ng_src/isofs_wrap.c ++ ng_src/data_source.c ++ ng_src/burn_wrap.c +Begin of porting to next generation libisofs + +2008.01.10.152353 [1354] +test/ng_xorrisoburn.c +test/compile_xorriso.sh +Made compile_xorriso.sh -nglibisofs work on ./ng_src + +2008.01.10.154948 [1355] +test/ng_xorrisoburn.c +test/compile_xorriso.sh +Made compile_xorriso.sh -oglibisofs work on ./og_src + +2008.01.11.133319 [1356] +test/compile_xorriso.sh +Adapted to existence of nglibisofs eltorito.o + +2008.01.11.133631 [1357] +test/xorriso.c +test/ng_xorrisoburn.c +test/xorrisoburn.c +Removed old and new bugs + +2008.01.11.174733 [1358] +test/xorriso.c +test/ng_xorrisoburn.c +test/xorrisoburn.c +Tracing the different behavior of isoburn_read_image() + +2008.01.11.175423 [1359] +test/ng_xorrisoburn.c +ng_src/isoburn.c +ng_src/libisoburn.h +Changed isoburn_source_opts.ouput_charset to output_charset + +2008.01.11.212545 [1361] +ng_src/isofs_wrap.c +Made initialization of iso_read_opts safer + +13 Jan 2008 [1364] ++ og_src +- src src/burn_wrap.c +- src/isoburn.c +- src/isoburn.h +- src/data_source.c +- src/isofs_wrap.c +- src/libisoburn.h ++ og_src/burn_wrap.c ++ og_src/isoburn.c ++ og_src/isoburn.h ++ og_src/data_source.c ++ og_src/isofs_wrap.c ++ og_src/libisoburn.h +Moved src to og_src and installed symbolic link instead + +13 Jan 2008 [1365] +ng_src/isofs_wrap.c +Changes about blanking loaded image + +2008.01.13.224929 [1366] +test/ng_xorrisoburn.c +Allowed all filetypes as input, silenced debug during image read + +14 Jan 2008 [1367] +test/compile_xorriso.sh +Added forgotten source module + +14 Jan 2006 [1368] +ng_src/libisoburn.h +ng_src/isoburn.c +New members in isoburn_source_opts + +2008.01.14.163814 [1369] +test/ng_xorrisoburn.c +Closed memory leak, adapted to new members in isoburn_source_opts + +2008.01.14.164628 [1370] +test/ng_xorrisoburn.c +Repaired memory hog and a freshly introduced bug + +2008.01.14.190220 [1371] +test/xorriso.c +test/ng_xorrisoburn.c +test/xorriso.1 +Removed some bugs and made adaptions to nglibisofs + +2008.01.14.224645 [1372] +test/xorriso_private.h +test/xorriso.c +test/ng_xorrisoburn.h +test/ng_xorrisoburn.c +test/xorriso.1 +Made improvements around volume id + +2008.01.15.174409 [1373] +test/xorriso.h +test/xorriso_private.h +test/xorriso.c +test/ng_xorrisoburn.h +test/ng_xorrisoburn.c +test/xorrisoburn.h +test/xorrisoburn.c +Made improvements about pattern matching .., closed small memory leaks + +2008.01.15.204057 [1374] +test/xorriso.c +test/ng_xorrisoburn.h +test/ng_xorrisoburn.c +test/xorrisoburn.h +test/xorrisoburn.c +Closed a small memory leak + +2008.01.15.211511 [1375] +test/ng_xorrisoburn.c +Added a forgotten iso_dir_iter_free() + +2008.01.16.132909 [1376] +ng_src/isofs_wrap.c +Repaired bug about MMC multi-session image loading + +2008.01.16.141631 [1378] +ng_src/isoburn.c +Changed default name of initial image to ISOIMAGE + +16 Jan 2008 [1378] +libisoburn.pc.in +Set correct name of library + +2008.01.16.200942 [1379] +test/xorriso.c +test/ng_xorrisoburn.c +Adaption to Xorriso_standalonE, some consequences from compiler warnings + +16 Jan 2008 [1380] ++ test/make_xorriso_standalone.sh ++ test/xorriso_makefile_am.txt ++ test/configure_ac.txt ++ test/xorriso_pc_in.txt +A sketch of a xorriso source standalone release generator + +16 Jan 2008 [1381] +test/configure_ac.txt +test/xorriso_makefile_am.txt +Added a test for readline.h and eventually enabled use of libreadline + +2008.01.17.145135 [1382] +test/ng_xorrisoburn.c +Silenced -pedantic compiler warnings about type punning + +17 Jan 2008 [1385] +test/make_xorriso_standalone.sh +Silenced most compiler warnings of libisofs in xorriso-standalone + +17 Jan 2008 [1386] ++ test/README +Began a README file for xorriso + +18 Jan 2008 [1387] +test/make_xorriso_standalone.sh +test/README ++ test/xorriso_eng.html +Worked on documentation + +2008.01.18.101933 [1388] +test/xorriso.c +Changed -report_about default to "UPDATE" + +18 Jan 2008 [1389] +test/xorriso.1 +test/make_xorriso_standalone.sh ++ test/convert_man_to_html.sh +Made a generator for HTML man page + +2008.01.19.090417 [1390] +ng_src/libisoburn.h +ng_src/isoburn.c +ng_src/isofs_wrap.c +test/ng_xorrisoburn.c +test/compile_xorriso.sh +test/xorriso_makefile_am.txt +Adaptions to revision 241 of nglibisofs + +2008.01.19.090546 [1391] +test/xorriso.c +Added startup message. Removed helptext sentence about unimplemented options + +19 Jan 2008 [1392] +test/xorriso_eng.html +test/make_xorriso_standalone.sh +Producing a bootstrapped xorriso standalone tarball + +19 Jan 2008 [1393] +test/README +test/xorriso.1 +test/xorriso_eng.html +Some polishing of xorriso documentation + +2008.01.19.162244 [1394] +test/xorriso.c +test/ng_xorrisoburn.c +Small corrections with version number and write counter report + +19 Jan 2008 [1395] +test/changelog.txt +Updated SVN copy of changelog + +2008.01.20.102946 [1397] +ng_src/burn_wrap.c +ng_src/data_source.c +ng_src/isoburn.c +ng_src/isofs_wrap.c +Made forgotten adaption to Xorriso_standalonE + +2008.01.20.131050 [1398] +test/xorriso.h +test/xorriso_private.h +test/xorriso.c +test/ng_xorrisoburn.c +test/xorriso.1 +Made -outdev stdio:/dev/fd/1 safe for single session runs + +2008.01.20.200254 [1399] +test/xorriso.h +test/xorriso_private.h +test/xorriso.c +test/xorriso.1 +New option -add_plainly + +2008.01.21.221939 [1400] +test/xorriso.c +test/xorriso.1 +Rejected unsuitable addresses "stdio:" , "stdio:/", "stdio:-", "stdio:." + +22 Jan 2008 [1401] ++ test/compare_file.c +Program which compares two files in different trees. Attributes and content. + +22 Jan 2008 [1402] +test/configure_ac.txt +Copied test for tm.tm_gmtim from libisofs configure.ac + +22 Jan 2008 [1403] +test/compare_file.c +Prepended type indication letter to report lines + +2008.01.22.224321 [1404] +test/ng_xorrisoburn.c +Better attributes with directories + +2008.01.23.195855 [] +ng_src/burn_wrap.c +test/ng_xorrisoburn.c +Adapted to libisofs revision 261 + +24 Jan 2008 [1410] +test/make_xorriso_standalone.sh +Removed remover of C++ comment lines + +2008.01.24.202206 [1411] +ng_src/isoburn.c +ng_src/burn_wrap.c +ng_src/isoburn.h +Gave up use of libburn fifo. Attached -fs and pacifier to libisofs fifo. + +2008.01.25.150902 [1413] +test/xorriso.h +test/xorriso.c +test/xorriso.1 +New option -rollback_end + +25 Jan 2008 [1414] +test/compare_file.c +Fixed bug about file content comparison. + +25 Jan 2008 [1415] +test/compare_file.c +Better handling of various content difference situations + +2008.01.25.175353 [1416] +test/xorriso.h +test/xorriso.c +test/xorriso.1 +test/ng_xorrisoburn.c +New option -commit_eject + +2008.01.26.002011 [1417] +- og_src/libisoburn.h +- og_src/isoburn.h +- og_src/isoburn.c +- og_src/isofs_wrap.c +- og_src/burn_wrap.c +- og_src/data_source.c +- og_src/ ++ libisoburn/ +- ng_src/libisoburn.h +- ng_src/isoburn.h +- ng_src/isoburn.c +- ng_src/isofs_wrap.c +- ng_src/burn_wrap.c +- ng_src/data_source.c ++ libisoburn/libisoburn.h ++ libisoburn/isoburn.h +*+ libisoburn/isoburn.c +*+ libisoburn/isofs_wrap.c +*+ libisoburn/burn_wrap.c +*+ libisoburn/data_source.c ++ xorriso/ +- test/README +- test/changelog.txt +- test/compare_file.c +- test/compile_xorriso.sh +- test/configure_ac.txt +- test/convert_man_to_html.sh +- test/make_timestamp.sh +- test/make_xorriso_standalone.sh +- test/ng_xorrisoburn.c +- test/ng_xorrisoburn.h +- test/xorriso.1 +- test/xorriso.c +- test/xorriso.h +- test/xorriso_eng.html +- test/xorriso_makefile_am.txt +- test/xorriso_pc_in.txt +- test/xorriso_private.h +- test/xorriso_timestamp.h +- test/xorrisoburn.c +- test/xorrisoburn.h ++ xorriso/README ++ xorriso/changelog.txt ++ xorriso/compare_file.c +*+ xorriso/compile_xorriso.sh ++ xorriso/configure_ac.txt +*+ xorriso/convert_man_to_html.sh +*+ xorriso/make_timestamp.sh +*+ xorriso/make_xorriso_standalone.sh ++ xorriso/xorriso.1 +*+ xorriso/xorriso.c ++ xorriso/xorriso.h ++ xorriso/xorriso_eng.html ++ xorriso/xorriso_makefile_am.txt ++ xorriso/xorriso_pc_in.txt ++ xorriso/xorriso_private.h ++ xorriso/xorriso_timestamp.h +*+ xorriso/xorrisoburn.c ++ xorriso/xorrisoburn.h +Makefile.am +Gave up adapter to old libisofs. Renaming libisoburn and xorriso dirs. + +2008.01.26.113604 [1418] +libisoburn/libisoburn.h +libisoburn/burn_wrap.c +xorriso/xorrisoburn.c +INCOMPATIBLE API CHANGE: isoburn_initialize(char msg[1024], int flag) + +2008.01.26.120534 [1419] +libisoburn/libisoburn.h +configure.ac +version.h.in +libisoburn/isoburn.c +libisoburn/burn_wrap.c +Introduced versioning (still pre-release) and new API function isoburn_version() + +2008.01.26.140005 [1423] +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +xorriso/xorriso_eng.html +Adapted standalone tarball to version functions + +2008.01.26.142130 [1424] +xorriso/xorriso.c +Set program revision to 0.0.1 (previous 0.1.0 was too early) + +2008.01.26.171156 [1425] +libisoburn/libisoburn.h +libisoburn/isoburn.c +libisoburn/burn_wrap.c +xorriso/xorrisoburn.c +INCOMPATIBLE API CHANGE: isoburn_prepare_new_image() now gets output drive + +2008.01.27.174454 [1434] +xorriso/xorriso.c +xorriso/xorriso.1 +Changed meaning of -add relative/path + +2008.01.28.105404 [1435] +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +Made use of iso_set_abort_severity() with option -abort_on + +2008.01.28.140149 [1436] +libisoburn/libisoburn.h +Updated API introduction and marked API instabilities for mending (soon) + +2008.01.28.171915 [1437] +libisoburn/isoburn.c +libisoburn/isofs_wrap.c +xorriso/xorrisoburn.c +xorriso/compile_xorriso.sh +xorriso/make_xorriso_standalone.sh +Adapted to libisofs revison 294 + +2008.01.28.235717 [1438] +libisoburn/libisoburn.h +libisoburn/isoburn.h +libisoburn/isoburn.c +xorriso/xorrisoburn.c +Changed struct isoburn_source_opts to opaque handle struct isoburn_imgen_opts + +2008.01.29.125956 [1439] +libisoburn/libisoburn.h +libisoburn/isoburn.h +libisoburn/isoburn.c +xorriso/xorrisoburn.c +Changed struct isoburn_read_opts to opaque handle + +2008.01.29.184356 [1440] +configure.ac +version.h.in +libisoburn/libisoburn.h +libisoburn/isoburn.c +libisoburn/burn_wrap.c +xorriso/xorrisoburn.c +xorriso/configure_ac.txt +New API call isoburn_is_compatible() + +29 Jan 2008 [1441] +libisoburn/libisoburn.h +Some API documentation enhancements + +2008.01.29.211543 [1443] +libisoburn/burn_wrap.c +Made use of newest libburn version features + +2008.01.31.152131 [1449] +libisoburn/libisoburn.h +libisoburn/isoburn.h +libisoburn/isoburn.c +libisoburn/isofs_wrap.c +xorriso/make_xorriso_standalone.sh +Adapted to libisofs revision 313 + +2008.01.31.214647 [1450] +xorriso/xorrisoburn.h +libisoburn/libisoburn.h +libisoburn/burn_wrap.c +xorriso/make_xorriso_standalone.sh +Compile time and runtime checks for library compatibility + +2008.02.01.195817 [1455] +configure.ac +Makefile.am +- libisoburn.pc.in ++ libisoburn-1.pc.in +xorriso/README +Enabled build of dynamically linked xorriso, joined -1.pc club + +2008.02.01.200153 [1456] +xorriso/xorriso_makefile_am.txt +Corrected some false paths in xorriso-standalone Makefile.am + +2008.02.02.131049 [1457] +configure.ac +Added version checks for libburn and libisofs (by Vreixo) + +2008.02.02.131903 [1458] +xorriso/xorriso.h +xorriso/xorriso.c +Added argument to option -commit_eject + +2 Feb 2008 [1459] +xorriso/xorriso_eng.html +Updated to current state of development + +2008.02.02.181200 [1460] +xorriso/xorrisoburn.c +Compile time check of libisoburn. Enforced minimum track size of 300 sectors. + +2008.02.03.131525 [1466] +libisoburn/isoburn.h +libisoburn/isoburn.c +libisoburn/burn_wrap.c +libisoburn/isofs_wrap.c +xorriso/xorrisoburn.c +Made use of ISO_ERR_SEV() and ISO_ERR_PRIO() + +2008.02.03.155704 [1467] +libisoburn/isofs_wrap.c +Adapted to libisofs revisio 328 + +2008.02.03.164038 [1468] +libisoburn/libisoburn.h +libisoburn/isoburn.c +xorriso/xorrisoburn.c +New API call isoburn_cancel_prepared_write() + +2008.02.03.164916 [1469] +xorriso/xorrisoburn.c +Reacted on compiler warning + +2008.02.03.181259 [1470] +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Made -abort_on and -report_about preemptive if given as dashed start arguments + +2008.02.04.093106 [1471] +libisoburn/burn_wrap.c +xorriso/xorrisoburn.c +Adapted to libisofs revision 332 + +2008.02.04.154405 [1472] +libisoburn/libisoburn.h +libisoburn/isoburn.c +xorriso/xorrisoburn.c +New API call isoburn_sync_after_write() + +2008.02.04.184038 [1475] +libisoburn/libisoburn.h +libisoburn/isoburn.c +libisoburn/burn_wrap.c +libisoburn/isofs_wrap.c +xorriso/xorrisoburn.c +Inserted problem messages where libisoburn API produces own failures + +2008.02.04.214133 [1476] +libisoburn/libisoburn.h +libisoburn/isoburn.c +xorriso/xorrisoburn.c +Added parameter to new API calls isoburn_cancel_prepared_write, isoburn_sync_after_write + +2008.02.05.162621 [1477] +xorriso/xorriso.h +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -padding + +2008.02.05.175733 [1478] +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorriso.1 +Implemented reassure for -rollback, -rollback_end, -end, -commit, -commit_eject + +2008.02.05.191456 [1479] +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorriso.1 +Implemented reassure for -blank, -format, -dev, -indev, -devices + +2008.02.06.131028 [1480] +xorriso/xorriso.c +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +libisoburn/libisoburn.h +libisoburn/burn_wrap.c +Now loading libraries before -version, pacifier for -add + +2008.02.06.153709 [1481] +libisoburn/burn_wrap.c +xorriso/xorriso.c +xorriso/xorriso.1 +xorriso/xorrisoburn.c +Rectified SORRY,FAILURE,FATAL classification + +2008.02.06.183423 [1484] +libisoburn/burn_wrap.c +xorriso/xorrisoburn.c +Adapted to libisofs revision 337 + +2008.02.06.183557 [1485] +xorriso/xorriso.c +Removed some unused code + +2009.02.06.184008 [1486] +libisoburn/burn_wrap.c +xorriso/xorrisoburn.c +Added a missing 0 digit + +2008.02.06.214426 [1487] +libisoburn/libisoburn.h +libisoburn/isoburn.h +libisoburn/isoburn.c +libisoburn/isofs_wrap.c +xorriso/xorrisoburn.c +Pacifier for isoburn_read_image() + +2008.02.07.074248 [1489] +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso_private.h +Added final message to image read pacifier + +2008.02.07.154947 [1490] +libisoburn/data_source.c +Implemented a primitive single tile cache for image reading + +2008.02.07.211424 [1491] +libisoburn/data_source.c +Stuffed memory leak with read cache. Economized on error retries. + +8 Feb 2008 [1494] +- xorriso/compare_file. ++ test/compare_file.c +- ng_src +Cleaning up remainings of move to ng_src + +8 Feb 2008 [1495] +test/compare_file.c +Fixed an endless cycle with early EOF + +2008.02.08.102122 [1496] +xorriso/xorriso_makefile_am.txt +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +xorriso/README +Added test/compare_file.c to xorriso-standalone tarball + +2008.02.08.173928 [1497] +2008.02.08.174126 [1498] +libisoburn/data_source.c +Renamed macro which controls read caching + +2008.02.08.175152 [1499] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Protecting volume ids from getting overwritten by predecessor + +2008.02.08.195627 [1500] +xorriso/xorriso.c +Warning of -volid which are not ECMA 119 compliant + +2008.02.08.215113 [1501] +xorriso/xorriso.h +xorriso/xorriso.c +Silenced misleading toc messages with -commit_eject "in" + +2008.02.09.092805 [1502] +libisoburn/libisoburn.h +libisoburn/isoburn.c +Adapted to libisofs revision 346 + +2008.02.09.100750 [1503] +libisoburn/libisoburn.h +libisoburn/burn_wrap.c +xorriso/xorriso.c +xorriso/xorrisoburn.c +New API function isoburn_disc_available_space() fixes bug with DVD+RW capacity + +10 Feb 2008 [1504] +xorriso/README +Some adjustments in description of compare_file and libisoburn + +2008.02.10.122020 [1505] +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Fixed bugs about -mv /im/age . -cdx / -cpr di/sk im/age -- -cpr di/sk . -- + +2008.02.10.130852 [1506] +Makefile.am +Added build of test/compare_file as noinst binary + +2008.02.10.135822 [1507] +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +Better handling of not-yet-existing -cd + +2008.02.11.094742 [1509] +xorriso/xorriso_private.h +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Discarding, keeping or patching boot images from existing ISO images + +2008.02.11.112917 [1510] +xorriso/xorrisoburn.c +Corrected message about isolinux patch option + +2008.02.11.113235 [1511] +xorriso/xorriso.h +xorriso/xorriso.c +Final UPDATE message after grafting in files from disk + +2008.02.11.135418 [1512] +xorriso/xorriso_private.h +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorriso.1 +New option -return_with + +2008.02.11.150123 [1513] +xorriso/xorrisoburn.c +isoburn_igopt_allow_full_ascii for -bootimage any keep + +2008.02.11.150700 [1514] +xorriso/xorriso.c +xorriso/xorriso.1 +Clarifications about -volid rules + +11 Feb 2008 [1515] +xorriso/README +Adjustments about libisoburn and xorriso dynamic dependencies, compare_file + +2008.02.11.162406 [1516] +xorriso/xorrisoburn.c +xorriso/xorriso.c +Changed failure to find a file for removal from FAILURE to SORRY + +2008.02.11.174517 [1517] +xorriso/xorriso.c +Corrected a bug about -status -return_with + +2008.02.11.194807 [1519] +libisoburn/burn_wrap.c +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New severity MISHAP + +2008.02.11.213918 [1520] +xorriso/xorrisoburn.c +Mapping in burn runs -abort_on MISHAP to SORRY + +2008.02.12.215327 [1521] +libisoburn/burn_wrap.c +xorriso/xorriso.c +xorriso/xorrisoburn.c +Improved MISHAP - SORRY mapping and tunneling + +2008.02.14.084342 [1525] ++ README ++ COPYING ++ COPYRIGHT ++ INSTALL +libisoburn/libisoburn.h +Completing documentation + +2008.02.14.101916 [1526] +Makefile.am +Adjusted EXTRA_DIST list of files + +2008.02.14.120557 [1527] +xorriso/xorrisoburn.c +Made a final abort check before burning begins + +2008.02.14.175623 [1528] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +Imprinting version of xorriso and libraries into ISO preparer_id + +2008.02.14.182351 [1529] +xorriso/xorrisoburn.c +Made preparer_id more safe against oversize + +14 Feb 2008 [1530] +xorriso/xorriso.1 +Polished man page + +14 Feb 2008 [1531] +xorriso/changelog.txt +Updated changelog + +2008.02.15.100001 [branch 1533] +configure.ac +README +libisoburn/libisoburn.h +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/compile_xorriso.sh +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +Made version number leap to 0.1.0 + +15 Feb 2008 [branch 1534] +xorriso/changelog.txt +Documented initial release and timestamp + +15 Feb 2008 [1536] +configure.ac +Increased libisofs requirement to 0.6.2 + +----------------------------- release - xorriso-0.1.0.pl00 - 2008.02.15.100001 +* Operates on an existing ISO image or creates a new one. +* Copies files from filesystem into the ISO image. +* Renames or deletes file objects in the ISO image. +* Changes file properties in the ISO image. +* Can write result as completely new image to optical media + or filesystem objects. +* Can write result as add-on session to appendable + multi-session media, to overwriteable media, + to regular files, and to block devices. +* Scans for optical drives, blanks re-useable optical media. +* Reads its instructions from command line arguments, dialog, and batch files. +* Provides navigation commands for interactive ISO image manipulation. +* Adjustable thresholds for abort, exit value, and problem reporting. + + +2008.02.15.211836 [1537] +configure.ac +README +libisoburn/libisoburn.h +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/compile_xorriso.sh +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +Version leap to 0.1.1 + +15 Feb 2008 [1538] +COPYRIGHT +Corrected according to content of libisofs/COPYRIGHT + +2008.02.15.212030 [1539] +xorriso/xorriso.c +Changed pacifier text for 0 nodes read from blank image + +------------------------------------ cycle - xorriso-0.1.1 - 2008.02.15.212030 + +15 Feb 2008 [1540] +xorriso/changelog.txt +Updated changelog + +16 Feb 2008 [1543] +xorriso/xorriso.1 +Adjusted CREDITS text + +2008.02.16.202533 [1544] +xorriso/xorriso_private.h +xorriso/xorrisoburn.c +Transfering properties from disk to implicit directories in image path + +2008.02.16.211549 [1545] +xorriso/xorriso_eng.html +xorriso/changelog.txt +Mentioned better directory attribute copying + +------------------------------------ cycle - xorriso-0.1.1 - 2008.02.16.211549 +* Improved attribute transfer from disk for implicit target directories + +2008.02.18.210343 [1546] +xorriso/xorriso.c +Bug fix: -report_about higher than NOTE did not report at all + +19 Feb 2008 [1547] +test/compare_file.c +Improved report format + +2008.02.19.184432 [1548] +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -as cdrecord emulates a narrow set of cdrecord gestures + +2008.02.19.212322 [1549] +xorriso/xorriso.c +xorriso/xorriso_private.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Improved -as cdrecord + +20 Feb 2008 [1550] +test/compare_file.c +Revoked inflation of file type characters to words + +2008.02.20.234726 [1551] +libisoburn/libisoburn.h +libisoburn/burn_wrap.c +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -as mkisofs emulates a narrow set of mkisofs gestures + +------------------------------------ cycle - xorriso-0.1.1 - 2008.02.21.090014 +* Bug fix: -report_about HINT or higher did not report at all +* Bug fix: speed=number without unit or media type letter was always CD speed +* Bug fix: it was possible to write to appendable media which was not -indev +* New option -as "cdrecord" emulates a narrow set of cdrecord gestures +* New option -as "mkisofs" emulates a narrow set of mkisofs gestures + +2008.02.21.090014 [1552] +xorriso/xorriso.h +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +New option -publisher + +2008.02.21.185203 [1553] +libisoburn/libisoburn.h +libisoburn/isoburn.h +libisoburn/isoburn.c +libisoburn/burn_wrap.c +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Implemented a more reasonable solution for drive truncation with regular files + +2008.02.21.204613 [1558] +libisoburn/burn_wrap.c +xorriso/xorrisoburn.c +Introduced new severity ERRFILE + +2008.02.21.211101 [1559] +xorriso/xorriso.c +Updated -help text + +2008.02.22.114917 [1561] +libisoburn/burn_wrap.c +xorriso/xorriso.c +xorriso/xorrisoburn.c +Producing ERRFILE messages where appropriate + +2008.02.23.101619 [1568] +libisoburn/libisoburn.h +Changed libisofs requirements to 0.6.3 + +2008.02.23.101619 [1569] +libisoburn/burn_wrap.c +xorriso/xorrisoburn.c +Testwise implementation of libisofs.0.6.3 features + +2008.02.23.101619 [1570] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorriso.1 +New option -errfile_log + +2008.02.23.102903 [1571] +xorriso/configure_ac.txt +Made libisofs version leap in xorriso-standalone + +2008.02.23.113902 [1572] +xorriso/xorriso.h +xorriso/xorriso.c +Directed -as mkisofs -print-size to real stdout + +2008.02.23.125537 [1573] +xorriso/xorrisoburn.c +Various bugs and deviations around -as mkisofs -print-size + +2008.02.23.131825 [1574] +xorriso/xorrisoburn.c +Wrong description text + +2008.02.25.090001 [ZeroOneZero-pl01 1576 1577] +libisoburn/burn_wrap.c +xorriso/xorriso_timestamp.h +Safety cap for ABI usage bug towards libisofs >= 0.6.2 + +2008.02.25.174229 [1579] +libisoburn/burn_wrap.c +xorriso/xorrisoburn.c +Adapted to libisofs 362 from Vreixo bzr + +2008.02.25.204402 [1580] +xorriso/xorriso.c +Adaptions of -as mkisofs and -as cdrecord to enable full use by scdbackup + +25 Feb 2008 [1581] +xorriso/changelog.txt +Updated changelog + +------------------------------------ cycle - xorriso-0.1.1 - 2008.02.25.204402 +* New option -publisher +* New option -errfile_log + + +26 Feb 2008 [1582] +test/compare_file.c +Avoided to read content of non-regular files + +2008.02.26.213437 [1583] +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -compare + +2008.02.27.185744 [1584] +xorriso/xorriso.c +Installed pacifier for data reading + +2008.02.28.132656 [1587] +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Added new action "compare" to -find + +28 Feb 2008 [1588] +xorriso/xorriso_eng.html +Mentioned capability to write DVD+R/DL. + +2008.02.28.212210 [1589] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +New option -compare_r + +28 Feb 2008 [1590] +xorriso/xorriso.1 +New option -compare_r, new -findx -exec in_iso, -exec no_in_iso + +28 Feb 2008 [1591] +test/compare_file.c +Micro bug fix ported from xorriso + +2008.02.28.215343 [1592] +xorriso/xorriso.c +Better handling of disk to iso address mapping during compare runs + +2008.02.29.200510 [1593] +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -update (not yet completed) + +2008.03.01.151219 [1594] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option update_r, -find actions "update" and "add_missing" (not yet completed) + +2008.03.02.172751 [1596] +xorriso/xorrisoburn.c +Made -update_r and -find -exec update safe against IsoDirIter pitfalls + +2008.03.02.201455 [1597] +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +Made IsoDirIter workaround obey -temp_mem_limit + +4 Mar 2008 [libisofs_thomas 1599 1600] +Switch to Vreixo development branch 378 + +2008.03.04.174107 [1601] +xorriso/make_xorriso_standalone.sh +xorriso/xorriso_makefile_am.txt +Adapted to libisofs Vreixo 378 + +2008.03.04.180738 [1602] +xorriso/xorriso.c +xorriso/xorrisoburn.c +Improvements about -update_r and -compare_r + +2008.03.05.125118 [1603] +xorriso/xorrisoburn.c +Bug fix: -follow param did not work for symbolic links + +------------------------------------ cycle - xorriso-0.1.1 - 2008.03.05.125118 +* Support for DVD+R/DL media +* Bug fix: -follow param did not work for adding non-directory symbolic links + + +2008.03.05.173329 [1604] +xorriso/xorriso.c +xorriso/xorrisoburn.c +Made -compare* and -update* obey -follow links (-follow mount still not correct) + +5 Mar 2008 [1605] +xorriso/xorriso.1 +Some man page clarification + +2008.03.06.114233 [1606] +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New -find actions "rm" and "rm_r", silenced comparison results with -update* + +2008.03.06.174724 [1608] +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Fixed bug about non existing disk_path with -update_r + +7 Mar 2008 [1609] +xorriso/xorriso_eng.html +Re-arranged development download part + +2008.03.07.075325 [1610] +xorriso/xorriso.c +xorriso/xorrisoburn.c +New -findx -type "m" for active mount points + +2008.03.07.182411 [1611] +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New -findx -exec action "empty_iso_dir", workaround for ticket 132 + +2008.03.07.220442 [1612] +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Made -update_r and -compare_r obey disabling of -follow "mount" + +8 Mar 2008 [libisofs_thomas 1613] +Switch to Vreixo development branch 383 + +2008.03.08.104231 [1614] +xorriso/xorrisoburn.c +Adapted to iso_tree_add_new_node() + +8 Mar 2008 [1615] +xorriso/xorriso.1 +Example use case for -update_r "Incremental backup of a few directory trees" + +------------------------------------ cycle - xorriso-0.1.1 - 2008.03.08.122747 +* Bug fix: It was not possible to -add /THIS=a /b=THIS +* New options -compare, -compare_r and according -find -exec action +* New options -update, -update_r and according -find -exec action +* New -find actions "rm", "rm_r", new -findx -type "m" -exec "empty_iso_dir" + + +2008.03.09.142200 [1616] +xorriso/xorriso.h +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -cut_out + +9 Mar 2008 [libisofs_thomas 1617] +Switch to Vreixo development branch 386 + +2008.03.09.211041 [1618] +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Some polishing about -cut_out + +2008.03.11.113444 [1619] +xorriso/xorriso.c +xorriso/xorrisoburn.c +Sketched split file scheme with partno,totalparts,offset,count,totalsize + +11 Mar 2008 [1620] +xorriso/xorriso.1 +Updated description of -cut_out + +------------------------------------ cycle - xorriso-0.1.1 - 2008.03.11.113444 +* New option -cut_out + + +2008.03.12.100001 [XorrisoZeroOneTwo 1626] +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +Version leap to xorriso-0.1.2 + +---------------------------------- release - xorriso-0.1.2 - 2008.03.12.100001 +* Bug fix: -report_about HINT or higher did not report at all +* Bug fix: speed=number without unit or media type letter was always CD speed +* Bug fix: it was possible to write to appendable media which was not -indev +* Bug fix: -follow param did not work for adding non-directory symbolic links +* Bug fix: It was not possible to -add /THIS=a /b=THIS +* Improved attribute transfer from disk for implicit target directories +* New option -as "cdrecord" emulates a narrow set of cdrecord gestures +* New option -as "mkisofs" emulates a narrow set of mkisofs gestures +* New option -publisher +* New option -errfile_log +* Support for DVD+R/DL media +* New options -compare, -compare_r and according -find -exec action +* New options -update, -update_r and according -find -exec action +* New -find actions "rm", "rm_r", new -findx -type "m" -exec "empty_iso_dir" +* New option -cut_out + + +2008.03.12.130605 [1627] +configure.ac +README +libisoburn/libisoburn.h +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +Version leap to 0.1.3 + +------------------------------------ cycle - xorriso-0.1.3 - 2008.03.12.130605 + +12 Mar 2008 [XorrisoZeroOneTwo 1628] [1629] +xorriso/changelog.txt +Documented changes and release timestamp + +2008.03.19.081837 [1637] +xorriso/xorriso.c +Bug fix: -as mkisofs -nopad must be -no-pad + +19 Mar 2008 [1638] +xorriso/xorriso.1 +Added a hint about alternating media with -update_r + +------------------------------------ cycle - xorriso-0.1.3 - 2008.03.19.081837 +* Bug fix: -as mkisofs -no-pad was misspelled -nopad + + +20 Mar 2008 [1639] +xorriso/README +Added -commit_eject all to an example which involves mount + +2008.03.20.192317 [1640] +xorriso/xorriso.c +Changed messages of -update and -update_r + +2008.03.20.210522 [1641] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +Better handling of attempt to manipulate non-existent ISO image + +2008.03.22.130031 [1642] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +Working towards coordination of -compare, -update and -cut_out + +2008.03.22.130128 [1643] +xorriso/xorrisoburn.c +Bug fix: Implicite directory attribute copying with -cut_out was wrong + +------------------------------------ cycle - xorriso-0.1.3 - 2008.03.22.130128 +* Bug fix: Implicite directory attribute copying with -cut_out was wrong + + +22 Mar 2008 [1644] +xorriso/xorriso.1 +Correction about Linux mount which does not accept session= with DVD. + +2008.03.25.170747 [1645] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +Working towards coordination of -compare, -update and -cut_out + +2008.03.26.092120 [1646] +xorriso/xorrisoburn.c +Gave up obsoleted macros and their code branches + +2008.03.27.103344 [1647] +xorriso/xorriso.c +xorriso/xorrisoburn.c +Working towards coordination of -update and -cut_out + +27 Mar 2008 [1648] +xorriso/xorriso.1 +Published coordination rules for -cut_out, -compare and -update + +2008.03.29.164038 [1649] +xorriso/xorriso_private.h +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -split_size, automated splitting of oversized files + +------------------------------------ cycle - xorriso-0.1.3 - 2008.03.29.164038 +* Coordination of -cut_out, -compare and -update +* New option -split_size, automated splitting of oversized files + +2008.03.31.081347 [1650] +xorriso/xorriso.c +xorriso/xorriso.1 +Adjusted documentation of -split_size + +2008.04.01.213121 [1652] +libisoburn/data_source.c +Replaced single 128 kB cache tile by 32 tiles of 64 kB each + +2 Apr 2008 [1653] +COPYRIGHT +Corrected GPL version + +------------------------------------ cycle - xorriso-0.1.3 - 2008.04.03.074309 +* Improved performance with reading directory trees + +2008.04.03.204051 [1657] +libisoburn/libisoburn.h +libisoburn/isoburn.h +libisoburn/isoburn.c +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -session_log + +5 Apr 2008 [1658] +xorriso/xorriso.1 +Mentioned that drives close full media automatically + +2008.04.05.112055 [1659] +xorriso/xorrisoburn.c +Reporting amount of non-data with -toc media summary + +5 Apr 2008 [1660] +xorriso/xorriso_eng.html +Mentioned new features + +------------------------------------ cycle - xorriso-0.1.3 - 2008.04.05.112055 +* New option -session_log + +2008.04.07.185727 [1662] +xorriso/xorriso.h +Added prototype of Xorriso_option_session_log() + +2008.04.07.201253 [1664] +xorriso/xorriso.c +xorriso/xorrisoburn.c +Removed some unused code + +8 Apr 2008 [1677] +xorriso/configure_ac.txt +Followed version leaps of libburn + +2008.04.08.153508 [1678] +libisoburn/libisoburn.h +xorriso/xorrisoburn.c +Made libisoburn and xorriso require libburn >= 0.4.4 + +2008.04.09.114815 [1679] +xorriso/xorriso.c +xorriso/xorrisoburn.c +Corrected behavior around image data read error + +2008.04.12.112159 [1682] +xorriso/xorriso.c +Changed behavior of -commit_eject "" + +2008.04.18.184517 [1690] +libisoburn/data_source.c +Restricted ds_read_block() messages about unreadable data to actual data block + +2008.04.20.111054 [1692] +libisoburn/data_source.c +Corrected maximum age value for read buffer tiles + +20 Apr 2008 [1693] +xorriso/xorriso.1 +Mentioned stdin with option -path_list + +2008.04.20.111419 [1694] +libisoburn/burn_wrap.c +xorriso/xorrisoburn.c +Displaying free space rather than "non-data" on drive aquiry and -toc + +28 Apr 2008 [1709] +xorriso/configure_ac.txt +Updated libisofs version number in xorriso-standalone + +------------------------------------ cycle - xorriso-0.1.3 - 2008.04.28.082539 +* Now depending on libisofs-0.6.4 + +2008.04.28.120001 [branch 1711] +configure.ac +README +libisoburn/libisoburn.h (isoburn_header_version_*) +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h (xorriso_libisoburn_req_*) +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +Version leap to 0.1.4 + +28 Apr 2008 [branch 1712] +xorriso/changelog.txt +Documented changes and release timestamp + +---------------------------------- release - xorriso-0.1.4 - 2008.04.28.120001 +* Bug fix: -as mkisofs -no-pad was misspelled -nopad +* Bug fix: Implicite directory attribute copying with -cut_out was wrong +* Coordination of -cut_out, -compare and -update +* New option -split_size, automated splitting of oversized files +* Improved performance with reading directory trees +* New option -session_log +* Dynamically linkable with release version 0.6.4 of libisofs + + +2008.04.28.122244 [1713] +configure.ac +README +libisoburn/libisoburn.h (isoburn_header_version_*) +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h (xorriso_libisoburn_req_*) +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +Version leap to 0.1.5 + +28 Apr 2008 [1714] +xorriso/changelog.txt +Documented changes and release timestamp + +------------------------------------ cycle - xorriso-0.1.5 - 2008.04.28.122244 + +2008.05.01.124248 [1716] +libisoburn/isofs_wrap.c +xorriso/xorriso.h +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -error_behavior with a first occasion 'image_loading' + +1 May 2008 [1717] +xorriso/convert_man_to_html.sh +Fine tuning of HTML man page appearance + +1 May 2008 [1718] +xorriso/xorriso.1 +Clarified "best_effort" behavior + +2008.05.01.135421 [1719] +libisoburn/data_source.c +Adjusted ds_read_block() to inofficial libisofs expectations + +2008.05.01.174110 [1720] +libisoburn/data_source.c +Adjusted ds_read_block() to inofficial libisofs expectations + +2008.05.02.072505 [1721] +libisoburn/data_source.c +Adjusted ds_read_block() to inofficial libisofs expectations + +2008.05.02.204942 [1722] +xorriso/xorriso_private.h +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +Working towards exclusion of user defined absolute paths and leaf patterns + +2008.05.03.151106 [1724] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +Working towards exclusion of user defined absolute paths and leaf patterns + +2008.05.03.223204 [1725] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +Working towards exclusion of user defined absolute paths and leaf patterns + +2008.05.04.133525 [1726] +xorriso/xorriso.c +xorriso/xorriso.1 +New options -not_paths, -not_leaf, -not_list, -not_mgt, -as mkisofs -m + +4 May 2008 [1727] +xorriso/xorriso_eng.html +xorriso/changelog.txt +Mentioned new options + +------------------------------------ cycle - xorriso-0.1.5 - 2008.05.04.133525 +* New option -error_behavior with a first occasion 'image_loading' +* New options -not_paths, -not_leaf, -not_list, -not_mgt, -as mkisofs -m + + +2008.05.05.210317 [1728] +xorriso/xorrisoburn.c +After formatting DVD-RW write 128 MB and close track to end Intermediate State + +2008.05.06.084439 [1731] +xorriso/xorrisoburn.c +Calling isoburn_cancel_prepared_write() after failed isoburn_disc_write() + +2008.05.06.144606 [1732] +libisoburn/isoburn.h +libisoburn/isoburn.c +libisoburn/isofs_wrap.c +libisoburn/burn_wrap.c +Experiment for TOC on overwriteables: Keep a target_head copy of session #1 + +2008.05.07.071427 [1737] +libisoburn/isoburn.h +libisoburn/isoburn.c +libisoburn/burn_wrap.c +libisoburn/isofs_wrap.c +Removed some outdated ifdef cases + +2008.05.07.175508 [1738] +libisoburn/libisoburn.h +libisoburn/isoburn.h +libisoburn/burn_wrap.c +Reading emulated toc info from overwriteable media, new API isoburn_toc_*() + +2008.05.07.175640 [1739] +xorriso/xorrisoburn.c +Making use of new isoburn_toc_* functions + +2008.05.07.214343 [1740] +libisoburn/libisoburn.h +libisoburn/burn_wrap.c +New API function isoburn_read_iso_head() + +2008.05.07.214442 [1741] +xorriso/xorrisoburn.c +New format with -toc is more concise and shows volume id + +2008.05.08.141054 [1742] +libisoburn/libisoburn.h +libisoburn/isoburn.h +libisoburn/burn_wrap.c +Try to read header chain from alleged -ROM media (e.g. DVD+RW in -ROM drive) + +2008.05.08.141920 [1743] +xorriso/xorriso.h +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +xorriso/xorriso_eng.html +New TOC layout with volume id and sbsector=, new option -rom_toc_scan + +8 May 2008 [1744] +xorriso/xorriso_eng.html +Mentioned new features + +------------------------------------ cycle - xorriso-0.1.5 - 2008.05.08.141920 +* Emulated TOC on overwriteable media +* New TOC layout with volume id and sbsector= +* New option -rom_toc_scan + + +2008.05.08.185350 [1745] +libisoburn/isoburn.h +libisoburn/isoburn.c +libisoburn/burn_wrap.c +Adjusted reply of isoburn_disc_get_msc1() to eventual -rom_toc_scan result + +8 May 2008 [1746] +xorriso/xorriso.1 +Updated man page examples + +8 May 2008 [1747] +xorriso/xorriso.1 +Updated man page examples + +------------------------------------ cycle - xorriso-0.1.5 - 2008.05.08.205551 + +9 May 2008 [1751] +xorriso/xorriso_eng.html +Updated details in web page + +2008.05.09.205517 [1752] +libisoburn/isofs_wrap.c +Trying to better handle non ISO images on -indev + +10 May 2008 [1761] +xorriso/configure_ac.txt +Adapted xorriso standalone production to new libburn cycle 0.4.7 + +10 May 2008 [1762] +xorriso/xorriso.1 +xorriso/xorriso_eng.html +Minor change in -update_r example + +2008.05.10.194336 [1763] +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.c +Better behavior of update_r with no image present + +2008.05.12.080812 [1765] +configure.ac +libisoburn/libisoburn.h +Switched requirements to libburn-0.4.6 + +2008.05.12.081331 [1766] +libisoburn/libisoburn.h +libisoburn/burn_wrap.c +New API call isoburn_set_msc1() + +2008.05.12.082733 [1767] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +xorriso/xorriso_eng.html +New option -load session|track|sbsector|volid + +------------------------------------ cycle - xorriso-0.1.5 - 2008.05.12.082733 +* New option -load session|track|sbsector|volid +* Now depending on libburn-0.4.6 + + +2008.05.12.193341 [1768] +libisoburn/burn_wrap.c +Reacted on harmless compiler warning + +2008.05.12.193642 [1769] +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New -blank and -format modes as_needed + +2008.05.13.115901 [1770] +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +xorriso/xorriso_eng.html +New option -list_formats + +2008.05.13.135251 [1771] +libisoburn/isoburn.h +libisoburn/isoburn.c +libisoburn/isofs_wrap.c +libisoburn/burn_wrap.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Corrected strange behavior with non-ISO images on overwriteable media + +2008.05.13.153837 [1772] +xorriso/xorrisoburn.c +Prepared Xorriso_get_profile() for potential call without flag bit1 + +2008.05.13.180624 [1773] +xorriso/xorrisoburn.c +Handled -list_format with non MMC drives + +2008.05.13.180912 [1774] +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorriso.1 +Eat up leading dashes with command options, convert inner dashes to underscores + +------------------------------------ cycle - xorriso-0.1.5 - 2008.05.13.180912 +* New -blank and -format modes as_needed +* New option -list_formats + +2008.05.14.114548 [1775] +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New -format types by_index and fast_by_index + +2008.05.14.173201 [1779] +configure.ac +libisoburn/libisoburn.h +Required libburn version is now 0.4.7 (because of DVD-RAM BD-RE bug fix) + +2008.05.14.173430 [1780] +xorriso/xorrisoburn.c +Automatic fast format on attempt to write to unformatted DVD-RAM or BD-RE + +2008.05.14.174846 [1781] +xorriso/xorriso_private.h +Uploaded forgotten enhancements + +2008.05.15.092028 [1783] +xorriso/xorriso.c +Enabled a pacifier for compare_r + +2008.05.15.150041 [1784] +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +xorriso/xorriso_eng.html +New options -map and -map_single + +2008.05.15.192118 [1785] +xorriso/xorriso.c +Bug fix: -update_r and others did not work properly with relative paths + +------------------------------------ cycle - xorriso-0.1.5 - +* New options -map and -map_single +* Bug fix: -update_r and others did not work properly with relative paths + + +2008.05.17.162753 [1794] +xorriso/xorriso.c +xorriso/xorrisoburn.c +Corrected ugly message with -update_r and root directory + +2008.05.17.170001 [1796] +configure.ac +README +libisoburn/libisoburn.h +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +Version leap to 0.1.6, requiring libburn-0.4.8 now + +2008.05.18.070001 [1797] +xorriso/xorriso.c +xorriso/xorrisoburn.c +Bug fix: -findi operated on nodes which ceased existence shortly before + +18 May 2008 [1799] +xorriso/changelog.txt +Documented changes and release timestamp + +---------------------------------- release - xorriso-0.1.6 - 2008.05.18.070001 +* New option -error_behavior with a first occasion 'image_loading' +* New options -not_paths, -not_leaf, -not_list, -not_mgt, -as mkisofs -m +* Emulated TOC on overwriteable media +* New TOC layout with volume id and sbsector= +* New option -rom_toc_scan +* New option -load session|track|sbsector|volid +* Now depending on libburn-0.4.8 +* New -blank and -format modes as_needed +* New option -list_formats +* New options -map and -map_single +* Bug fix: -update_r and others did not work properly with relative paths +* Bug fix: -findi operated on nodes which ceased existence shortly before + + +2008.05.18.082208 [1798] +xorriso/xorriso.c +xorriso/xorrisoburn.c +Bug fix: -findi operated on nodes which ceased existence shortly before + +2008.05.18.084729 [1800] +configure.ac +README +libisoburn/libisoburn.h +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +xorriso/changelog.txt +Version leap to 0.1.7, requiring libburn-0.4.8 now + +------------------------------------ cycle - xorriso-0.1.7 - 2008.05.18.084729 + +2008.05.20.075142 [1804] +xorriso/xorriso.c +Making Xorriso_prescan_args() safe against misunderstandings + +2008.05.22.192618 [1808] +xorriso/xorriso.h +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +First experiments of osirrox ISO-to-disk copying + +2008.05.22.192737 [1809] +libisoburn/data_source.c +Removed outdated code branch + +2008.05.22.210835 [1810] +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New options -osirrox and -cpx + +2008.05.24.092546 [1812] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Enabled osirrox of more file types, curbed with device files + +2008.05.24.092853 [1813] +libisoburn/isoburn.c +Bug fix: modifying to overwriteable target yielded unmountable results + +------------------------------------ cycle - xorriso-0.1.7 - 2008.05.24.092853 +* Bug fix: Modifying to overwriteable target yielded unmountable results +* New options -osirrox and -cpx + + +2008.05.24.170109 [1814] +xorriso/xorriso.c +xorriso/xorrisoburn.c +Some polishing with -cpx + +26 May 2008 [1815] +xorriso/configure_ac.txt +standalone version switch to libisofs-0.6.5 + +2008.05.26.181210 [1816] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +Improved access permission restauration by osirrox + +2008.05.27.201513 [1817] +xorriso/xorriso.h +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +xorriso/xorriso_eng.html +New option -stream_recording + +2008.05.31.174045 [1819] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Implemented concatenation of split files during -cpx + +------------------------------------ cycle - xorriso-0.1.7 - 2008.05.31.174045 +* New option -stream_recording + +2008.06.01.134322 [1820] +xorriso/xorrisoburn.c +Reacted on harmless compiler warning + +2008.06.01.145038 [1821] +xorriso/configure_ac.txt +standalone version switch to libisofs-0.6.6 + +2008.06.01.145155 [1822] +configure.ac +libisoburn/libisoburn.h +Switched requirements to libisofs-0.6.6 + +------------------------------------ cycle - xorriso-0.1.7 - 2008.06.01.145155 +* Bug fix: major,minor numbers of device files appeared as 0,1 in next session + + +2008.06.02.070301 [1824] +configure.ac +README +libisoburn/libisoburn.h +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +Version leap to 0.1.8 + +2 Jun 2008 [1825] +xorriso/changelog.txt +Documented changes and release timestamp + +---------------------------------- release - xorriso-0.1.8 - 2008.06.02.070301 +* Bug fix: Modifying to overwriteable target yielded unmountable results +* Bug fix: major,minor numbers of device files appeared as 0,1 in next session +* New option -stream_recording for full speed with DVD-RAM and BD-RE +* New options -osirrox and -cpx allow to extract single files from ISO image + + +2008.06.02.141334 [1826] +configure.ac +README +libisoburn/libisoburn.h +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +Version leap to 0.1.9 + +2 Jun 2008 [1827] +xorriso/changelog.txt +Documented changes and release timestamp + +2 Jun 2008 [1828] +xorriso/xorriso.1 +Beautified documentation of -osirrox + +------------------------------------ cycle - xorriso-0.1.9 - 2008.06.02.141334 + +5 Jun 2008 [1834] +xorriso/convert_man_to_html.sh +Beautified HTML man page + +2008.06.05.165023 [1835] +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New options -cpax, -cp_rx, -cp_rax to restore files and trees from ISO to disk + +2008.06.06.083432 [1839] +xorriso/xorriso.c +Bug fix: -chmod unintentionally performed o-x as first operation + +2008.06.06.103735 [1840] +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Fine tuning of directory attribute copying with -cp_rx + + +------------------------------------ cycle - xorriso-0.1.9 - +* New options -cpax, -cp_rx, -cp_rax to restore files and trees from ISO to disk +* Bug fix: -chmod unintentionally performed o-x as first operation + + +2008.06.09.134432 [1841] +xorriso/xorriso.h +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +Allowing to restore from image with pending changes + +2008.06.09.165735 [1842] +xorriso/xorriso.c +xorriso/xorrisoburn.c +Removed some outdated code parts + +2008.06.10.094304 [1844] +libisoburn/isoburn.c +libisoburn/burn_wrap.c +Removed outdated code parts + +2008.06.10.100231 [1845] +xorriso/xorrisoburn.c +Removed outdated code parts + +2008.06.11.131607 [1846] +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Proper handling of restore overwrite situations with directories and softlinks + +------------------------------------ cycle - xorriso-0.1.9 - 2008.06.11.131607 + +2008.06.12.112644 [1847] +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Corrections about restoring of directories + +------------------------------------ cycle - xorriso-0.1.9 - 2008.06.12.112644 + +2008.06.13.151630 [1848] +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -paste_in + +2008.06.14.104745 [1849] +xorriso/xorriso.c +xorriso/xorriso.1 +xorriso/xorriso_eng.html +New options -extract and -extract_single + +14 Jun 2008 [1850] +xorriso/convert_man_to_html.sh +Beautification of HTML man page + +2008.06.14.140459 [1851] +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Correction about -extract / / + +2008.06.14.184512 [1854] +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorriso.1 +xorriso/convert_man_to_html.sh +Gave up the unusual parameter sequences of -extract and -paste_in + +------------------------------------ cycle - xorriso-0.1.9 - 2008.06.14.184512 +* New option -paste_in to copy ISO files into parts of disk files +* New option -extract restores with arguments of -map or -update_r + + +2008.06.17.121524 [1857] +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorriso.1 +New options -map_l, -compare_l, -update_l, -extract_l + +2008.06.17.133914 [1858] +xorriso/xorriso.c +Reacted on harmless compiler warning + +2008.06.17.170622 [1859] +xorriso/xorriso.c +xorriso/xorrisoburn.c +Fixed a bug about -update_l + +2008.06.18.132057 [1860] +libisoburn/isoburn.h +libisoburn/burn_wrap.c +Made -rom_toc_scan work on closed DVD-R in a DVD-ROM drive + +2008.06.18.161512 [1861] +libisoburn/libisoburn.h +libisoburn/isoburn.h +libisoburn/isoburn.c +libisoburn/isofs_wrap.c +libisoburn/burn_wrap.c +libisoburn/data_source.c +New API functions isoburn_preset_msgs_submit(), isoburn_set_msgs_submit() + +2008.06.18.161723 [1862] +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +Made use of isoburn_preset_msgs_submit() + +------------------------------------ cycle - xorriso-0.1.9 - 2008.06.18.161723 +* New options -map_l, -compare_l, -update_l, -extract_l +* New API functions isoburn_set_msgs_submit(), isoburn_drive_set_msgs_submit() + + +2008.06.18.192913 [1863] +libisoburn/burn_wrap.c +Improved pacifier with -rom_toc_scan + +2008.06.19.090436 [1864] +libisoburn/libisoburn.h +libisoburn/burn_wrap.c +xorriso/xorrisoburn.c +Renamed isoburn_*set_msgs_submit() and slightly changed meaning + +2008.06.19.092458 [1865] +libisoburn/burn_wrap.c +Corrected wrong size unit MB to kB in toc scan pacifier text + +2008.06.20.091647 [1866] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New -osirrox option auto_chmod_on + +------------------------------------ cycle - xorriso-0.1.9 - 2008.06.20.091647 + + +2008.06.20.164105 [1867] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +Fixed several bugs with restore operations + +2008.06.21.180701 [1870] +xorriso/xorriso.1 +Corrected mistake in xorriso man page + +------------------------------------ cycle - xorriso-0.1.9 - 2008.06.21.180701 + +2008.06.22.080000 [1872] +xorriso/xorriso.c +Removed duplicated help text snippet + +2008.06.22.090001 [1873] +configure.ac +README +libisoburn/libisoburn.h +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +Version leap to 0.2.0 + +22 Jun 2008 [1874] +xorriso/changelog.txt +Documented changes and release timestamp + +---------------------------------- release - xorriso-0.2.0 - 2008.06.22.090001 +* Bug fix: -chmod unintentionally performed o-x as first operation +* New options -cpax, -cp_rx, -cp_rax to restore files and trees from ISO to disk +* New option -extract restores with arguments of -map or -update_r +* New option -paste_in to copy ISO files into parts of disk files +* New options -map_l, -compare_l, -update_l, -extract_l +* New API functions isoburn_set_msgs_submit(), isoburn_drive_set_msgs_submit() + +2008.06.22.111236 [1875] +xorriso/xorriso.c +Removed duplicated help text snippet + +2008.06.22.135202 [1876] +configure.ac +README +libisoburn/libisoburn.h +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +Version leap to 0.2.1 + +22 Jun 2008 [1877] +xorriso/changelog.txt +Documented changes and release timestamp + +------------------------------------ cycle - xorriso-0.2.1 - 2008.06.22.135202 + + +2008.06.27.124201 [1880] +xorriso/xorrisoburn.c +Bug fix: -as cdrecord -atip falsely announced overwriteable DVD-RW to sdvdbackup + +2008.06.27.130235 [1881] +xorriso/xorriso.c +Extended -as cdrecord blank= by blank type format_overwrite + +------------------------------------ cycle - xorriso-0.2.1 - 2008.06.27.130235 + + +2008.07.03.133023 [1882] +xorriso/xorriso.c +Flushing stdout after each result text to deconfuse stdout/stderr with SSH + +2008.07.04.070001 [1884] +xorriso/xorriso.c +Supporting option -as cdrecord -waiti + +2008.07.05.132528 [1885] +libisoburn/libisoburn.h +libisoburn/isoburn.h +libisoburn/isoburn.c +libisoburn/isofs_wrap.c +libisoburn/burn_wrap.c +libisoburn/data_source.c +New API function isoburn_prepare_blind_grow() for -as mkisofs -multi + +2008.07.05.133721 [1886] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -grow_blindly + +2008.07.05.180241 [1887] +libisoburn/isoburn.c +Fixed a bug with -grow_blindly to overwriteable media + +2008.07.05.182424 [1888] +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorriso.1 +New options -C and -M for -as mkisofs + +2008.07.05.184434 [1889] +xorriso/xorriso.c +Cared for a peculiarity of growisofs when using mkisofs -C + +5 Jul 2008 [1890] +xorriso/xorriso_eng.html +Updated xorriso homepage + +------------------------------------ cycle - xorriso-0.2.1 - 2008.07.05.184434 +* New API function isoburn_prepare_blind_grow() +* New option -grow_blindly +* New options -C and -M for -as mkisofs emulation + + +2008.07.06.110336 [1891] +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +Improved effective drive address with -as mkisofs -M + +2008.07.07.095531 [1892] +xorriso/xorriso.c +Fixed bug about -as mkisofs without -C + +2008.07.07.102941 [1893] +xorriso/xorriso.h +xorriso/xorriso_private.h +xorriso/xorriso.c +Semi-permanent emulation by start names xorrisofs,genisofs,mkisofs,genioimage + +------------------------------------ cycle - xorriso-0.2.1 - 2008.07.07.102941 + +2008.07.07.150241 [1894] +xorriso/xorriso.c +Correction about -as mkisofs -C if already an input device was set + +2008.07.07.150337 [1895] +libisoburn/isoburn.c +Correction about isoburn_igopt_get_effective_lba() with blind growing + +7 Jul 2008 [1896] +xorriso/xorriso.1 +Clarification about -grow_blindly predicted_nwa + +2008.07.07.150337 [1897] +xorriso/xorriso.c +xorriso/xorriso.1 +Made leafname triggered emulation more similar to -as emulation + +2008.07.08.092732 [1898] +Makefile.am +README +xorriso/xorriso_makefile_am.txt +xorriso/README +Installing softlinks xorrisofs and osirrox pointing to the xorriso binary + +2008.07.08.102622 [1899] +xorriso/xorriso_private.h +Header file forgotten with rev 1897 + +2008.07.08.132054 [1900] +xorriso/xorriso.c +xorriso/xorrisoburn.c +Avoided misleading message about emptied ISO image during -as mkisofs -C + +8 Jul 2008 [1901] +xorriso/xorriso_eng.html +Documented newest progress + +------------------------------------ cycle - xorriso-0.2.1 - 2008.07.08.132054 +* Can serve growisofs if started as xorrisofs, genisofs, mkisofs, genisoimage +* make install creates xorriso aliases as symbolic links: osirrox, xorrisofs + +2008.07.09.055133 [1901] +xorriso/xorriso.c +Avoided to use MMC code with -as mkisofs -M by prepending stdio: to address + +2008.07.09.055133 [1902] +xorriso/xorriso.h +xorriso/xorriso.c +Fixed bug with -as mkisofs -x and pattern expansion + +------------------------------------ cycle - xorriso-0.2.1 - 2008.07.09.055133 + + +2008.07.09.155540 [1903] +Makefile.am +xorriso/xorriso_private.h ++ xorriso/xorriso_buildstamp.h ++ xorriso/xorriso_buildstamp_none.h +xorriso/xorriso_makefile_am.txt +xorriso/make_xorriso_standalone.sh +Opportunity to generate build timestamp via make buildstamped + +9 Jul 2008 [1904] +xorriso/xorriso_makefile_am.txt +Completed (unused) dist rule of standalone-xorriso + +2008.07.10.141731 [1905] +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Enabled -multi and -msinfo with -as cdrecord + +2008.07.10.141913 [1906] +libisoburn/libisoburn.h +Small correction in API introduction text + +2008.07.10.144535 [1907] +xorriso/xorriso_private.h +Header file forgotten with rev 1903 + +2008.07.10.162809 [1908] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorriso.1 +cdrecord emulation by start names xorrecord, cdrecord, wodim, cdrskin + +2008.07.10.164015 [1909] +xorriso/xorriso.c +Reacted on compiler warning + +2008.07.10.164412 [1910] +Makefile.am +README +xorriso/xorriso_makefile_am.txt +xorriso/README +Installing softlink xorrecord pointing to the xorriso binary + +10 Jul 2008 [1911] +xorriso/xorriso.1 +xorriso/xorriso_eng.html +xorriso/convert_man_to_html.sh +Some documentation updates + +------------------------------------ cycle - xorriso-0.2.1 - 2008.07.10.164412 +* New options -multi and -msinfo for -as cdrecord emulation +* make install creates xorriso alias as symbolic link: xorrecord + + +2008.07.12.181846 [1912] +libisoburn/libisoburn.h +libisoburn/burn_wrap.c +New info mode 2 with isoburn_read_iso_head() + +2008.07.12.184833 [1913] +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New options --grow_overwriteable_iso and write_start_address= with -as cdrecord + +2008.07.14.114515 [1918] +libisoburn/libisoburn.h +Required libburn version is now 0.4.9 + +2008.07.14.114613 [1919] +configure.ac +Did LT_CURRENT++, LT_AGE++ which was forgotten with revision 1885 + +2008.07.14.120527 [1920] +libisoburn/libisoburn.h +libisoburn/burn_wrap.c +New flag options with isoburn_read_iso_head() + +2008.07.14.125133 [1921] +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -isosize with -as cdrecord + +14 Jul 2008 [1923] +xorriso/convert_man_to_html.sh +Small correction with a sed expression + +2008.07.15.063040 [1924] +xorriso/xorriso_makefile_am.txt +Generating automatic build timestamp + +2008.07.15.121754 [1925] +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option tsize= with -as cdrecord + +------------------------------------ cycle - xorriso-0.2.1 - 2008.07.15.121754 +* New options --grow_overwriteable_iso and write_start_address= with -as cdrecord +* New options -isosize and tsize= with -as cdrecord + + +2008.07.16.130711 [1933] +xorriso/xorriso.h +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -pacifier, more compatible pacifier with -as mkisofs + +2008.07.16.130758 [1934] +xorriso/configure_ac.txt +Updated xorriso standalone configure.ac version number BURN_*_VERSION + +2008.07.16.130841 [1935] +libisoburn/libisoburn.h +Required libburn version is now 0.5.0 + +2008.07.16.131110 [1936] +configure.ac +Required libburn version is now 0.5.0 + +2008.07.16.140043 [1937] +xorriso/xorriso.c +xorriso/xorriso.1 +Recognizing "b" as speed factor for BD media + +------------------------------------ cycle - xorriso-0.2.1 - 2008.07.16.140043 +* New option -pacifier, more compatible pacifier with -as mkisofs + +2008.07.17.110812 [1939] +libisoburn/libisoburn.h +libisoburn/burn_wrap.c +Ability to emulate a featured bug with mkisofs -C : read 16 block too early + +2008.07.17.111411 [1940] +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Rectified usage of original xorriso options underneath growisofs + +2008.07.17.183024 [1941] +libisoburn/burn_wrap.c +Recognizing growisofs follow-up sessions on xorriso overwriteables + +2008.07.17.184520 [1942] +libisoburn/burn_wrap.c +xorriso/xorriso.c +xorriso/xorrisoburn.c +Removed MULTI construction site remarks + +------------------------------------ cycle - xorriso-0.2.1 - 2008.07.17.184520 + + +2008.07.18.120001 [1944] +configure.ac +README +libisoburn/libisoburn.h +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt + +18 Jul 2008 [1946] +README +xorriso/README +Corrected outdated statement about minimum library requirements + + +---------------------------------- release - xorriso-0.2.2 - 2008.07.18.120001 +* New API function isoburn_prepare_blind_grow() +* New option -grow_blindly +* Options -C and -M for -as mkisofs emulation +* Can serve growisofs if started as xorrisofs, genisofs, mkisofs, genisoimage +* make install creates aliases as symbolic links: osirrox, xorrisofs, xorrecord +* Options for -as cdrecord emulation: -multi, -msinfo, -isosize, tsize, + --grow_overwriteable_iso, write_start_address, +* New option -pacifier, more compatible pacifier with -as mkisofs + + +2008.07.18.135540 [1947] +configure.ac +README +libisoburn/libisoburn.h +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +xorriso/changelog.txt +Version leap to 0.2.3 + +------------------------------------ cycle - xorriso-0.2.3 - 2008.07.18.135540 + + +2008.07.19.113048 [1949] +Makefile.am +xorriso/compile_xorriso.sh +Introduced automatic buildstamp generation for dynamic library version + +2008.07.21.155324 [1950] +Makefile.am +xorriso/xorriso_makefile_am.txt +Reacting on ticket 138 by stick, revoked buildstamp due to ugly make install + +2008.07.21.161826 [1951] +Makefile.am +xorriso/xorriso_makefile_am.txt +Used quotation marks as does ./bootstrap when generating Makefile.in + +------------------------------------ cycle - xorriso-0.2.3 - 2008.07.21.161826 +* Bug fix: Variable DESTDIR was not properly respected during make install + + +2008.07.23.080001 [xorriso-0.2.2.pl01] +Makefile.in +xorriso/xorriso_timestamp.h +xorriso/changelog.txt +* Bug fix: external make variable DESTDIR was not used by xorriso link creation + +------------------------------- patch - xorriso-0.2.2.pl01 - 2008.07.23.080001 +* Bug fix: Variable DESTDIR was not properly respected during make install + + +2008.07.26.075027 [1953] +libisoburn/burn_wrap.c +Producing on overwriteables a partial TOC up to first damaged superblock + +2008.08.01.101355 [1955] +xorriso/xorrisoburn.c +Better finish time estimation with -pacifier mkisofs + +2008.08.01.141210 [1956] +xorriso/xorrisoburn.c +Better finish time estimation with -pacifier mkisofs + +2008.08.06.143825 [1967] +xorriso/xorriso_private.h +Removed obsolete type definition + +2008.08.06.143922 [1968] +xorriso/xorrisoburn.c +Removed obsolete function + +2008.08.07.112529 [1972] +xorriso/xorriso.c +Minor changes around display of time and byte counts + +2008.08.09.160515 [1977] +configure.ac +libisoburn/libisoburn.h +Demanding libburn-0.5.1 now + +2008.08.09.160947 [1978] +libisoburn/burn_wrap.c +Create emulated toc entry for simple ISO session on overwriteable media + +2008.08.09.161311 [1979] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +Evaluating readability of media + +2008.08.11.201604 [1980] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +Adapted media evaluation to CD peculiarities + +2008.08.13.185434 [1981] +libisoburn/libisoburn.h +Corrected documentation of isoburn_disc_get_msc1() + +2008.08.13.190704 [1982] +xorriso/xorriso.h +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +New capability to redirect program output used for toc in sector map file + +2008.08.14.220520 [1983] +libisoburn/burn_wrap.c +Changed wrong update message from MB to kB + +2008.08.14.221412 [1984] +xorriso/xorriso.h +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -check_media + +2008.08.15.102849 [1985] +xorriso/xorriso.h +xorriso/xorriso_private.h +xorriso/xorriso.c +Allowed independent redirecton of result and info channel + +2008.08.15.155421 [1986] +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Enabled printing of sector bitmaps by use=sector_map + +15 Aug 2008 [1987] +xorriso/xorriso_eng.html +Mentioned progress of development version + +2008.08.17.220043 [1988] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +-find tests -damaged and -lba_range, new -find action report_damage + +2008.08.17.221350 [1989] +xorriso/xorrisoburn.c +xorriso/xorriso_eng.html +Reacted on compiler warning + +------------------------------------ cycle - xorriso-0.2.3 - +* Included libburn has enhanced Linux drive access and listing code +* New option -check_media +* New -find test -damaged, new -find action "report_damage" + + +2008.08.18.134140 [1990] +xorriso/xorrisoburn.c +xorriso/README +xorriso/xorriso.1 +New -find action report_lba + +2008.08.20.101410 [2000] +xorriso/configure_ac.txt +Adopted to new libburn version 0.5.3 + +2008.08.20.121008 [2002] +libisoburn/libisoburn.h +configure.ac +Demanding libburn-0.5.2 now + +2008.08.20.181734 [2003] +xorriso/xorrisoburn.c +Made -check_media process first 32 blocks of a multi-session overwriteable + +2008.08.21.070602 [2004] +xorriso/xorriso.c +Synced -lsl display of major,minor numbers with /usr/include/sys/sysmacros.h + +2008.08.22.231051 [2005] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New -check_media option -patch_lba0= + +2008.08.24.100552 [2007] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +xorriso/xorriso_eng.html +New -error_behavior behavior occasion "file_extraction" + +2008.08.24.124424 [2008] +xorriso/xorrisoburn.c +Fixed a bug with -check_media use=outdev + +2008.08.24.125257 [2009] +xorriso/xorrisoburn.c +Reacted on compiler warning + +------------------------------------ cycle - xorriso-0.2.3 - 2008.08.24.125257 +* New -find action "report_lba" +* New -error_behavior behavior occasion "file_extraction" + + +2008.08.24.160001 [2011] +configure.ac +README +libisoburn/libisoburn.h +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +Version leap to 0.2.4 + +24 Aug 2008 [2012] +xorriso/changelog.txt +Documented changes and release timestamp + +24 Aug 2008 [2013] +configure.ac +Corrected ISOBURN_MICRO_VERSION + +---------------------------------- release - xorriso-0.2.4 - 2008.08.24.160001 +* Included libburn has enhanced Linux drive access and listing code +* New option -check_media +* New -find test -damaged, new -find actions "report_damage", "report_lba" +* New -error_behavior occasion "file_extraction" + + +2008.08.24.173217 [2014] +configure.ac +README +libisoburn/libisoburn.h +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +Version leap to 0.2.5 + +24 Aug 2008 [2015] +xorriso/changelog.txt +Documented changes and release timestamp + +------------------------------------ cycle - xorriso-0.2.5 - 2008.08.24.173217 + +26 Aug 2008 [2017] +xorriso/convert_man_to_html.sh +Adjusted HTML generator to recent man page changes + +2008.08.26.163254 [2018] +libisoburn/libisoburn.h +libisoburn/data_source.c +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/configure_ac.txt +Adopting next development step of libisofs + +26 Aug 2008 [2019] +xorriso/xorriso.1 +Adjusted man page statements about file size limits + +2008.08.27.121211 [2020] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -file_size_limit, -as mkisofs now supports -iso-level 1 to 3 + +2008.08.27.122127 [2021] +xorriso/xorriso.c +Reacted on compiler warning + +------------------------------------ cycle - xorriso-0.2.5 - 2008.08.27.122127 +* Capability to insert and extract files far larger than 4 GB +* New option -file_size_limit, -as mkisofs now supports -iso-level 1 to 3 + + +27 Aug 2008 [2022] +xorriso/xorriso.1 +Corrected a typo in man page + +2008.09.02.164803 [2025] +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -extract_cut + +2008.09.03.143218 [2026] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New -error_behavior "file_extraction" behavior "best_effort" + +2008.09.04.100158 [2027] +xorriso/xorriso.h +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -check_media_defaults + +------------------------------------ cycle - xorriso-0.2.5 - 2008.09.04.100158 +* New option -extract_cut +* New -error_behavior "file_extraction" behavior "best_effort" +* New option -check_media_defaults + + +2008.09.05.095344 [2028] +xorriso/xorriso_private.h +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -list_delimiter + +5 Sep 2008 [2029] +xorriso/xorriso_eng.html +Updated development feature list + +2008.09.05.114936 [2030] +xorriso/xorriso.c +-commit_eject, -alter_date, -alter_date_r, -pacifier, -prog_help had wrong argument count prediction + +5 Sep 2008 [2031] +xorriso/xorriso.1 +Documented forgotten option -publisher + +5 Sep 2008 [2032] +xorriso/xorriso_eng.html +xorriso/xorriso.1 +Minor documentation polishing + +------------------------------------ cycle - xorriso-0.2.5 - 2008.09.05.114936 +* New option -list_delimiter + + +6 Sep 2008 [2033] +xorriso/xorriso_eng.html +xorriso/xorriso.1 +Documentation polishing + +2008.09.07.144714 [2034] +xorriso/xorrisoburn.c +Removed outdated alternative code for support of libisofs-0.6.6 + +2008.09.08.094748 [2035] +xorriso/xorriso.c +xorriso/xorrisoburn.c +Made use of new libisofs call iso_image_update_sizes() + +2008.09.08.121548 [2036] +xorriso/xorrisoburn.c +Bug fix: -format full did not re-format already formatted DVD+RW + +2008.09.09.082406 [2037] +xorriso/xorrisoburn.c +Smoothened time estimation with pacifier mkisofs style + +9 Sep 2008 [2038] +xorriso/xorriso_eng.html +Updated web page + +------------------------------------ cycle - xorriso-0.2.5 - 2008.09.09.082406 +* Bug fix: -format full did not re-format already formatted DVD+RW + + +2008.09.11.114227 [2040] +xorriso/xorrisoburn.c +Issuing message at begin of image loading + +2008.09.13.204455 [2047] +xorriso/xorrisoburn.c +Correction about -check_media report and message about image loading + +2008.09.16.060427 [2053] +xorriso/xorriso.c +xorriso/xorrisoburn.c +Corrected pacifier text (Ticket 141) + +2008.09.16.185206 [2054] +xorriso/xorriso_private.h +xorriso/xorriso.1 +Corrected falsely computed default setting of -file_size_limit + +2008.09.17.193824 [2056] +xorriso/xorrisoburn.c +Corrected message duplication about emulated sessions on overwriteable media + +2008.09.19.090619 [2057] [2058] +xorriso/configure_ac.txt +standalone version switch to libisofs-0.6.8 + +19 Sep 2008 [2059] +xorriso/xorriso.1 +Small change in man page + +2008.09.19.104424 [2060] +configure.ac +libisoburn/libisoburn.h +Switched requirements to libisofs-0.6.8 + +------------------------------------ cycle - xorriso-0.2.5 - 2008.09.19.104424 + + +2008.09.19.122656 [2061] +xorriso/xorrisoburn.c +Changed WARNING about non-writeable media to NOTE severity of blank messages + + +2008.09.19.180001 [2066] +configure.ac +README +libisoburn/libisoburn.h +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +Version leap to 0.2.6 + +20 Sep 2008 [2067] +xorriso/changelog.txt +Documented changes and release timestamp + +---------------------------------- release - xorriso-0.2.6 - 2008.09.19.180001 +* Capability to insert and extract files far larger than 4 GB +* New option -file_size_limit, -as mkisofs now supports -iso-level 1 to 3 +* New option -extract_cut +* New -error_behavior "file_extraction" behavior "best_effort" +* New option -check_media_defaults +* New option -list_delimiter +* Bug fix: -format full did not re-format already formatted DVD+RW + + +2008.09.20.093140 [2068] +configure.ac +README +libisoburn/libisoburn.h +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +Version leap to 0.2.7 + +20 Sep 2008 [2069] +xorriso/changelog.txt +Documented changes and release timestamp + +------------------------------------ cycle - xorriso-0.2.7 - 2008.09.20.093140 + +2008.09.24.155424 [2077] +xorriso/xorrisoburn.c +Trying to get pacifiers of simultaneously running emulations into sync + +2008.09.26.120934 [2082] +xorriso/xorriso.c +Bug fix: -as mkisofs -iso-level was accused to be an unknown option + +2008.09.26.161331 [2083] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +A first attempt on making bootable ISO images + +2008.09.28.112850 [2084] +xorriso/configure_ac.txt +Standalone version switch to libisofs-0.6.9 (vreixoml 387) to avoid SIGSEGV + +2008.09.28.113256 [2085] +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +xorriso/convert_man_to_html.sh +xorriso/xorriso_eng.html +Made -boot_image isolinux activation obey -overwrite setting + +2008.09.30.102243 [2088] +libisoburn/libisoburn.h +Requiring libisofs-0.6.9 because of bug fixes with El Torito + +2008.09.30.102753 [2089] +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Adjustments about -boot_image after testing with various media types + +30 Sep 2008 [2090] +xorriso/xorriso_eng.html +Mentioned progress and bug fixes in 0.2.7 + +------------------------------------ cycle - xorriso-0.2.7 - 2008.09.30.102753 +* Bug fix: -as mkisofs -iso-level was accused to be an unknown option +* Ability to write and maintain bootable ISO images based on ISOLINUX + + +2008.09.30.174925 [2091] +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Small adjustments about -boot_image + +2008.10.02.092354 [2092] +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Small adjustments about -boot_image + +2008.10.02.092635 [2093] +xorriso/xorriso.c +Enabled -as cdrecord blank=as_needed + +2008.10.02.105442 [2094] +xorriso/README +xorriso/configure_ac.txt +Introduced xorriso-standalone ./configure option --disable-libreadline + +2008.10.02.110828 [2095] +README +xorriso/README +xorriso/configure_ac.txt +Fine tuning about ./configure option --disable-libreadline + +------------------------------------ cycle - xorriso-0.2.7 - 2008.10.02.110828 +* New ./configure option --disable-libreadline to make binary more portable + + +4 Oct 2008 [2099] +xorriso/convert_man_to_html.sh +xorriso/xorriso.1 +Relocated the El Torito paragraph in man xorriso + +2008.10.05.075432 [2101] +libisoburn/libisoburn.h +libisoburn/burn_wrap.c +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +-rom_toc_scan nonrom_off disables toc emulation on overwriteables + +2008.10.05.093703 [2105] +xorriso/xorrisoburn.c +Bug fix: Random target filenames with looping symbolic links + +2008.10.05.125046 [2109] +xorriso/configure_ac.txt +Adapted standalone BURN_*_VERSION to libburn 0.5.5 + +2008.10.05.125242 [2110] +configure.ac +libisoburn/libisoburn.h +libisoburn now demands libburn-0.5.4 + +------------------------------------ cycle - xorriso-0.2.7 - 2008.10.05.125242 +* Bug fix: -follow link attributed random target filenames to looping links + + +2008.10.06.114114 [2113] +xorriso/configure_ac.txt +Adapted standalone LIBISOFS_*_VERSION to libisofs 0.6.10 + +2008.10.06.114845 [2114] +configure.ac +libisoburn/libisoburn.h +libisoburn now demands libisofs-0.6.10 + +------------------------------------ cycle - xorriso-0.2.7 - 2008.10.06.114845 + + +7 Oct 2008 [2115] +xorriso/xorriso.1 +Polished man xorriso + +2008.10.08.135848 [2116] +xorriso/xorriso.c +xorriso/xorriso.1 +Changed newly introduced -rom_toc_scan nonrom_off to off:emul_off + +2008.10.09.145926 [2117] +configure.ac +README +Introduced libburn ./configure option --disable-libreadline + +9 Oct 2008 [2118] +xorriso/compile_xorriso.sh +Introduced xorriso development compiler script option -no_libreadline + +------------------------------------ cycle - xorriso-0.2.7 - 2008.10.09.145926 + + +2008.10.10.131102 [2119] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorriso.1 +Enabled dialog for multi-lines and newline characters in quotation marks + +2008.10.10.134020 [2120] +xorriso/xorriso.c +Polishing multi-line dialog + +2008.10.12.120001 [2122] +configure.ac +README +libisoburn/libisoburn.h +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +Version leap to 0.2.8 + +12 Oct 2008 [2123] +xorriso/changelog.txt +Documented changes and release timestamp + +---------------------------------- release - xorriso-0.2.8 - 2008.10.12.120001 +* Bug fix: -as mkisofs -iso-level was accused to be an unknown option +* Bug fix: -follow link attributed random target filenames to looping links +* Ability to write and maintain bootable ISO images based on ISOLINUX +* New ./configure option --disable-libreadline to make binary more portable + + +2008.10.12.133957 [2124] +configure.ac +README +libisoburn/libisoburn.h +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +Version leap to 0.2.9 + +12 Oct 2008 [2125] +xorriso/changelog.txt +Documented changes and release timestamp + +------------------------------------ cycle - xorriso-0.2.9 - 2008.10.12.133957 + + +15 Oct 2008 [2128] +xorriso/xorriso_eng.html +Corrected a typo in xorriso web page + +2008.10.15.182605 [2130] +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New options -quoted_path_list, -quoted_not_list. Multiline for -options_from_file + +2008.10.17.074953 [2131] +xorriso/xorriso_private.h +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorriso.1 +New option -backslash_codes for expressing weird file names + +2008.10.17.123308 [2132] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorriso.1 +Adjustments and documentation about -backslash_codes + +17 Oct 2008 [2133] +xorriso/xorriso_eng.html +Updated xorriso web page + +------------------------------------ cycle - xorriso-0.2.9 - 2008.10.17.123308 +* New options -quoted_path_list, -quoted_not_list +* New option -backslash_codes for weird file names and terminal safety + +18 Oct 2008 [2134] +xorriso/make_isohybrid_mbr.c +Exposed function make_isohybrid_mbr() for discussion + +19 Oct 2008 [2135] +xorriso/make_isohybrid_mbr.c +Corrected a bug in make_isohybrid_mbr() + +2008.10.19.172237 [2136] +xorriso/configure_ac.txt +xorriso/xorriso_makefile_am.txt +Adapted to libisofs 0.6.11 + +19 Oct 2008 [2137] +xorriso/compile_xorriso.sh +Adapted to libisofs 0.6.11 + +19 Oct 2008 [2138] +- xorriso/make_isohybrid_mbr.c +The make_isohybrid_mbr() function is now part of libisofs development + +2008.10.19.182512 [2139] +libisoburn/libisoburn.h +libisoburn now depends on libisofs-0.6.11 + +2008.10.20.180747 [2140] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Made use of new libisofs isohybrid capability + +------------------------------------ cycle - xorriso-0.2.9 - 2008.10.20.180747 +* Suitable ISOLINUX boot images are made alternatively bootable via MBR + + +21 Oct 2008 [2141] +xorriso/xorriso_eng.html +Mentioned isohybrid capability in xorriso homepage + +2008.10.21.112523 [2142] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +Implemented in xorriso provisory 1 MB alignement for MBR enhanced ISO images + +2008.10.21.123226 [2143] +xorriso/xorrisoburn.c +Showing a "Media summary:" with blank media + +------------------------------------ cycle - xorriso-0.2.9 - 2008.10.21.123226 + + +2008.10.22.110204 [2144] +xorriso/xorriso.c +xorriso/xorriso.1 +New options --quoted_path_list , isolinux_mbr= for -as mkisofs + +2008.10.22.201702 [2145] +xorriso/xorriso.1 +xorriso/xorrisoburn.c +Gave up automatic switch to -boot_image "isolinux" "patch" after writing + +------------------------------------ cycle - xorriso-0.2.9 - 2008.10.22.201702 + +2008.10.24.130124 [2146] +xorriso/xorrisoburn.c +Fixed image size aligment to 1 MB with follow-up sessions + +------------------------------------ cycle - xorriso-0.2.9 - 2008.10.24.130124 + + +2008.10.25.123133 [2147] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +Eventually reporting boot info with TOC of -indev, redirected drive aquiration TOC to info channel + +2008.10.25.170010 [2148] +xorriso/xorrisoburn.c +Fixed SIGSEGV introduced with previous revision + +2008.10.26.134421 [2149] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Introduced info option -boot_image "any" "show_status" + +2008.10.26.142422 [2150] +xorriso/xorrisoburn.c +Precautions against patching deleted boot images + +------------------------------------ cycle - xorriso-0.2.9 - 2008.10.26.142422 + + +2008.10.27.142720 [2151] +xorriso/xorrisoburn.c +Trying to recognize isohybrid MBR for "Boot record :" message + +------------------------------------ cycle - xorriso-0.2.9 - 2008.10.27.142720 + + +2008.10.30.110049 [2152] +xorriso/xorriso.c +Made -as mkisofs -path-list and --quoted_path_list switch pacifier mode + +2008.10.30.114313 [2153] +xorriso/xorriso.c +Enabled @ as indicator of UTC seconds in timestrings + +2008.11.03.115721 [2159] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +xorriso/convert_man_to_html.sh +New options -charset, -in_charset, -out_charset + +2008.11.04.162214 [2162] +xorriso/xorriso_private.h +xorriso/xorriso.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -application_id + +4 Nov 2008 [2163] +xorriso/xorriso_eng.html +Mentioned new options in xorriso homepage + +2008.11.06.183736 [2164] +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +New option -local_charset + +------------------------------------ cycle - xorriso-0.2.9 - 2008.11.06.183736 +* New options -charset, -in_charset, -out_charset +* New option -application_id +* New option -local_charset + + +2008.11.07.173315 [2170] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Copying -out_charset to -in_charset after -commit + +2008.11.07.201909 [2171] +xorriso/xorrisoburn.c +Removed some defunct code from xorrisoburn.c + +2008.11.09.102554 [2176] +xorriso/xorriso.c +Added a setlocale() call to xorriso main() + +------------------------------------ cycle - xorriso-0.2.9 - 2008.11.09.102554 +* Bug fix in libisofs: ISOLINUX boot images were not patched correctly + +2008.11.10.123332 [2177] +xorriso/xorrisoburn.c +Disabled experimental weight sorting with MBR generation + +2008.11.10.123713 [2178] +xorriso/xorriso.c +xorriso/xorriso.1 +Eventual backslash output conversion outside quotes for more terminal-safety + +11 Nov 2008 [2179] +xorriso/xorriso_eng.html +Updated xorriso home page + +------------------------------------ cycle - xorriso-0.2.9 - 2008.11.10.123713 + + +12 Nov 2008 [2190] +xorriso/configure_ac.txt +Version leap to libburn-0.5.7 + +2008.11.12.153437 [2192] +xorriso/xorriso.c +Added forgotten exit value registration to -return_with. Thanks to Steve Dodd. + +------------------------------------ cycle - xorriso-0.2.9 - 2008.11.12.153437 +* Bug fix: Forgot exit value registration to -return_with. Thanks to Steve Dodd. + + +15 Nov 2008 [2195] +xorriso/xorriso.1 +Took into respect that xorriso loads non-RR images + +2008.11.15.133724 [2196] +xorriso/xorriso.c +Adaptions to FreeBSD. Thanks to J.R. Oldroyd. + +2008.11.15.231831 [2198] +libisoburn/libisoburn.h +libisoburn/isoburn.h +libisoburn/isoburn.c +Introduced new relax flag isoburn_igopt_always_gmt + +2008.11.15.232058 [2199] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +Making use of new relax flag isoburn_igopt_always_gmt + +------------------------------------ cycle - xorriso-0.2.9 - 2008.11.18.110100 + +18 Nov 2008 [2204] +test/aaip.c +Demo of the emerging Arbitrary Attribute Interchange Protocol format + +18 Nov 2008 [2205] +README +xorriso/README +xorriso/xorriso.1 +xorriso/xorriso_eng.html +Mentioned FreeBSD peculiarities in our docs + +2008.11.21.160019 [2206] +libisoburn/libisoburn.h +libisoburn/isoburn.h +libisoburn/isoburn.c +Making use of experimental libisofs calls _rrip_version_1_10() _dir_rec_mtime() + +2008.11.21.160632 [2207] +xorriso/xorriso.h +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.h +xorriso/xorrisoburn.c +xorriso/xorriso.1 +xorriso/xorriso_eng.html +New option -relax_compliance + +22 Nov 2008 [2209] +- test/aaip.c +Revoked proposal AAIP 0.0 in favor of 0.2 which is nearly like RRIP field SL + + +------------------------------------ cycle - xorriso-0.2.9 - 2008.11.21.160632 + +26 Nov 2008 [2210] +xorriso/configure_ac.txt +Promoted standalone libisofs copy to 0.6.12 + +2008.11.26.174940 [2211] +xorriso/xorrisoburn.c +Disabled "Starting up libraries ..." message + +2008.11.26.180935 [2212] +xorriso/xorriso.c +Augmented version message by "and burn program" + +------------------------------------ cycle - xorriso-0.2.9 - 2008.11.26.180935 + + +2008.11.29.091030 [2216] +xorriso/xorriso.c +xorriso/xorrisoburn.c +xorriso/xorriso.1 +Renamed new option -relax_compliance to -compliance, added _off rules + +------------------------------------ cycle - xorriso-0.2.9 - 2008.11.29.091030 +* New option -compliance allows certain deviations from standards + + +2008.11.29.140837 [2219] +xorriso/xorrisoburn.c +Bug fix: -format as_needed did not recognize unformatted BD-RE + +2008.11.29.165843 [2220] +xorriso/xorriso_private.h +xorriso/xorriso.c +xorriso/xorrisoburn.c +Re-aquiring outdev after formatting and blanking already in xorrisoburn + +2008.11.29.214208 [2221] +xorriso/xorriso.c +New -as cdrecord option stream_recording=on|off + +2008.11.30.095007 [2222] +xorriso/xorrisoburn.c +Reporting BD speed units with pacifier rather than DVD units + +2008.11.30.123700 [2223] +xorriso/xorriso.c +Gave -as mkisofs problem handlers rather than to let it abort on any error + +2008.11.30.214121 [2224] +xorriso/xorriso.c +xorriso/xorrisoburn.c +Changed layout of xorriso style write pacifier line + +2008.12.01.110022 [2225] +xorriso/xorriso.c +xorriso/xorrisoburn.c +Removed outdated macro case Xorriso_fat_local_meM + +2008.12.01.122825 [2226] +xorriso/xorriso.c +Bug fix: disk patterns with relative addresses were not properly resolved + +1 Dec 2008 [2227] +xorriso/xorriso_eng.html +Updated list of bugfixes in xorriso home page + +------------------------------------ cycle - xorriso-0.2.9 - +* Bug fix: -format as_needed did not recognize unformatted BD-RE +* Bug fix: disk patterns with relative addresses were not properly resolved + + +1 Dec 2008 [2228] +Branching for libisoburn release 0.3.0 + +2008.12.01.200001 [2229] +configure.ac +README +libisoburn/libisoburn.h +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +Version leap to 0.3.0 + +1 Dec 2008 [2230] +xorriso/changelog.txt +Documented changes and release timestamp + +1 Dec 2008 [2231] +configure.ac +Corrected values of LIB*_REQUIRED + +---------------------------------- release - xorriso-0.3.0 - 2008.12.01.200001 + +* New options -quoted_path_list, -quoted_not_list +* New option -backslash_codes for weird file names and terminal safety +* New options -charset, -in_charset, -out_charset +* New option -local_charset allows to override locale +* New option -application_id +* New option -compliance allows certain deviations from standards +* Suitable ISOLINUX boot images are made alternatively bootable via an MBR +* Bug fix in libisofs: ISOLINUX boot images were not patched correctly +* Bug fix in libisofs: mkisofs images with empty files got damaged +* Bug fix: Forgot exit value registration to -return_with. Thanks to Steve Dodd. +* Bug fix: -format as_needed did not recognize unformatted BD-RE +* Bug fix: disk patterns with relative addresses were not properly resolved + + +2008.12.01.202911 [2232] +configure.ac +README +libisoburn/libisoburn.h +xorriso/README +xorriso/xorriso_timestamp.h +xorriso/xorriso_private.h +xorriso/xorrisoburn.h +xorriso/xorriso_eng.html +xorriso/make_xorriso_standalone.sh +xorriso/configure_ac.txt +Version leap to 0.3.1 + +1 Dec 2008 [] +xorriso/changelog.txt +Documented changes and release timestamp + +------------------------------------ cycle - xorriso-0.3.1 - +------------------------------------ cycle - xorriso-0.3.1 - + +=============================================================================== + TODO +=============================================================================== + +------------------------------------------------- bugs + + +------------------------------------------------- important + + +------------------------------------------------- development + +- -load option to ignore existing images + +- mount helper which takes arguments like -load + +- image sort weight control: + isoburn_igopt_set_sort_files iso_node_set_sort_weight + +- stream_recording for data blocks but not for superblock and directory trees + +- random access read and write option + +- option to patch the mount image size and location on overwriteables + +- change -check_media what=disc to libburn disc rather than libisoburn + (seems to need new API capabilities of libburn) + +??? Clarify handling of links in ISO and on disk during restore + +> Relative addressing and pattern matching : + iso_rr_pattern on + cd /u/FERTIG + lsd nonexist/.. + +- perform any long lasting operation in separate threads while + the main thread cares for user and message queues. + +- Introduce an interrupt key for dialog + >>> but how without disturbing readline ? + +- regularly do valgrind check for memory leaks + +- ??? http://scan.coverity.com/faq.html + +- ??? curb depth of tree traversal recursion + +- make xorrisoburn.c leaner + +- eject a not yet aquired device (e.g. after modifying commit) + +- -cd[ix] and pattern + +- memory curb for image model + + +> Make transactional the tree deletions meant for replacing + + +------------------------------------------------- libisofs wishes + +------ problem fixes : + +<<< done in 0.6.12 +ts A81106 : removed apostrophe and dangerous text display + +<<< done in 0.6.12 +ts A81107 : option to override the local charset name + +<<< done in libisofs-0.6.10.pl01 +<<< done in 0.6.12 +ts A81108 : ticket 145, delaying boot image patching until new LBA is known + In ecma119_image_new() get move ElTorito ->compute_data_blocks() + behind all other ->compute_data_blocks() in order to have the + correct future LBA of isolinux.bin in patch_boot_image() as + t->bootimg->sections[0].block. + +<<< done in libisofs-0.6.10.pl01 +<<< done in 0.6.12 +ts A81112 : ticket 142 by jr, porting to FreeBSD + +<<< done in 0.6.12 +ts A81113 : emphasized in the API docs the fact that + iso_image_create_burn_source() starts image generation + mentioned the FreeBSD timezone bug with API docs of + iso_write_opts_set_always_gmt() + +<<< done in libisofs-0.6.10.pl01 +<<< done in 0.6.12 +ts A81118 : ticket 144: non-unique inode numbers with non-RRIP-1.12 images + +<<< done in 0.6.12 +ts A81120 : Option to use of old fashioned RRIP-1.10 rather than RRIP-1.12 + API function iso_write_opts_set_rrip_version_1_10() + This can be disabled by disabling A81114. +<<< done in 0.6.12 +ts A81114 : #ifdef for producing old ER signature "RRIP_1991A" + +<<< done in 0.6.12 +ts A81121 : Option to store in ECMA-119 timestamp mtime of source + +<<< done in 0.6.12 +ts A81125 : Version switch to 0.6.12 , libisofs-6.8.0.so + +<<< done in 0.6.12 +ts A81125.2 : Described need to pad isohybrid to full MB. + Removed compiler warning about isohybrid FIXME. + +<<< done in 0.6.12 +ts A81125.3 : More apostrophes removed from messages + +<<< done in 0.6.12 +ts A81125.4 : Removed surplus line from rrip_add_PN(). + It was introduced with the FreeBSD port. + +<<< done in 0.6.12 +ts A81125.5 : Added a missing change for RRIP-1.10 option to rrip_calc_len() + +<<< done in 0.6.12 +ts A81125.6 0.6.12 : Described license situation of make_isohybrid_mbr.c + + + + +>>> make ISO_FILENAME_WRONG_CHARSET a warning rather than a HINT + +>>> Fix the potential bug with read_rr_PX() seeing length 36 in a IEEE_1282 + + +- the error handling system should be comprehensively documented + and eventually rectified where needed. + +------ feature enhancements : + +- Optional performing of ISO hybrid patch for USB and other pseudo hard disks + http://www.sfr-fresh.com/linux/misc/syslinux-3.72.tar.gz:a/syslinux-3.72/utils/isohybrid + http://syslinux.zytor.com/archives/2008-October/010869.html + >>> this is completed if above image patching bug is fixed + +- Relax option to make the ECMA-119 9.1.5 timestamp reflect the mtime + of the source file rather than the creation time of the image. + mkisofs does it so and circumvents OS bugs. + +- A repeatable shell command as origin ("disk_file") + of a regular file in the ISO image. + +- API: iso_stream_get_dev_ino() to get the source side dev_t and ino_t + +- API: iso_cout_stream_get_params(stream, &path, &offset, &size) + +- Image checksum tag in the last data blocks of an image. + A data file entry should point to that block. + +- Re-use unchanged sub trees in the previous image in order to + reduce the session overhead. + +- Memorize the character set name for file names in the ISO image + + +------ extended attribute stunts: Not visible for mount but for libisofs + +- ticket 136 and http://libburnia-project.org/wiki/AAIP + ACLs + man attr(5) extended attributes + +- file checksums + + +=============================================================================== + This is the dirty end of the todo list. + The recent changelog entries are above the headline "TODO". +=============================================================================== diff --git a/libisoburn/branches/ZeroThreeTwo/xorriso/compile_xorriso.sh b/libisoburn/branches/ZeroThreeTwo/xorriso/compile_xorriso.sh new file mode 100755 index 00000000..0d978cda --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/xorriso/compile_xorriso.sh @@ -0,0 +1,164 @@ +#!/bin/sh + +# compile_xorriso.sh +# Copyright 2005 - 2008 Thomas Schmitt, scdbackup@gmx.net, GPL +# +# Not intended for general use in production installations ! +# Rather use: ./bootstrap ; ./configure ; make +# +# This is a development tool which expects a special setup of directories. +# It is to be executed in a common parent of the directories given with +# $isofs $isoburn $burn $xorr + +isofs=./nglibisofs-develop/libisofs +burn=./libburn-develop/libburn +isoburn=./libisoburn-develop/libisoburn +xorr=./libisoburn-develop/xorriso + +debug_opts="-O2" +def_opts= +largefile_opts="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1" +do_strip=0 +static_opts= +warn_opts="-Wall" +nglibisofs=1 +def_libreadline="-DXorriso_with_readlinE" +link_libreadline="-lreadline" + +for i in "$@" +do + if test "$i" = "-do_diet" + then + def_opts="$def_opts -DXorriso_no_helP" + warn_opts= + elif test "$i" = "-do_strip" + then + do_strip=1 + elif test "$i" = "-g" + then + debug_opts="-g -O0" + elif test "$i" = "-no_libreadline" + then + def_libreadline="" + link_libreadline="" + elif test "$i" = "-help" -o "$i" = "--help" -o "$i" = "-h" + then + echo \ + "$xorr/compile_xorriso.sh : to be executed above top level directories" + echo "Options:" + echo " -no_libreadline do not compile for and link with libreadline." + 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 + +libisofs= +libisofs="$libisofs $isofs"/buffer.o +libisofs="$libisofs $isofs"/builder.o +libisofs="$libisofs $isofs"/data_source.o +libisofs="$libisofs $isofs"/ecma119.o +libisofs="$libisofs $isofs"/ecma119_tree.o +libisofs="$libisofs $isofs"/eltorito.o +libisofs="$libisofs $isofs"/filesrc.o +libisofs="$libisofs $isofs"/fs_image.o +libisofs="$libisofs $isofs"/fs_local.o +libisofs="$libisofs $isofs"/fsource.o +libisofs="$libisofs $isofs"/image.o +libisofs="$libisofs $isofs"/iso1999.o +libisofs="$libisofs $isofs"/joliet.o +libisofs="$libisofs $isofs"/libiso_msgs.o +libisofs="$libisofs $isofs"/messages.o +libisofs="$libisofs $isofs"/node.o +libisofs="$libisofs $isofs"/rockridge.o +libisofs="$libisofs $isofs"/rockridge_read.o +libisofs="$libisofs $isofs"/stream.o +libisofs="$libisofs $isofs"/tree.o +libisofs="$libisofs $isofs"/util.o +libisofs="$libisofs $isofs"/util_htable.o +libisofs="$libisofs $isofs"/util_rbtree.o +libisofs="$libisofs $isofs"/system_area.o +libisofs="$libisofs $isofs"/make_isohybrid_mbr.o + + +echo "Version timestamp : $(sed -e 's/#define Xorriso_timestamP "//' -e 's/"$//' "$xorr"/xorriso_timestamp.h)" + +date -u '+#define Xorriso_build_timestamP "%Y.%m.%d.%H%M%S"' >"$xorr"/xorriso_buildstamp.h +echo "Build timestamp : $(sed -e 's/#define Xorriso_build_timestamP "//' -e 's/"$//' "$xorr"/xorriso_buildstamp.h)" + +echo "compiling program $xorr/xorriso.c $static_opts $debug_opts $def_opts" +cc -I. -DXorriso_with_maiN $def_libreadline \ + $warn_opts \ + $static_opts \ + $debug_opts \ + $def_opts \ + $largefile_opts \ + \ + -o "$xorr"/xorriso \ + \ + "$xorr"/xorriso.c \ + \ + "$xorr"/xorrisoburn.c \ + \ + "$burn"/async.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 \ + "$burn"/libdax_audioxtr.o \ + "$burn"/libdax_msgs.o \ + "$burn"/cleanup.o \ + \ + "$burn"/mmc.o \ + "$burn"/sbc.o \ + "$burn"/spc.o \ + "$burn"/util.o \ + \ + "$burn"/sector.o \ + "$burn"/toc.o \ + \ + "$burn"/crc.o \ + "$burn"/lec.o \ + \ + "$isoburn"/isoburn.o \ + "$isoburn"/burn_wrap.o \ + "$isoburn"/data_source.o \ + "$isoburn"/isofs_wrap.o \ + \ + $libisofs \ + \ + $link_libreadline \ + \ + -lpthread + + ret=$? + if test "$ret" = 0 + then + dummy=dummy + else + echo >&2 + echo "+++ FATAL : Compilation of xorriso failed" >&2 + echo >&2 + exit 1 + fi + + +if test "$do_strip" = 1 +then + echo "stripping result $xorr/xorriso" + strip "$xorr"/xorriso +fi + +echo 'done.' diff --git a/libisoburn/branches/ZeroThreeTwo/xorriso/configure_ac.txt b/libisoburn/branches/ZeroThreeTwo/xorriso/configure_ac.txt new file mode 100644 index 00000000..240d6bb2 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/xorriso/configure_ac.txt @@ -0,0 +1,120 @@ +AC_INIT([xorriso], [0.3.1], [http://libburnia-project.org]) +AC_PREREQ([2.50]) +dnl AC_CONFIG_HEADER([config.h]) + +AC_CANONICAL_HOST +AC_CANONICAL_TARGET + +AM_INIT_AUTOMAKE([subdir-objects]) + +BURN_MAJOR_VERSION=0 +BURN_MINOR_VERSION=6 +BURN_MICRO_VERSION=1 +AC_SUBST(BURN_MAJOR_VERSION) +AC_SUBST(BURN_MINOR_VERSION) +AC_SUBST(BURN_MICRO_VERSION) + +LIBISOFS_MAJOR_VERSION=0 +LIBISOFS_MINOR_VERSION=6 +LIBISOFS_MICRO_VERSION=12 +AC_SUBST(LIBISOFS_MAJOR_VERSION) +AC_SUBST(LIBISOFS_MINOR_VERSION) +AC_SUBST(LIBISOFS_MICRO_VERSION) + +dnl The API version codes are defined in libisoburn/libisoburn.h +dnl #define isoburn_header_version_* + + +AC_PREFIX_DEFAULT([/usr/local]) +test "$prefix" = "NONE" && prefix=$ac_default_prefix + +AM_MAINTAINER_MODE + +AM_PROG_CC_C_O +AC_C_CONST +AC_C_INLINE +AC_C_BIGENDIAN + +dnl Large file support +AC_SYS_LARGEFILE +AC_FUNC_FSEEKO +AC_CHECK_FUNC([fseeko]) +if test ! $ac_cv_func_fseeko; then + AC_ERROR([Libburn requires largefile support.]) +fi + +AC_PROG_LIBTOOL +AC_SUBST(LIBTOOL_DEPS) +LIBTOOL="$LIBTOOL --silent" + +AC_PROG_INSTALL + +AC_CHECK_HEADERS() + +AC_CHECK_MEMBER([struct tm.tm_gmtoff], + [AC_DEFINE(HAVE_TM_GMTOFF, 1, + [Define this if tm structure includes a tm_gmtoff entry.])], + , + [#include ]) + +dnl Check if non standard timegm() function is available +AC_CHECK_DECL([timegm], + [AC_DEFINE(HAVE_TIMEGM, 1, [Define this if timegm function is available])], + , + [#include ]) + +dnl Check if non standard eaccess() function is available +AC_CHECK_DECL([eaccess], + [AC_DEFINE(HAVE_EACCESS, 1, [Define this if eaccess function is available])], + , + [#include ]) + +THREAD_LIBS=-lpthread +AC_SUBST(THREAD_LIBS) + +TARGET_SHIZZLE +AC_SUBST(ARCH) +AC_SUBST(LIBBURN_ARCH_LIBS) + +dnl Add compiler-specific flags + +dnl See if the user wants aggressive optimizations of the code +AC_ARG_ENABLE(debug, +[ --enable-debug Disable aggressive optimizations [default=yes]], + , enable_debug=yes) +if test x$enable_debug != xyes; then + if test x$GCC = xyes; then + CFLAGS="$CFLAGS -O3" + CFLAGS="$CFLAGS -fexpensive-optimizations" + fi + CFLAGS="$CFLAGS -DNDEBUG" +else + if test x$GCC = xyes; then + CFLAGS="$CFLAGS -g -pedantic -Wall" + fi + CFLAGS="$CFLAGS -DDEBUG" +fi + +AC_ARG_ENABLE(libreadline, +[ --enable-libreadline Enable use of libreadline by xorriso, default=yes], + , enable_libreadline=yes) +if test x$enable_libreadline = xyes; then +dnl Check whether there is readline-devel and readline-runtime. +dnl If not, erase this macro which would enable use of readline(),add_history() + READLINE_DEF="-DXorriso_with_readlinE" +dnl The empty yes case obviously causes -lreadline to be linked + AC_CHECK_HEADER(readline/readline.h, AC_CHECK_LIB(readline, readline, , READLINE_DEF= ), READLINE_DEF= ) +dnl The X= in the yes case prevents that -lreadline gets linked twice + AC_CHECK_HEADER(readline/history.h, AC_CHECK_LIB(readline, add_history, X= , READLINE_DEF= ), READLINE_DEF= ) +else + READLINE_DEF= +fi +AC_SUBST(READLINE_DEF) + + +AC_CONFIG_FILES([ + Makefile + version.h + xorriso.pc + ]) +AC_OUTPUT diff --git a/libisoburn/branches/ZeroThreeTwo/xorriso/convert_man_to_html.sh b/libisoburn/branches/ZeroThreeTwo/xorriso/convert_man_to_html.sh new file mode 100755 index 00000000..23d2aa3a --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/xorriso/convert_man_to_html.sh @@ -0,0 +1,113 @@ +#!/bin/sh + +# +# convert_man_to_html.sh - ts A80118 +# +# Generates a HTML version of man page xorriso.1 +# +# To be executed in the libisoburn toplevel directory (eg. ./libisoburn-0.1.0) +# + +# set -x + +man_dir=$(pwd)"/xorriso" +export MANPATH="$man_dir" +manpage="xorriso" +raw_html=$(pwd)/"xorriso/raw_man_1_xorriso.html" +htmlpage=$(pwd)/"xorriso/man_1_xorriso.html" + +if test -r "$man_dir"/"$manpage".1 +then + dummy=dummy +else + echo "Cannot find readable man page source $1" >&2 + exit 1 +fi + +if test -e "$man_dir"/man1 +then + dummy=dummy +else + ln -s . "$man_dir"/man1 +fi + +if test "$1" = "-work_as_filter" +then + +# set -x + + sed \ + -e 's///' \ + -e 's///' \ + -e 's/XORRISO<\/title>/<title>man 1 xorriso<\/title>/' \ + -e 's/<h1 align=center>XORRISO<\/h1>/<h1 align=center>man 1 xorriso<\/h1>/' \ + -e 's/<body>/<body BGCOLOR="#F5DEB3" TEXT=#000000 LINK=#0000A0 VLINK=#800000>/' \ + -e 's/<b>Overview of features:<\/b>/\ <BR><b>Overview of features:<\/b>/' \ + -e 's/<b>General information paragraphs:<\/b>/\ <BR><b>General information paragraphs:<\/b>/' \ + -e 's/have a look at section EXAMPLES/have a look at section <A HREF="#EXAMPLES">EXAMPLES<\/A>/' \ + -e 's/<b>Session model:<\/b>/\ <BR><b>Session model:<\/b>/' \ + -e 's/<b>Media types and states:<\/b>/\ <BR><b>Media types and states:<\/b>/' \ + -e 's/<b>Creating, Growing, Modifying, Blind/\ <BR><b>Creating, Growing, Modifying, Blind/' \ + -e 's/<b>Libburn drives:<\/b>/\ <BR><b>Libburn drives:<\/b>/' \ + -e 's/^-dev /\ \ -dev /' \ + -e 's/^-devices /\ \ -devices /' \ + -e 's/<b>Rock Ridge, POSIX, X\/Open, and El Torito:<\/b>/\ <BR><b>Rock Ridge, POSIX, X\/Open, and El Torito:<\/b>/' \ + -e 's/<b>Command processing:<\/b>/\ <BR><b>Command processing:<\/b>/' \ + -e 's/<b>Dialog, Readline, Result pager:<\/b>/\ <BR><b>Dialog, Readline, Result pager:<\/b>/' \ + -e 's/<b>Aquiring source and target drive:<\/b>/\ <BR><b>Aquiring source and target drive:<\/b><BR>\ <BR>/' \ + -e 's/<b>Data manipulations:<\/b>/\ <BR><b>Data manipulations:<\/b><BR>\ <BR>/' \ + -e 's/^<p><b>−iso_rr_pattern/<p>\ <BR><b>\−iso_rr_pattern/' \ + -e 's/EXAMPLES):<br>/<A HREF="#EXAMPLES">EXAMPLES<\/A>):<br>/' \ + -e 's/<b>Writing the result:<\/b>/\ <BR><b>Writing the result:<\/b><BR>/' \ + -e 's/^-find \/ /\ \ -find \/ /' \ + -e 's/<b>Settings for data insertion:<\/b>/\ <BR><b>Settings for data insertion:<\/b><BR>\ <BR>/' \ + -e 's/^$<\/b> ln -s/\ \ $<\/b> ln -s/' \ + -e 's/<b>Settings for result writing:<\/b>/\ <BR><b>Settings for result writing:<\/b><BR>\ <BR>/' \ + -e 's/^706k = 706kB/\ \ 706k = 706kB/' \ + -e 's/^5540k = 5540kB/\ \ 5540k = 5540kB/' \ + -e 's/<b>Character sets:<\/b>/\ <BR><b>Character sets:<\/b><BR>\ <BR>/' \ + -e 's/<b>Exception processing:<\/b>/\ <BR><b>Exception processing:<\/b><BR>\ <BR>/' \ + -e 's/<b>El Torito bootable ISO images:<\/b>/\ <BR><b>El Torito bootable ISO images:<\/b><BR>\ <BR>/' \ + -e 's/<b>Dialog mode control:<\/b>/\ <BR><b>Dialog mode control:<\/b><BR>\ <BR>/' \ + -e 's/<b>Drive and media related inquiry actions:<\/b>/\ <BR><b>Drive and media related inquiry actions:<\/b><BR>\ <BR>/' \ + -e 's/<b>Navigation in ISO image/\ <BR><b>Navigation in ISO image/' \ + -e 's/^filesystem:<\/b>/filesystem:<\/b><BR>\ <BR>/' \ + -e 's/<b>Evaluation of readability and recovery:<\/b>/\ <BR><b>Evaluation of readability and recovery:<\/b><BR>\ <BR>/' \ + -e 's/<b>osirrox restore options:<\/b>/\ <BR><b>osirrox restore options:<\/b><BR>\ <BR>/' \ + -e 's/<b>Command compatibility emulations:<\/b>/\ <BR><b>Command compatibility emulations:<\/b><BR>\ <BR>/' \ + -e 's/^<p><b>−as</<p>\ <BR><b>\−as</' \ + -e 's/<b>Scripting, dialog and/\ <BR><b>Scripting, dialog and/' \ + -e 's/^features:<\/b>/features:<\/b><BR>\ <BR>/' \ + -e 's/<b>Support for frontend/\ <BR><b>Support for frontend/' \ + -e 's/^listening at stdout:<\/b>/listening at stdout:<\/b><BR>\ <BR>/' \ + -e 's/xorriso -outdev \/dev\/sr2 \\ -blank fast \\ -pathspecs on/xorriso -outdev \/dev\/sr2 -blank fast -pathspecs on/' \ + -e 's/\\ -add \\ \/sounds=\/home\/me\/sounds \\ \/pictures \\ -- \\ -rm_r \\/ -add \/sounds=\/home\/me\/sounds \/pictures -- -rm_r /' \ + -e 's/\/sounds\/indecent \\ \’\/pictures\/\*private\*\’ \\/\/sounds\/indecent \’\/pictures\/*private*\’ /' \ + -e 's/\/pictures\/confidential \\ -- \\ -add \\/\/pictures\/confidential -- -add/' \ + -e 's/xorriso -dev \/dev\/sr2 \\ -rm_r \/sounds -- \\ -mv \\/xorriso -dev \/dev\/sr2 -rm_r \/sounds -- -mv /' \ + -e 's/\/pictures\/confidential \\ \/pictures\/restricted \\ -- \\ -chmod/\/pictures\/confidential \/pictures\/restricted -- -chmod/' \ + -e 's/go-rwx \/pictures\/restricted -- \\ -pathsspecs on \\ -add \\/go-rwx \/pictures\/restricted -- -pathsspecs on -add /' \ + -e 's/\/sounds=\/home\/me\/prepared_for_dvd\/sounds_dummy /\/sounds=\/home\/me\/prepared_for_dvd\/sounds_dummy/' \ + -e 's/\/movies=\/home\/me\/prepared_for_dvd\/movies \\ -- \\ -commit/\/movies=\/home\/me\/prepared_for_dvd\/movies -- -commit/' \ + -e 's/xorriso -indev \/dev\/sr2 \\ -rm_r \/sounds -- \\/xorriso -indev \/dev\/sr2 -rm_r \/sounds -- /' \ + -e 's/-outdev \/dev\/sr0 -blank fast \\ -commit -eject all/-outdev \/dev\/sr0 -blank fast -commit -eject all/' \ + -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/<\/body>/<BR><HR><FONT SIZE=-1><CENTER>(HTML generated from '"$manpage"'.1 on '"$(date)"' by '$(basename "$0")' )<\/CENTER><\/FONT><\/body>/' \ + <"$2" >"$htmlpage" + + set +x + + chmod u+rw,go+r,go-w "$htmlpage" + echo "Emerged file:" + ls -lL "$htmlpage" + +else + + export BROWSER='cp "%s" '"$raw_html" + man -H "$manpage" + "$0" -work_as_filter "$raw_html" + rm "$raw_html" + rm "$man_dir"/man1 + +fi diff --git a/libisoburn/branches/ZeroThreeTwo/xorriso/make_timestamp.sh b/libisoburn/branches/ZeroThreeTwo/xorriso/make_timestamp.sh new file mode 100755 index 00000000..d6cfcb57 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/xorriso/make_timestamp.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +# Create version timestamp xorriso/xorriso_timestamp.h +# to be executed within ./libisoburn-develop + +timestamp="$(date -u '+%Y.%m.%d.%H%M%S')" +echo "Version timestamp : $timestamp" +echo '#define Xorriso_timestamP "'"$timestamp"'"' >xorriso/xorriso_timestamp.h + diff --git a/libisoburn/branches/ZeroThreeTwo/xorriso/make_xorriso_standalone.sh b/libisoburn/branches/ZeroThreeTwo/xorriso/make_xorriso_standalone.sh new file mode 100755 index 00000000..b8cfc163 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/xorriso/make_xorriso_standalone.sh @@ -0,0 +1,240 @@ +#!/bin/sh + +# make_xorriso_standalone.sh +# Copyright 2008 Thomas Schmitt, scdbackup@gmx.net, GPL +# +# Not intended for general use in production installations ! +# +# This is a development tool which expects a special setup of directories. +# It is to be executed in a common parent of the directories +# nglibisofs-develop libburn-develop libisoburn-develop +# +# Creates a standalone tree for building xorriso +# from the contents of a unified libburnia development tree. +# +# The ./bootstrap script gets applied and a source tarball +# is made. +# +# From that tree can be build a binary xorriso/xorriso +# which at runtime depends only on libc and libpthread. +# Execute in $lone_dir : +# +# ./configure && make +# + +current_dir=$(pwd) +lone_dir="$current_dir"/"xorriso-standalone" + +xorriso_rev=0.3.1 +# For unstable uploads: +xorriso_pl="" +# For stable releases: +# xorriso_pl=".pl00" + +with_bootstrap_tarball=1 + +create_dir() { + if mkdir "$1" + then + dummy=dummy + else + echo "Failed to create : $1" >&2 + exit 1 + fi +} + +goto_dir() { + if cd "$1" + then + dummy=dummy + else + echo "Failed to cd $1" >&2 + exit 1 + fi +} + +copy_files() { + if cp "$@" + then + dummy=dummy + else + echo "Failed to : cp " "$@" >&2 + exit 1 + fi +} + +if test -e "$lone_dir" +then + echo "Already existing : $lone_dir" >&2 + exit 1 +fi + + +# Top level directory + +goto_dir "$current_dir"/libisoburn-develop + +create_dir "$lone_dir" + +copy_files \ + AUTHORS \ + CONTRIBUTORS \ + COPYRIGHT \ + COPYING \ + INSTALL \ + acinclude.m4 \ + aclocal.m4 \ + bootstrap \ + compile \ + config.guess \ + config.status \ + config.sub \ + depcomp \ + install-sh \ + libtool \ + ltmain.sh \ + missing \ + mkinstalldirs \ + version.h.in \ + \ + "$lone_dir" + +copy_files xorriso/configure_ac.txt "$lone_dir"/configure.ac + +copy_files xorriso/xorriso_makefile_am.txt "$lone_dir"/Makefile.am + +copy_files xorriso/xorriso_pc_in.txt "$lone_dir"/xorriso.pc.in + +copy_files xorriso/README "$lone_dir"/README + +# echo "See end of xorriso/changelog.txt" >"$lone_dir"/TODO + + +# libisoburn + +create_dir "$lone_dir"/libisoburn +copy_files \ + libisoburn/*.[ch] \ + "$lone_dir"/libisoburn + +xorriso/convert_man_to_html.sh + +create_dir "$lone_dir"/xorriso +copy_files \ + xorriso/xorrisoburn.[ch] \ + xorriso/xorriso.[ch1] \ + xorriso/xorriso_private.h \ + \ + xorriso/xorriso_timestamp.h \ + \ + xorriso/changelog.txt \ + xorriso/xorriso_eng.html \ + xorriso/man_1_xorriso.html \ + "$lone_dir"/xorriso + +copy_files xorriso/xorriso_buildstamp_none.h \ + "$lone_dir"/xorriso/xorriso_buildstamp.h + +create_dir "$lone_dir"/test +copy_files \ + test/compare_file.c \ + "$lone_dir"/test/compare_file.c + + +# nglibisofs + +create_dir "$lone_dir"/libisofs +create_dir "$lone_dir"/libisofs/filters +goto_dir "$current_dir"/nglibisofs-develop +copy_files libisofs/*.[ch] "$lone_dir"/libisofs +copy_files libisofs/filters/*.[ch] "$lone_dir"/libisofs/filters +copy_files COPYRIGHT "$lone_dir"/libisofs + +# To get a common version.h +cat version.h.in >> "$lone_dir"/version.h.in + + +# <<< obsoleted patchings + +if test 1 = 0 +then + +# Change GNU macro name to POSIX name +sed -e 's/FNM_FILE_NAME/FNM_PATHNAME/g' \ + <libisofs/tree.c >"$lone_dir"/libisofs/tree.c + +# Filter out the semi-illegal TODO comments +( cd "$lone_dir"/libisofs && grep '^[[:space:]]*//' *.[ch] | less ) +echo "Is it ok delete all shown //-lines ?" +read yesno +if test "$yesno" = "y" -o "$yesno" = "1" +then + for i in "$lone_dir"/libisofs/*.[ch] + do + # first copy attributes + cp "$i" "$lone_dir"/libisofs/tmpfile + # now filter away // lines + grep -v '^[[:space:]]*//' <"$i" >"$lone_dir"/libisofs/tmpfile && \ + mv "$lone_dir"/libisofs/tmpfile "$i" + done +fi +echo "Remaining // lines:" +( cd "$lone_dir"/libisofs && grep '//' *.[ch] ) + +fi + + + +# libburn + +create_dir "$lone_dir"/libburn +goto_dir "$current_dir"/libburn-develop +copy_files libburn/*.[ch] "$lone_dir"/libburn +copy_files COPYRIGHT "$lone_dir"/libburn + + +# To get a common version.h +cat version.h.in >> "$lone_dir"/version.h.in + + +# tarball + +if test "$with_bootstrap_tarball" = 1 +then + +tarball_dir="$current_dir"/xorriso-"$xorriso_rev" +mv "$lone_dir" "$tarball_dir" + +goto_dir "$tarball_dir" + +./bootstrap + +# Remove unneeded temporary data from ./bootstrap +rm -r ./autom4te.cache + +# 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 +) + +cd "$current_dir" +tar czf ./xorriso-"$xorriso_rev""$xorriso_pl".tar.gz $(basename "$tarball_dir") + +ls -l $(pwd)/xorriso-"$xorriso_rev""$xorriso_pl".tar.gz + +mv "$tarball_dir" "$lone_dir" + +fi + +echo "Done" +echo "HINT: Now build xorriso/xorriso by:" +echo " cd '$lone_dir' && ./configure && make" +echo diff --git a/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso.1 b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso.1 new file mode 100644 index 00000000..7ac38ab6 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso.1 @@ -0,0 +1,3059 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" First parameter, NAME, should be all caps +.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection +.\" other parameters are allowed: see man(7), man(1) +.TH XORRISO 1 "Dec 16, 2008" +.\" Please adjust this date whenever revising the manpage. +.\" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp <n> insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.nh +.SH NAME +xorriso - creates, loads, manipulates and writes ISO 9660 filesystem images +with Rock Ridge extensions. +.SH SYNOPSIS +.B xorriso +.RI [ settings | actions ] +.br +.SH DESCRIPTION +.PP +.B xorriso +is a program which maps file objects from POSIX compliant +filesystems into Rock Ridge enhanced ISO 9660 filesystems and allows +session-wise manipulation of such filesystems. It can load the management +information of existing ISO images and it writes the session results to +optical media or to filesystem objects. +.br +Vice versa xorriso is able to restore file objects from ISO 9660 filesystems. +.PP +A special property of xorriso is that it needs neither an external ISO 9660 +formatter program nor an external burn program for CD or DVD but rather +incorporates the libraries of libburnia-project.org . +.SS +.B Overview of features: +.br +Operates on an existing ISO image or creates a new one. +.br +Copies files from filesystem into the ISO image. +.br +Renames or deletes file objects in the ISO image. +.br +Changes file properties in the ISO image. +.br +Updates ISO subtrees incrementally to match given disk subtrees. +.br +Writes result either as completely new image or as add-on session +to optical media or filesystem objects. +.br +Can activate ISOLINUX boot images via El Torito. +.br +Can perform multi-session tasks as emulation of mkisofs and cdrecord. +.br +Can restore files from ISO image to disk filesystem (see osirrox). +.br +Can issue commands to mount older sessions on Linux or FreeBSD. +.br +Can check media for damages and copy readable blocks to disk. +.br +Scans for optical drives, blanks re-useable optical media. +.br +Reads its instructions from command line arguments, dialog, and batch files. +.br +Provides navigation commands for interactive ISO image manipulation. +.br +Adjustable thresholds for abort, exit value, and problem reporting. +.SS +.B General information paragraphs: +.br +Session model +.br +Media types and states +.br +Creating, Growing, Modifying, Blind Growing +.br +Libburn drives +.br +Rock Ridge, POSIX, X/Open, and El Torito +.br +Command processing +.br +Dialog, Readline, Result pager +.sp 1 +Maybe you first want to have a look at section EXAMPLES near the end of +this text before reading the next few hundred lines of background information. +.SS +.B Session model: +.br +Unlike other filesystems, ISO 9660 is not intended for read-write operation but +rather for being generated in a single sweep and being written to media as a +.B session. +.br +The data content of the session is called filesystem +.B image. +.PP +The written image in its session can then be mounted by the operating system +for being used read-only. Linux is able to mount ISO images from block devices, +which may represent optical media, other media or via a loop device even +from regular disk files. FreeBSD mounts ISO images from devices that represent +arbitrary media or from regular disk files. +.PP +This session usage model has been extended on CD media by the concept of +.B multi-session , +which allows to add information to the CD and gives the mount programs +of the operating systems the addresses of the entry points of each +session. The mount programs recognize block devices which represent +CD media and will by default mount the image in the last session. +.br +This session usually contains an updated directory tree for the whole media +which governs the data contents in all recorded sessions. +So in the view of the mount program all sessions of a particular media +together form a single filesystem image. +.br +Adding a session to an existing ISO image is in this text referred as +\fBgrowing\fR. +.br +The multi-session model of the MMC standard does not apply to all media +types. But program growisofs by Andy Polyakov showed how to extend this +functionality to overwriteable media or disk files which carry valid ISO 9660 +filesystems. This expansion method is referred as emulated growing. +.PP +xorriso provides both ways of growing as well as an own method named +\fBmodifying\fR which produces a completely new ISO image from the old +one and the modifications. +See paragraph Creating, Growing, Modifying, Blind Growing below. +.PP +xorriso adopts the concept of multi-session by loading an eventual image +directory tree, allowing to manipulate it by several actions, and to write +the new image to the target media. +.br +The first session of a xorriso run begins by the definition of the input +drive with the eventual ISO image or by the definition of an output drive. +The session ends by command -commit which triggers writing. A -commit is +done automatically when the program ends regularly. +.PP +After -commit a new session begins with the freshly written one as input. +A new input drive can only be chosen as long as the loaded ISO image was +not altered. Pending alteration can be revoked by command -rollback. +.PP +Writing a session to the target is supposed to be very expensive in terms of +time and of consumed space on appendable or write-once media. Therefore all +intended manipulations of a particular ISO image should be done in a single +session. +.br +In some special situations (e.g. in a file-to-file situation) it can be +useful to store intermediate states and to continue with image manipulations. +.SS +.B Media types and states: +There are two families of media in the MMC standard: +.br +\fBMulti-session media\fR are CD-R, CD-RW, DVD-R, DVD+R, DVD+R/DL, and +unformatted DVD-RW. These media provide a table of content which +describes their existing sessions. See option \fB-toc\fR. +.br +\fBOverwriteable media\fR are DVD-RAM, DVD+RW, BD-RE, and formatted DVD-RW. +They allow random write access but do not provide information about their +session history. If they contain one or more ISO 9660 sessions and if the +first session was written by xorriso, then a table of content can +be emulated. Else only a single overall session will be visible. +.br +DVD-RW media can be formatted by -format full. +They can be made unformatted by -blank deformat. +.br +Emulated drives are handled as overwriteable media if they are random +read-write accessible. If they are only sequentially writeable then +they are handled as blank multi-session media. +.PP +These media can assume several states in which they offer different +capabilities. +.br +\fBBlank\fR media can be written from scratch. They contain no ISO image +suitable for xorriso. +.br +Blank is the state of newly purchased optical media. +With used CD-RW and DVD-RW it can be achieved by action -blank "as_needed". +Overwriteable media are considered blank if they are new or if they have +been marked as blank by xorriso. +Action -blank "as_needed" can be used to do this marking on overwriteable +media, or to apply eventual mandatory formatting of new media. +.br +\fBAppendable\fR media accept further sessions. Either they are MMC +multi-session media in appendable state, or they are overwriteable media +which contain an ISO image suitable for xorriso. +.br +Appendable is the state after writing a session with option -close off. +.br +\fBClosed\fR media cannot be written. They may contain an ISO image suitable +for xorriso. +.br +Closed is the state of DVD-ROM media and of multi-session media which were +written with option -close on. If the drive is read-only hardware then it will +probably show any media as closed CD-ROM resp. DVD-ROM. +.br +Overwriteable media assume this state in such read-only drives or if they +contain unrecognizable data in the first 32 data blocks. +.br +Read-only drives may or may not show session histories of multi-session +media. Often only the first and the last session are visible. Sometimes +not even that. Option -rom_toc_scan might or might not help in such cases. +.SS +.B Creating, Growing, Modifying, Blind Growing: +.br +A new empty ISO image gets \fBcreated\fR +if there is no input drive with a valid ISO 9660 image when the first time +an output drive is defined. This is achieved by option -dev on blank media +or by option -outdev on media in any state. +.br +The new empty image can be populated with directories and files. +Before it can be written, the media in the output drive must get into +blank state if it was not blank already. +.PP +If there is a input drive with a valid ISO image, then this image gets loaded +as foundation for manipulations and extension. The constellation of input +and output drive determines which write method will be used. +They have quite different capabilities and constraints. +.PP +The method of \fBgrowing\fR adds new data to the existing media. These +data comprise of eventual new file content and they override the existing +ISO 9660 + Rock Ridge directory tree. It is possible to hide files from +previous sessions but they still exist on media and with many types of +optical media it is quite easy to recover them by mounting older sessions. +.br +Growing is achieved by option -dev. +.PP +The write method of \fBmodifying\fR produces compact filesystem +images with no outdated files or directory trees. Modifying can write its +images to target media which are completely unsuitable for multi-session +operations. E.g. DVD-RW which were treated with -blank deformat_quickest, +named pipes, character devices, sockets. +On the other hand modified sessions cannot be written to appendable media +but to blank media only. +.br +So for this method one needs either two optical drives or has to work with +filesystem objects as source and/or target media. +.br +Modifying takes place if input drive and output drive are not the same and +if option -grow_blindly is set to its default "off". +This is achieved by options -indev and -outdev. +.PP +If option -grow_blindly is set to a non-negative number and if -indev and +-outdev are both set to different drives, then \fBblind growing\fR is +performed. It produces an add-on session which is ready for being written +to the given block address. This is the usage model of +.br + mkisofs -M $indev -C $msc1,$msc2 -o $outdev +.br +which gives much room for wrong parameter combinations and should thus only be +employed if a strict distinction between ISO formatter xorriso and the burn +program is desired. -C $msc1,$msc2 is equivalent to: +.br + -load sbsector $msc1 -grow_blindly $msc2 +.SS +.B Libburn drives: +.br +Input drive, i.e. source of an existing or empty ISO image, can be any random +access readable libburn drive: optical media with readable data, +blank optical media, regular files, block devices. +.PP +Output drive, i.e. target for writing, can be any libburn drive. +Some drive types do not support the method of growing but only the methods +of modifying and blind growing. They all are suitable for newly created images. +.br +All drive file objects have to offer rw-permission to the user of xorriso. +Even those which will not be useable for reading an ISO image. +.PP +MMC compliant (i.e. optical) drives on Linux usually get addressed by +the path of their block device or of their generic character device. E.g. +.br + -dev /dev/sr0 +.br + -dev /dev/hdc +.br + -dev /dev/sg2 +.br +On FreeBSD the device files have names like +.br + -dev /dev/cd0 +.br + -dev /dev/acd0 +.br +Get a list of accessible drives by command +.br + -devices +.br +It might be necessary to do this as +.B superuser +in order to see all drives and to then allow rw-access for the intended users. +Consider to bundle the authorized users in a group like old "floppy". +.PP +Filesystem objects of nearly any type can be addressed by prefix "stdio:" and +their path in the filesystem. E.g.: +.br + -dev stdio:/dev/sdc +.br +The default setting of -drive_class allows to address files outside the +/dev tree without that prefix. E.g.: +.br + -dev /tmp/pseudo_drive +.br +If path leads to a regular file or to a block device then the emulated drive +is random access readable and can be used for the method of growing if it +already contains a valid ISO 9660 image. Any other file type is not readable +via "stdio:" and can only be used as target for the method of modifying or +blind growing. +Non-existing paths in existing directories are handled as empty regular files. +.PP +A very special kind of pseudo drive are open file descriptors. They are +depicted by "stdio:/dev/fd/" and descriptor number (see man 2 open). +.br +Addresses "-" or "stdio:/dev/fd/1" depict standard output, which normally is +the output channel for result texts. +To prevent a fatal intermingling of ISO image and text messages, all result +texts get redirected to stderr if -*dev "-" or "stdio:/dev/fd/1" is among +the start arguments of the program. +.br +Standard output is currently suitable for creating one session +per program run without dialog. Use in other situations is discouraged +and several restrictions apply: +.br +It is not allowed to use standard output as pseudo drive if it was not +among the start arguments. Do not try to fool this ban via backdoor addresses +to stdout. +.br +If stdout is used as drive, then -use_readline is permanently disabled. +Use of backdoors will cause severe memory and/or tty corruption. +.PP +Be aware that especially the superuser can write into any accessible file or +device by using its path with the "stdio:" prefix. By default any address +in the /dev tree without prefix "stdio:" will work only if it leads to a MMC +drive. +.br +One may use option +.B -ban_stdio_write +to surely prevent this risk and to allow only MMC drives. +.br +One may prepend "mmc:" to a path to surely disallow any automatic "stdio:". +.br +By option -drive_class one may ban certain paths or allow access without +prefix "stdio:" to other paths. +.SS +.B Rock Ridge, POSIX, X/Open, and El Torito: +.br +.B Rock Ridge +is the name of a set of additional informations which enhance +an ISO 9660 filesystem so that it can represent a POSIX compliant filesystem +with ownership, access permissions, symbolic links, and other attributes. +.PP +This is what xorriso uses for a decent representation of the disk files +within the ISO image. Rock Ridge information is produced with any xorriso +image. +.PP +xorriso is not named "porriso" because POSIX only guarantees 14 characters +of filename length. It is the X/Open System Interface standard XSI which +demands a file name length of up to 255 characters and paths of up to 1024 +characters. Rock Ridge fulfills this demand. +.PP +An +.B El Torito +boot record connects a boot image, which is a binary program plus some +other files stored in the ISO image, with the bootstrapping facility of +contemporary computers. +The content of the boot image files is not in the scope of El Torito. +.br +Most bootable Linux CDs are equipped with ISOLINUX boot images. xorriso is +able to create or maintain an El Torito object which makes such an image +bootable. For details see option -boot_image. +Emulation -as mkisofs supports the example options out of the ISOLINUX wiki. +.br +The support for other boot image types is sparse. +.br +An MBR is generated together with the El Torito boot record if the boot image +bears the isohybrid signature of ISOLINUX 3.72 or later. It will occupy the +first 512 bytes of the emerging ISO image and enable booting from media which +appear as hard disk rather than as CDROM. An MBR does not hamper CDROM booting. +The MBR of a follow-up session can get in effect only on overwriteable media. +.SS +.B Command processing: +.br +Commands are either actions or settings. They consist of a command word, +followed by zero or more parameter words. If the list of parameter words +is of variable length (indicated by "[...]" or "[***]") then it has to be +terminated by either the \fBlist delimiter\fR, or the end of argument list, +or an end of an input line. +.PP +At program start the list delimiter is the word "--". This may be changed +by option -list_delimiter in order to allow "--" as argument in a list of +variable length. It is advised to reset the delimiter to "--" immediately +afterwards. +.br +For brevity the list delimiter is referred as "--" throughout this text. +.br +The list delimiter is silently tolerated if it appears after the parameters of +a command with a fixed list length. It is handled as normal text if it +appears among the arguments of such a command. +.PP +.B Pattern expansion +is a property of some particular commands and not a general +feature. It gets controlled by commands -iso_rr_pattern and -disk_pattern. +Commands which eventually use pattern expansion all have variable argument +lists which are marked in this man page by "[***]" rather than "[...]". +.br +Some other commands perform pattern matching unconditionally. +.PP +Command and parameter words are either read from program arguments, where one +argument is one word, or from quoted input lines where words are recognized +similar to the quotation rules of a shell parser. +.br +xorriso is not a shell, although it might appear so on first glimpse. +Be aware that the interaction of quotation marks and pattern symbols like "*" +differs from the usual shell parsers. In xorriso, a quotation mark does not +make a pattern symbol literal. +.PP +.B Quoted input +converts whitespace separated text pieces into words. +The double quotation mark " and the single quotation mark ' can be used to +enclose whitespace and make it part of words (e.g. of file names). Each mark +type can enclose the marks of the other type. A trailing backslash \\ outside +quotations or an open quotation cause the next input line to be appended. +.br +Quoted input accepts any ASCII character except NUL (0) as content of quotes. +Nevertheless it can be cumbersome for the user to produce those characters +at all. Therefore quoted input and program arguments allow optional +.B Backslash Interpretation +which can represent all ASCII characters except NUL (0) by backslash codes +as in $'...' of bash. +.br +It is not enabled by default. See option -backslash_codes. +.PP +When the program begins then it first looks for argument -no_rc. If this is +not present then it looks for its startup files and +eventually reads their content as command input lines. Then it interprets +the program arguments as commands and parameters and finally it enters +dialog mode if command -dialog "on" was executed up to then. +.PP +The program ends either by command -end, or by the end of program arguments +if not dialog was enabled up to that moment, or by a problem +event which triggers the threshold of command -abort_on. +.SS +.B Dialog, Readline, Result pager: +.br +Dialog mode prompts for a quoted input line, parses it into words, and performs +them as commands with their parameters. It provides assisting services +to make dialog more comfortable. +.PP +Readline is an enhancement for the input line. You may know it already from +the bash shell. Whether it is available in xorriso depends on the availability +package readline-dev at the time when xorriso was built from its sourcecode. +.br +It allows to move the cursor over the text in the line by help of the +Leftward and the Rightward arrow key. +Text may be inserted at the cursor position. The Delete key removes the +character under the cursor. Upward and Downward arrow keys navigate through +the history of previous input lines. +.br +See man readline for more info about libreadline. +.PP +Option -page activates a builtin result text pager which may be convenient in +dialog. After an action has put out the given number of terminal lines, +the pager prompts the user for a line of input. +.br +An empty line lets xorriso resume work until the next page is put out. +.br +The single character "@" disables paging for the current action. +.br +"@@@", "x", "q", "X", or "Q" urge the current action to abort and suppress +further result output. +.br +Any other line will be interpreted as new dialog line. The current action +is urged to abort. Afterwards, the input line is executed. +.PP +Some actions apply paging to their info output, too. +.br +The urge to abort may or may not be obeyed by the current action. All actions +try to abort as soon as possible. +.br +.SH OPTIONS +.br +All command words are shown with a leading dash although this dash is not +mandatory for the option to be recognized. There may be future emulation +modes, where dashes may become mandatory in order to distinguish options +from file addresses. +.br +Normally any number of leading dashes is ignored with command words and +inner dashes are interpreted as underscores. +.TP +.B Aquiring source and target drive: +.TP +\fB\-dev\fR address +Set input and output drive to the same address and load an eventual ISO image. +If there is no ISO image then create a blank one. +Set the image expansion method to growing. +.br +This is only allowed as long as no changes are pending in the currently +loaded ISO image. Eventually one has to perform -commit or -rollback first. +Violation yields a FAILURE event. +.br +Special address string "-" means standard output, to which several restrictions +apply. See above paragraph "Libburn drives". +.br +An empty address string "" gives up the current device +without aquiring a new one. +.TP +\fB\-indev\fR address +Set input drive and load an eventual ISO image. If the new input drive differs +from -outdev then switch from growing to modifying or to blind growing. +It depends on the setting of -grow_blindly which of both gets activated. +The same rules and restrictions apply as with -dev. +.TP +\fB\-outdev\fR address +Set output drive and if it differs from the input drive then switch from +growing to modifying or to blind growing. Unlike -dev and -indev this action +does not load a new ISO image. So it can be performed even if there are pending +changes. +.br +-outdev can be performed without previous -dev or -indev. In that case an +empty ISO image with no changes pending is created. It can either be populated +by help of -map, -add et.al. or it can be discarded silently if -dev or -indev +are performed afterwards. +.br +Special address string "-" means standard output, to which several restrictions +apply. See above paragraph "Libburn drives". +.br +An empty address string "" gives up the current output drive +without aquiring a new one. No writing is possible without an output drive. +.TP +\fB\-drive_class\fR "harmless"|"banned"|"risky"|"clear_list" disk_pattern +Add a drive path pattern to one of the safety lists or make those lists empty. +There are three lists defined which get tested in the following sequence: +.br +If a drive address path matches the "harmless" list then the drive will be +accepted. If it is not a MMC device then the prefix "stdio:" will be prepended +automatically. This list is empty by default. +.br +Else if the path matches the "banned" list then the drive will not be +accepted by xorriso but rather lead to a FAILURE event. This list is empty by +default. +.br +Else if the path matches the "risky" list and if it is not a MMC device, +then its address must have the prefix "stdio:" or it will be rejected. +This list has by default one entry: "/dev". +.br +If a drive path matches no list then it is considered "harmless". By default +these are all paths which do not begin with directory "/dev". +.br +A path matches a list if one of its parent paths or itself matches a list +entry. An eventual address prefix "stdio:" or "mmc:" will be ignored when +testing for matches. +.br +By pseudo-class "clear_list" and pseudo-patterns "banned", "risky", "harmless", +or "all", the lists may be made empty. +.br +E.g.: -drive_class clear_list banned +.br +One will normally define the -drive_class lists in one of the xorriso +Startup Files. +.br +Note: This is not a security feature but rather a bumper for the superuser to +prevent inadverted mishaps. For reliably blocking access to a device file you +have to deny its rw-permissions in the filesystem. +.TP +\fB\-grow_blindly\fR "off"|predicted_nwa +If predicted_nwa is a non-negative number then perform blind growing rather +than modifying if -indev and -outdev are set to different drives. +"off" or "-1" switch to modifying, which is the default. +.br +predicted_nwa is the block address where the add-on session of blind +growing will finally end up. It is the responsibility of the user to ensure +this final position and the presence of the older sessions. Else the +overall ISO image will not be mountable or will produce read errors when +accessing file content. xorriso will write the session to the address +as obtained from examining -outdev and not necessarily to predicted_nwa. +.br +During a run of blind growing, the input drive gets released before output +begins. The output drive gets released when writing is done. +.TP +\fB\-load\fR entity id +Load a particular (possibly outdated) ISO image from a -dev or -indev which +hosts more than one session. Usually all available sessions are shown with +option -toc. +.br +entity depicts the kind of addressing. id depicts the particular +address. The following entities are defined: +.br +"auto" with any id addresses the last session in -toc. This is the default. +.br +"session" with id being a number as of a line "ISO session", column "Idx". +.br +"track" with id being a number as of a line "ISO track", column "Idx". +.br +"lba" or "sbsector" with a number as of a line "ISO ...", column "sbsector". +.br +"volid" with a search pattern for a text as of a line "ISO ...", +column "Volume Id". +.br +Adressing a non-existing entity or one which does not represent an ISO +image will either abandon -indev or at least lead to a blank image. +.br +If an input drive is set at the moment when -load is executed, then the +addressed ISO image is loaded immediately. Else, the setting will be pending +until the next -dev or -indev. After the image has been loaded once, the +setting is valid for -rollback until next -dev or -indev, where it +will be reset to "auto". +.TP +\fB\-assert_volid\fR pattern severity +Refuse to load ISO images with volume ids which do not match the given +search pattern. When refusing an image, give up the input drive and issue +an event of the given severity. An empty search pattern accepts any image. +.br +This option does not hamper the creation of an empty image from blank +input media and does not discard an already loaded image. +.TP +\fB\-in_charset\fR character_set_name +Set the character set from which to convert file names when loading an +image. This has eventually to be done before specifying -dev , -indev or +-rollback. See paragraph "Character sets" for more explanations. +When loading the written image after -commit the setting of -out_charset +will be copied to -in_charset. +.TP +\fB\-rom_toc_scan\fR "on"|"off"[:"emul_on"|"emul_off"] +Read-only drives do not tell the actual media type but show any media as +ROM (e.g. as DVD-ROM). The session history of MMC multi-session media might +be truncated to first and last session or even be completely false. +(The eventual emulated history of overwriteable media is not affected by this.) +.br +To have in case of failure a chance of getting the session history and +especially the address of the last session, there is a scan for ISO 9660 +filesystem headers which might help but also might yield worse results +than the drive's table of content. At its end it can cause read attempts +to invalid addresses and thus ugly drive behavior. +Setting "on" enables that scan for alleged read-only media. +.br +On the other hand the emulation of session history on overwriteable media +can hamper reading of partly damaged media. Setting "off:emul_off" disables +the elsewise trustworthy table-of-content scan for those media. +.br +To be in effect, the -rom_toc_scan setting has to be made before the -*dev +command which aquires drive and media. +.TP +\fB\-ban_stdio_write\fR +Allow for writing only the usage of MMC optical drives. Disallow +to write the result into files of nearly arbitrary type. +Once set, this command cannot be revoked. +.TP +.B Data manipulations: +.PP +The following commands expect file addresses of two kinds: +.br +.B disk_path +is a path to an object in the local filesystem tree. +.br +.B iso_rr_path +is the Rock Ridge name of a file object in the ISO image. (Do not +confuse with the lowlevel ISO 9660 names visible if Rock Ridge gets ignored.) +.PP +Note that in the ISO image you are as powerful as the superuser. Access +permissions of the existing files in the image do not apply to your write +operations. They are intended to be in effect with the read-only mounted image. +.PP +If the iso_rr_path of a newly inserted file leads to an existing +file object in the ISO image, then the following collision handling +happens: +.br +If both objects are directories then they get merged by recursively inserting +the subobjects from filesystem into ISO image. +If other file types collide then the setting of command +.B \-overwrite +decides. +.br +Renaming of files has similar collision handling, but directories can only +be replaced, not merged. Note that -mv inserts the source objects into an +eventual existing target directory rather than attempting to replace it. +.PP +The commands in this section alter the ISO image and not the local filesystem. +.TP +\fB\-iso_rr_pattern\fR "on"|"ls"|"off" +Set the pattern expansion mode for the iso_rr_path arguments of several +commands which support this feature. +.br +.B Pattern expansion +converts a list of pattern words into a list of existing file addresses. +Eventual unmatched pattern words appear themselves in that result list, though. +.br +Pattern matching supports the usual shell parser wildcards '*' '?' '[xyz]' +and respects '/' as separator which may only be matched literally. +.br +Setting "off" disables this feature for all commands which are marked in this +man page by "iso_rr_path [***]" or "iso_rr_pattern [***]". +.br +Setting "on" enables it for all those commands. +.br +Setting "ls" enables it only for those which are marked by +"iso_rr_pattern [***]". +.br +Default is "on". +.TP +\fB\-disk_pattern\fR "on"|"ls"|"off" +Set the pattern expansion mode for the disk_path arguments of several +commands which support this feature. +.br +Setting "off" disables this feature for all commands which are marked in this +man page by "disk_path [***]" or "disk_pattern [***]". +.br +Setting "on" enables it for all those commands. +.br +Setting "ls" enables it only for those which are marked by +"disk_pattern [***]". +.br +Default is "ls". +.TP +\fB\-add\fR pathspec [...] | disk_path [***] +Insert the given files or directory trees from filesystem +into the ISO image. +.br +If -pathspecs is set to "on" then pattern expansion is always disabled and +character '=' has a special meaning. It eventually separates the ISO image path +from the disk path: +.br +iso_rr_path=disk_path +.br +The separator '=' can be escaped by '\\'. +If iso_rr_path does not begin with '/' then -cd is prepended. +If disk_path does not begin with '/' then -cdx is prepended. +.br +If no '=' is given then the word is used as both, iso_rr_path and disk path. +If in this case the word does not begin with '/' then -cdx is prepended to +the disk_path and -cd is prepended to the iso_rr_path. +.br +If -pathspecs is set to "off" then eventual -disk_pattern expansion applies. +The resulting words are used as both, iso_rr_path and disk path. Eventually +-cdx gets prepended to disk_path and -cd to iso_rr_path. +.TP +\fB\-add_plainly\fR mode +If set to mode "unknown" then any command word that does not begin with "-" and +is not recognized as known command will be subject to a virtual -add command. +I.e. it will be used as pathspec or as disk_path and added to the image. +Eventually -disk_pattern expansion applies to disk_paths. +.br +Mode "dashed" is similar to "unknown" but also adds unrecognized command +words even if they begin with "-". +.br +Mode "any" announces that all further words are to be added as pathspecs +or disk_paths. This does not work in dialog mode. +.br +Mode "none" is the default. It prevents any words from being understood +as files to add, if they are not parameters to appropriate commands. +.TP +\fB\-path_list\fR disk_path +Like -add but read the parameter words from file disk_path +or standard input if disk_path is "-". +The list must contain exactly one pathspec resp. disk_path pattern per line. +.TP +\fB\-quoted_path_list\fR disk_path +Like -path_list but with quoted input reading rules. Lines get split into +parameter words for -add. Whitespace outside quotes is discarded. +.TP +\fB\-map\fR disk_path iso_rr_path +Insert file object disk_path into the ISO image as iso_rr_path. If disk_path +is a directory then its whole sub tree is inserted into the ISO image. +.TP +\fB\-map_single\fR disk_path iso_rr_path +Like -map, but if disk_path is a directory then its sub tree is not inserted. +.TP +\fB\-map_l\fR disk_prefix iso_rr_prefix disk_path [***] +Perform -map with each of the disk_path arguments. iso_rr_path will be +composed from disk_path by replacing disk_prefix by iso_rr_prefix. +.TP +\fB\-update\fR disk_path iso_rr_path +Compare file object disk_path with file object iso_rr_path. If they do not +match, then perform the necessary image manipulations to make iso_rr_path +a matching copy of disk_path. This comparison will imply lengthy content +reading before a decision is made. On the other hand it strives for the +smallest possible amount of add-on data which is needed to achieve the +matching copy. +.br +If disk_path is a directory and iso_rr_path does not exist yet, then the +whole subtree will be inserted. Else only directory attributes will be +updated. +.TP +\fB\-update_r\fR disk_path iso_rr_path +Like -update but working recursively. I.e. all file objects below both +addresses get compared whether they have counterparts below the other address +and whether both counterparts match. If there is a mismatch then the necessary +update manipulation is done. +.br +Note that the comparison result may depend on option -follow. Its setting +should always be the same as with the first adding of disk_path as iso_rr_path. +.br +If iso_rr_path does not exist yet, then it gets added. If disk_path does not +exist, then iso_rr_path gets deleted. +.TP +\fB\-update_l\fR disk_prefix iso_rr_prefix disk_path [***] +Perform -update_r with each of the disk_path arguments. iso_rr_path will be +composed from disk_path by replacing disk_prefix by iso_rr_prefix. +.TP +\fB\-cut_out\fR disk_path byte_offset byte_count iso_rr_path +Map a byte interval of a regular disk file into a regular file in the ISO +image. +This may be necessary if the disk file is larger than a single media, or if +it exceeds the traditional limit of 2 GiB - 1 for old operating systems, +or the limit of 4 GiB - 1 for newer ones. Only the newest Linux kernels +seem to read properly files >= 4 GiB - 1. +.br +A clumsy remedy for this limit is to backup file pieces and to concatenate +them at restore time. A well tested chopping size is 2047m. +It is permissible to request a higher byte_count than available. The +resulting file will be truncated to the correct size of a final piece. +To request a byte_offset higher than available yields no file in +the ISO image but a SORRY event. +E.g: +.br + -cut_out /my/disk/file 0 2047m \\ +.br + /file/part_1_of_3_at_0_with_2047m_of_5753194821 \\ +.br + -cut_out /my/disk/file 2047m 2047m \\ +.br + /file/part_2_of_3_at_2047m_with_2047m_of_5753194821 \\ +.br + -cut_out /my/disk/file 4094m 2047m \\ +.br + /file/part_3_of_3_at_4094m_with_2047m_of_5753194821 +.br +-cut_out is coordinated with -compare* and -update* if the names of the +part files follow a convention by which xorriso is able to recognize +file parts and process them accordingly: +.br +A disk file gets mapped to an ISO directory containing its split parts +as regular files. The parts have names which describe the splitting +by 5 numbers which are separated by some non-numerical text: +.br +part_number, total_parts, byte_offset, byte_count, disk_file_size +.br +Scaling characters like "m" or "k" are taken into respect and may +serve as separators as well. All digits are interpreted as decimal, +even if leading zeros are present. +.br +Not all parts have to be present on the same media. But those parts +which are present have to sit in the same directory. No other files +are allowed in there. Parts have to be disjoint. Their numbers have +to be plausible. E.g. byte_count must be valid as -cut_out argument +and it must be the same with all parts. +.br +If the disk file grows enough to need new parts then those get added +to the directory if it already contains all parts of the old disk file. +If not all parts are present, then only those present parts will +be updated. +.TP +\fB\-cpr\fR disk_path [***] iso_rr_path +Insert the given files or directory trees from filesystem +into the ISO image. +.br +The rules for generating the ISO addresses are similar as with +shell command cp -r. Nevertheless, directories of the iso_rr_path +are created if necessary. Especially a not yet existing iso_rr_path +will be handled as directory if multiple disk_paths are present. +The leafnames of the multiple disk_paths will be grafted under that +directory as would be done with an existing directory. +.br +If a single disk_path is present then a non-existing iso_rr_path will +get the same type as the disk_path. +.br +If a disk_path does not begin with '/' then -cdx is prepended. +If the iso_rr_path does not begin with '/' then -cd is prepended. +.TP +\fB\-rm\fR iso_rr_path [***] +Delete the given files from the ISO image. +.br +Note: This does not free any space on the -indev media, even if +the deletion is committed to that same media. +.br +The image size will shrink if the image is written to a different +media in modification mode. +.TP +\fB\-rm_r\fR iso_rr_path [***] +Delete the given files or directory trees from the ISO image. +See also the note with option -rm. +.TP +\fB\-mv\fR iso_rr_path [***] iso_rr_path +Rename the given file objects in the ISO tree to the last +argument in the list. Use the same rules as with shell command mv. +.br +If pattern expansion is enabled and if the last argument contains wildcard +characters then it must match exactly one existing file address, or else the +command fails with a FAILURE event. +.TP +\fB\-chown\fR uid iso_rr_path [***] +Set ownership of file objects in the ISO image. uid may either be a decimal +number or the name of a user known to the operating system. +.TP +\fB\-chown_r\fR uid iso_rr_path [***] +Like -chown but affecting all files below eventual directories. +.TP +\fB\-chgrp\fR gid iso_rr_path [***] +Set group attribute of file objects in the ISO image. gid may either be a +decimal number or the name of a group known to the operating system. +.TP +\fB\-chgrp_r\fR gid iso_rr_path [***] +Like -chgrp but affecting all files below eventual directories. +.TP +\fB\-chmod\fR mode iso_rr_path [***] +Equivalent to shell command chmod in the ISO image. +mode is either an octal number beginning with "0" or a comma separated +list of statements of the form [ugoa]*[+-=][rwxst]* . +.br +Like: go-rwx,u+rwx . +.br +.B Personalities: +u=user, g=group, o=others, a=all +.br +.B Operators: ++ adds given permissions, - revokes given permissions, += revokes all old permissions and then adds the given ones. +.br +.B Permissions: +r=read, w=write, x=execute|inspect, s=setuid|setgid, t=sticky bit +.br +For octal numbers see man 2 stat. +.TP +\fB\-chmod_r\fR mode iso_rr_path [***] +Like -chmod but affecting all files below eventual directories. +.TP +\fB\-alter_date\fR type timestring iso_rr_path [***] +Alter the date entries of a file in the ISO image. type is +one of "a", "m", "b" for access time, modification time, +both times. +.br +timestring may be in the following formats +(see also section EXAMPLES): +.br +As expected by program date: + MMDDhhmm[[CC]YY][.ss]] +.br +As produced by program date: + [Day] MMM DD hh:mm:ss [TZON] YYYY +.br +Relative times counted from current clock time: + +|-Number["s"|"h"|"d"|"w"|"m"|"y"] +.br +where "s" means seconds, "h" hours, "d" days, "w" weeks, "m"=30d, +"y"=365.25d plus 1d added to multiplication result. +.br +Absolute seconds counted from Jan 1 1970: + =Number +.br +xorriso's own timestamps: + YYYY.MM.DD[.hh[mm[ss]]] +.br +scdbackup timestamps: + YYMMDD[.hhmm[ss]] +.br +where "A0" is year 2000, "B0" is 2010, etc. +.TP +\fB\-alter_date_r\fR type timestring iso_rr_path [***] +Like -alter_date but affecting all files below eventual directories. +.TP +\fB\-find\fR iso_rr_path [test [test ...]] [-exec action [params]] -- +A very restricted substitute for shell command find in the ISO image. +It performs an action on matching file objects at or below iso_rr_path. +.br +Tests are optional. If they are omitted then action is applied to all file +objects. If tests are given then action is applied only if all of them +match the file object. Available tests are: +.br +-name pattern +.br +Pattern is not expanded but used for comparison with +the particular file names of the eventual directory tree underneath +iso_rr_path. +.br +-type type_letter +.br +matches only files files of the given type: +"block", "char", "dir", "pipe", "file", "link", "socket", "eltorito", +"Xotic" which eventually matches what is not matched by the other types. +.br +Only the first letter is interpreted. E.g.: -find / -type d +.br +-damaged +.br +matches only files which use data blocks marked as damaged by a previous +run of -check_media. The damage info vanishes when a new ISO image gets +loaded. +.br +-undamaged +.br +matches only files which use data blocks outside the areas marked as damaged. +.br +-lba_range start_lba block_count +.br +matches only files which use data blocks within the range of start_lba +and start_lba+block_count-1. +.br +Default action is "echo", +i.e. to print the address of the found file. Other actions are certain +xorriso commands which get performed on the found files. These commands +may have specific parameters. See also their particular descriptions. +.br +"chown" and "chown_r" change the ownership and get the user id as param. E.g.: +.br + -find / -exec chown thomas -- +.br +"chgrp" and "chgrp_r" change the group attribute and get the group id as param. +E.g.: +.br + -find / name 'news*' -type d -exec chgrp_r staff -- +.br +"chmod" and "chmod_r" change access permissions and get a mode string as param. +E.g.: +.br + -find / -exec chmod a-w,a+r -- +.br +"alter_date" and "alter_date_r" change the timestamps. +They get a type character and a timestring as params. +E.g.: +.br + -find / -exec alter_date "m" "Dec 30 19:34:12 2007" -- +.br +"lsdl" prints file information like shell command ls -dl. +E.g.: +.br + -find / -exec lsdl -- +.br +"compare" performs command -compare with the found file address as iso_rr_path +and the corresponding file address below its argument disk_path_start. For this +the iso_rr_path of the -find command gets replaced by the disk_path_start. +E.g.: +.br + -find / -exec compare /home/thomas -- +.br +"update" performs command -update with the found file address as iso_rr_path. +The corresponding file address is determined like with above "compare". +.br +E.g.: +.br + -find / -exec update /home/thomas -- +.br +"rm" removes the found iso_rr_path from the image if it is not a directory with +files in it. I.e. this "rm" includes "rmdir". +.br +E.g.: +.br + -find / -name *.doc -exec rm -- +.br +"rm_r" removes the found iso_rr_path from the image, including whole directory +trees. +.br +E.g.: +.br + -find /uh/oh -name *private* -exec rm_r -- +.br +"report_damage" classifies files whether they hit a data block that is +marked as damaged. The result is printed together with the eventual address +of the first damaged byte, the maximum span of damages, file size, and the +path of the file. +.br +E.g.: +.br + -find / -damaged -exec report_damage +.br +"report_lba" prints files which are associated to image data blocks. +It tells the logical block address, the block number, the byte size, +and the path of each file. There may be reported more than one +line per file if the file is very large. In this case each line has a +different extent number in column "xt". +.br +E.g.: +.br + -find / -lba_range 302000 50000 -exec report_lba +.br +"find" performs another run of -find on the matching file address. It accepts +the same params as -find, except iso_rr_path. +E.g.: +.br + -find / -name '???' -type d -exec find -name '[abc]*' -exec chmod a-w,a+r -- +.br +If not used as last command in the line then the argument list +needs to get terminated by "--". +.TP +\fB\-mkdir\fR iso_rr_path [...] +Create empty directories if they do not exist yet. +Existence as directory generates a WARNING event, existence as +other file causes a FAILURE event. +.TP +\fB\-rmdir\fR iso_rr_path [***] +Delete empty directories. +.TP +\fB\-rollback\fR +Discard the manipulated ISO image and reload it from -indev. +.TP +\fB\-rollback_end\fR +Discard the manipulated ISO image. End program without loading a new image. +.TP +.B Writing the result: +(see also paragraph about settings below) +.TP +\fB\-commit\fR +Perform the write operation. Afterwards eventually make the +-outdev the new -dev and load the image from there. +Switch to growing mode. +(A subsequent -outdev will activate modification mode or blind growing.) +-commit is performed automatically at end of program if there +are uncommitted manipulations pending. +So, to perform a final write operation with no new -dev +and no new loading of image, rather execute option -end. +To suppress a final write, execute -rollback_end. +To eject outdev after write without new loading of image, use -commit_eject. +.br + +Writing can last quite a while. It is not unnormal with several +types of media that there is no progress visible for the first +few minutes or that the drive gnaws on the media for a few +minutes after all data have been transmitted. +xorriso and the drives are in a client-server relationship. +The drives have much freedom about what to do with the media. +Some combinations of drives and media simply do not work, +despite the promises by their vendors. +If writing fails - or even the drive gets stuck and you need +to reboot - then try other media or another drive. The reason +for such failure is hardly ever in the code of the various +burn programs but you may well try some of those listed below +under SEE ALSO. +.TP +\fB\-eject\fR "in"|"out"|"all" +Eject the media in -indev, resp. -outdev, resp. both drives. +Note: It is not possible yet to effectively eject disk files. +.TP +\fB\-commit_eject\fR "in"|"out"|"all"|"none" +Combined -commit and -eject. When writing has finished do not make +-outdev the new -dev, and load no ISO image. Rather eject +-indev and/or -outdev. Eventually give up any non-ejected drive. +.TP +\fB\-blank\fR mode +Make media ready for writing from scratch (if not -dummy is activated). +.br +This affects only the -outdev not the -indev. +If both drives are the same and if the ISO image was altered +then this command leads to a FAILURE event. +Defined modes are: + as_needed, fast, all, deformat, deformat_quickest +.br +"as_needed" cares for used CD-RW, DVD-RW and for used overwriteable media +by applying -blank "fast". It applies -format "full" to yet unformatted +DVD-RAM and BD-RE. Other media in blank state are gracefully ignored. +Media which cannot be made ready for writing from scratch cause a FAILURE +event. +.br +"fast" and "all" make CD-RW and unformatted DVD-RW re-usable, +or invalidate overwriteable ISO images. +.br +"deformat" converts overwriteable DVD-RW into unformatted ones. +.br +"deformat_quickest" is a faster way to deformat or blank DVD-RW +but produces media which are only suitable for a single session. +xorriso will write onto them only if option -close is set to "on". +.br +The progress reports issued by some drives while blanking are +quite unrealistic. Do not conclude success or failure from the +reported percentages. Blanking was successful if no SORRY event or +worse occured. +.TP +\fB\-format\fR mode +Convert unformatted DVD-RW into overwriteable ones, "de-ice" DVD+RW, format +newly purchased BD-RE or BD-R, re-format DVD-RAM or BD-RE. +.br +Defined modes are: +.br + as_needed, full, fast, by_index_<num>, fast_by_index_<num> +.br +"as_needed" formats yet unformatted DVD-RW, DVD-RAM, BD-RE, or blank +unformatted BD-R. Other media are left untouched. +.br +"full" (re-)formats DVD-RW, DVD+RW, DVD-RAM, BD-RE, or blank unformatted BD-R. +.br +"fast" does the same as "full" but tries to be quicker. +.br +"by_index_" selects a format out of the descriptor list issued by option +-list_formats. The index number from that list is to be appended to the +mode word. E.g: "by_index_3". +.br +"fast_by_index_" does the same as "by_index_" but tries to be quicker. +.br +"by_size_" selects a format out of the descriptor list which provides at +least the given size. That size is to be appended to the mode word. +E.g: "by_size_4100m". This applies to media with Defect Management. +.br +"fast_by_size_" does the same as "by_size_" but tries to be quicker. +.br +The formatting action has no effect on media if -dummy is activated. +.br +Formatting is normally needed only once during the lifetime of a media, +if ever. But it is a reason for re-formatting if: +.br + DVD-RW was deformatted by -blank, +.br + DVD+RW has read failures (re-format before next write), +.br + DVD-RAM or BD-RE shall change their amount of defect reserve. +.br +BD-R may be written unformatted or may be formatted before first use. +Formatting activates Defect Management which tries to catch and repair +bad spots on media during the write process at the expense of half speed +even with flawless media. +.br +The progress reports issued by some drives while formatting are +quite unrealistic. Do not conclude success or failure from the +reported percentages. Formatting was successful if no SORRY event +or worse occured. Be patient with apparently frozen progress. +.TP +\fB\-list_formats\fR +Put out a list of format descriptors as reported by the output drive for +the current media. The list gives the index number after "Format idx", +a MMC format code, the announced size in blocks (like "2236704s") +and the same size in MiB. +.br +MMC format codes are manifold. Most important are: +"00h" general formatting, "01h" increases reserve space for DVD-RAM, +"26h" for DVD+RW, "30h" for BD-RE with reserve space, +"31h" for BD-RE without reserve space, "32h" for BD-R. +.br +Smaller format size with DVD-RAM, BD-RE, or BD-R means more reserve space. +.TP +.B Settings for data insertion: +.TP +\fB\-file_size_limit\fR value [value [...]] -- +Set the maximum permissible size for a single data file. The values get +summed up for the actual limit. If the only value is "off" then the file +size is not limited by xorriso. Default is a limit of 100 extents, 4g -2k each: +.br + -file_size_limit 400g -200k -- +.br +When mounting ISO 9660 filesystems, old operating systems can handle only files +up to 2g -1 --. Newer ones are good up to 4g -1 --. +You need quite a new Linux kernel to read correctly the final bytes +of a file >= 4g if its size is not aligned to 2048 byte blocks. +.br +xorriso's own data read capabilities are not affected by eventual +operating system size limits. They apply to mounting only. Nevertheless, +the target filesystem of an -extract must be able to take the file size. +.TP +\fB\-not_mgt\fR code[:code[...]] +Control the behavior of the exclusion lists. +.br +Exclusion processing happens before disk_paths get mapped to the ISO image +and before disk files get compared with image files. +The absolute disk path of the source is matched against the -not_paths list. +The leafname of the disk path is matched against the patterns in the -not_leaf +list. If a match is detected then the disk path will not be regarded as an +existing file and not be added to the ISO image. +.br +Several codes are defined. +The _on/_off settings persist until they are revoked by their_off/_on +counterparts. +.br +"erase" empties the lists which were accumulated by -not_paths and -not_leaf. +.br +"reset" is like "erase" but also re-installs default behavior. +.br +"off" disables exclusion processing temporarily without invalidating +the lists and settings. +.br +"on" re-enables exclusion processing. +.br +"param_off" applies exclusion processing only to paths below disk_path +parameter of commands. I.e. explicitely given disk_paths are exempted +from exclusion processing. +.br +"param_on" applies exclusion processing to command parameters as well as +to files below such parameters. +.br +"subtree_off" with "param_on" excludes parameter paths only if they +match a -not_paths item exactly. +.br +"subtree_on" additionally excludes parameter paths which lead to a file +address below any -not_paths item. +.br +"ignore_off" treats excluded disk files as if they were missing. I.e. they +get reported with -compare and deleted from the image with -update. +.br +"ignore_on" keeps excluded files out of -compare or -update activities. +.TP +\fB\-not_paths\fR disk_path [***] +Add the given paths to the list of excluded absolute disk paths. If a given +path is relative, then the current -cdx is prepended to form an absolute path. +Eventual pattern matching happens at definition time and not when exclusion +checks are made. +.br +(Do not forget to end the list of disk_paths by "--") +.TP +\fB\-not_leaf\fR pattern +Add a single shell parser style pattern to the list of exclusions for +disk leafnames. These patterns are evaluated when the exclusion checks are +made. +.TP +\fB\-not_list\fR disk_path +Read lines from disk_path and use each of them either as -not_paths argument, +if they contain a / character, or as -not_leaf pattern. +.TP +\fB\-quoted_not_list\fR disk_path +Like -not_list but with quoted input reading rules. Each word is +handled as one argument for -not_paths resp. -not_leaf. +.TP +\fB\-follow\fR occasion[:occasion[...]] +Enable or disable resolution of symbolic links and mountpoints under +disk_paths. This applies to actions -add, -du*x, -ls*x, -findx, +and to -disk_pattern expansion. +.br +There are two kinds of follow decisison to be made: +.br +"link" is the hop from a symbolic link to its target file object. +If enabled then symbolic links are handled as their target file objects, +else symbolic links are handled as themselves. +.br +"mount" is the hop from one filesystem to another subordinate filesystem. +If enabled then mountpoint directories are handled as any other directory, +else mountpoints are handled as empty directories if they are encountered in +directory tree traversals. +.br +Less general than above occasions: +.br +"pattern" is mount and link hopping, but only during -disk_pattern expansion. +.br +"param" is link hopping for parameter words (after eventual pattern expansion). +If enabled then -ls*x will show the link targets rather than the links +themselves. -du*x, -findx, and -add will process the link targets but not +follow links in an eventual directory tree below the targets (unless "link" +is enabled). +.br +Occasions can be combined in a colon separated list. All occasions +mentioned in the list will then lead to a positive follow decision. +.br +"off" prevents any positive follow decision. Use it if no other occasion +applies. +.br +Shortcuts: +.br +"default" is equivalent to "pattern:mount:limit=100". +.br +"on" always decides positive. Equivalent to "link:mount". +.br + +Not an occasion but an optional setting is: +.br +"limit="<number> which sets the maximum number of link hops. +A link hop consists of a sequence of symbolic links and a final target +of different type. Nevertheless those hops can loop. Example: +.br + \fB$\fR ln -s .. uploop +.br +Link hopping has a builtin loop detection which stops hopping at the first +repetition of a link target. Then the repeated link is handled as itself +and not as its target. +Regrettably one can construct link networks which +cause exponential workload before their loops get detected. +The number given with "limit=" can curb this workload at the risk of truncating +an intentional sequence of link hops. +.TP +\fB\-pathspecs\fR "on"|"off" +Control parameter interpretation with xorriso actions -add and -path_list. +.br +"on" enables pathspecs of the form +.B target=source +like with program mkisofs -graft-points. +It also disables -disk_pattern expansion for command -add. +.br +"off" disables pathspecs of the form target=source +and eventually enables -disk_pattern expansion. +.TP +\fB\-overwrite\fR "on"|"nondir"|"off" +Allow or disallow to overwrite existing files in the +ISO image by files with the same user defined name. +.br +With setting "off", name collisions cause FAILURE events. +With setting "nondir", only directories are protected by such events, other +existing file types get treated with -rm before the new file gets added. +Setting "on" allows automatic -rm_r. I.e. a non-directory can replace an +existing directory and all its subordinates. +.br +If restoring of files is enabled, then the overwrite rule applies to the +target file objects on disk as well, but "on" is downgraded to "nondir". +.TP +\fB\-split_size\fR number["k"|"m"] +Set the threshold for automatic splitting of regular files. Such splitting +maps a large disk file onto a ISO directory with several part files in it. +This is necessary if the size of the disk file exceeds -file_size_limit. +Older operating systems can handle files in mounted ISO 9660 filesystems +only if they are smaller than 2 GiB resp. 4 GiB. +See also option -cut_out for more information about file parts. +.br +Default is 0 which will exclude files larger than -file_size_limit by a +FAILURE event. +A well tested -split_size is 2047m. Sizes above -file_size_limit are not +permissible. +.TP +.B Settings for result writing: +.TP +Rock Ridge info will be generated by the program unconditionally. +.TP +\fB\-joliet\fR "on"|"off" +If enabled by "on", generate Joliet info additional to Rock Ridge info. +.TP +\fB\-compliance\fR rule[:rule...] +Adjust the compliance to specifications of ISO 9660 and its extensions. In some +cases it is worth to deviate a bit in order to circumvent bugs of the intended +reader system or to get inofficial extra features. +.br +There are several adjustable rules which have a keyword each. If they +are mentioned with this option then their rule gets added to the relaxation +list. This list can be erased by rules "strict" or "clear". It can be reset +to its start setting by "default". All of the following relaxation rules +can be revoked individually by appending "_off". Like "deep_paths_off". +.br +Rule keywords are: +.br +"omit_version" do not add versions (";1") to the file names. +.br +"deep_paths" allow ISO file paths deeper than 8 levels. +.br +"long_paths" allow ISO file paths longer than 255 characters. +.br +"long_names" allow up to 37 characters with ISO file names. +.br +"no_force_dots" do not add a dot to filenames which have none. +.br +"lowercase" allow lowercase characters in ISO file names. +.br +"full_ascii" allow all ASCII characters in ISO file names. +.br +"joliet_long_paths" allow Joliet paths longer than 240 characters. +.br +"always_gmt" store timestamps in GMT representation with timezone 0. +.br +"old_rr" use Rock Ridge version 1.10 (needed if the intended reader +system does not recognize Rock Ridge 1.12 signature). +.br +"rec_mtime" record with ISO files the disk file's mtime and not the +creation time of the image. +.br +Default setting is "clear:deep_paths:long_paths:always_gmt". +.br +Note: The term "ISO file" means the plain ISO 9660 names wnd attributes +which get visible if the reader ignores Rock Ridge. +.TP +\fB\-volid\fR text +Specify the volume ID. xorriso accepts any text up to 32 characters, +but according to rarely obeyed specs stricter rules apply: +.br +ECMA 119 demands ASCII characters out of [A-Z0-9_]. Like: "IMAGE_23" +.br +Joliet allows 16 UCS-2 characters. Like: "Windows name" +.br +Be aware that the volume id might get used automatically as name of the +mount point when the media is inserted into a playful computer system. +.br +If an ISO image gets loaded while the volume ID is set to default "ISOIMAGE" +or to "", then the volume ID of the loaded image will become the effective +volume id for the next write run. But as soon as command -volid is performed +afterwards, this pending id is overridden by the new setting. +.br +Consider this when setting -volid "ISOIMAGE" before executing -dev, -indev, +or -rollback. +If you insist in -volid "ISOIMAGE", set it again after those commands. +.TP +\fB\-publisher\fR text +Set the publisher string to be written with the next -commit. Permissible +are up to 128 characters. +.TP +\fB\-application_id\fR text +Set the application id string to be written with the next -commit. Permissible +are up to 128 characters. +.TP +\fB\-out_charset\fR character_set_name +Set the character set to which file names get converted when writing an +image. See paragraph "Character sets" for more explanations. +When loading the written image after -commit the setting of -out_charset +will be copied to -in_charset. +.TP +\fB\-uid\fR uid +User id to be used for all files when the new ISO tree gets written to media. +.TP +\fB\-gid\fR gid +Group id to be used for all files when the new ISO tree gets written to media. +.TP +\fB\-speed\fR number[k|m|c|d|b] +Set the burn speed. Default is 0 = maximum speed. +Speed can be given in media dependent numbers or as a +desired throughput per second in MMC compliant kB (= 1000) +or MB (= 1000 kB). Media x-speed factor can be set explicity +by "c" for CD, "d" for DVD, "b" for BD, "x" is optional. +.br +Example speeds: +.br + 706k = 706kB/s = 4c = 4xCD +.br + 5540k = 5540kB/s = 4d = 4xDVD +.br +If there is no hint about the speed unit attached, then the +media in the -outdev will decide. Default unit is CD = 176.4k. +.br +MMC drives usually activate their own idea of speed and take +the speed value given by the burn program only as upper limit +for their own decision. +.TP +\fB\-stream_recording\fR "on"|"off" +Setting "on" tries to circumvent the management of defects on DVD-RAM, BD-RE, +or BD-R. Defect management keeps partly damaged media usable. But it reduces +write speed to half nominal speed even if the media is in perfect shape. +For the case of flawless media, one may use -stream_recording "on" to get +full speed. +.TP +\fB\-dummy\fR "on"|"off" +If "on" then simulate burning or refuse with FAILURE event if +no simulation is possible, do neither blank nor format. +.TP +\fB-fs\fR number["k"|"m"] +Set the size of the fifo buffer which smoothens the data +stream from ISO image generation to media burning. Default +is 4 MiB, minimum 64 kiB, maximum 1 GiB. +The number may be followed by letter "k" or "m" +which means unit is kiB (= 1024) or MiB (= 1024 kiB). +.TP +\fB\-close\fR "on"|"off" +If "on" then mark the written media as not appendable +any more (if possible at all with the given type of target media). +.br +This is the contrary of cdrecord, wodim, cdrskin option -multi, +and is one aspect of growisofs option -dvd-compat. +.TP +\fB\-padding\fR number["k"|"m"] +Append the given number of extra bytes to the image stream. +This is a traditional remedy for a traditional bug in block +device read drivers. Needed only for CD recordings in TAO mode. +Since one can hardly predict on what media an image might end up, +xorriso adds the traditional 300k of padding by default to all images. +.br +For images which will never get to a CD it is safe to use -padding 0 . +.TP +.B El Torito bootable ISO images: +.PP +Contrary to published specifications many BIOSes will load an El Torito +object from the first session on media and not from the last one, which +gets mounted by default. This makes no problems with overwriteable media, +because they appear to inadverted readers as one single session. +.br +But with multi-session media CD-R[W], DVD-R[W], DVD+R, it implies that the +whole bootable system has to reside already in the first session and that +the last session still has to bear all files which the booted system expects +after eventually mounting the ISO image. +.br +If ISOLINUX is known to be present on media then it is advised to patch it +when a follow-up session gets written. But one should not rely on the +capability to influence the bootability of the existing sessions, unless one +can assume overwriteable media. +.TP +\fB\-boot_image\fR "any"|"isolinux" +.br + "discard"|"keep"|"patch"|"show_status"|bootspec +.br +Define the handling of an eventual El Torito object which has +been read from an existing ISO image or defines how to make a prepared +ISOLINUX file set bootable. +.br + +All types ("any") of El Torito boot images can be discarded or kept unaltered. +The latter makes only sense if the format of the boot image is +relocatable without content changes. +.br +With any type, "show_status" will print what is known about the loaded image +and its designated fate. +.br +An existing boot image of type "isolinux" can be discarded or it can be +patched to match its relocation. In the latter case the resulting ISO image +stays bootable if the boot image was really produced by ISOLINUX. +.br +CAUTION: +This is an expert option. +xorriso cannot recognize the inner form of boot images. +So the user has already to know about the particular needs of the +boot image which is present on the input media. +.br +Most safe is the default: -boot_image "any" "discard". +.br + +A bootspec is a word of the form name=value and is used to describe the +activation of a ISOLINUX boot image by an El Torito record and eventually +a MBR. The names "dir" and "bin_path" lead to boot image activation. +.br +On all media types this is possible within the first session. In further +sessions an existing boot image can get replaced by a new one, but depending +on the media type this may have few effect at boot time. See above. +.br +The ISOLINUX files have to be added to the ISO image by normal means +(image loading, -map, -add, ...) and should reside either in ISO image +directory /isolinux or in /boot/isolinux . +In that case it suffices to use as bootspec the text "dir=/isolinux" or +"dir=/boot/isolinux". E.g.: +.br + -boot_image isolinux dir=/boot/isolinux +.br +which bundles these individual settings: +.br + -boot_image isolinux bin_path=/boot/isolinux/isolinux.bin +.br + -boot_image isolinux cat_path=/boot/isolinux/boot.cat +.br + -boot_image isolinux load_size=2048 +.br +bin_path depicts the binary program which is to be started by the BIOS at +boot time. It is among the files produced by ISOLINUX. +.br +An El Torito boot catalog file gets inserted into the ISO image with address +cat_path at -commit time. +It is subject to normal -overwrite and -reassure processing if there is already +a file with the same name. +.br +Bootspec "isohybrid=off" disables MBR generation, "isohybrid=on" prevents the +write session if not the isohybrid signature is found in the bin_path file. +Default is "isohybrid=auto" which silently omits the MBR if the signature is +missing. +.TP +.B Character sets: +.PP +File names are strings of non-zero bytes with 8 bit each. Unfortunately +the same byte string may appear as different peculiar national characters +on differently nationalized computers. +The meanings of byte codes are defined in \fBcharacter sets\fR which have +names. Shell command iconv -l lists them. +.br +Character sets should not matter as long as only english alphanumeric +characters are used for file names or as long as all writers and readers +of the media use the same character set. +Outside these constraints it may be necessary to let xorriso convert byte +codes. +.br +There is an input conversion from input character set to the local character +set which applies when an ISO image gets loaded. A conversion from local +character set to the output character set is performed when an +image tree gets written. The sets can be defined independently by options +-in_charset and -out_charset. Normally one will have both identical, if ever. +.br +If conversions are desired then xorriso needs to know the name of the +local character set. xorriso can inquire the same info as shell command +"locale" with argument "charmap". This may be influenced by environment +variables LC_ALL, LC_CTYPE, or LANG and should match the expectations of +the terminal. +.TP +\fB\-charset\fR character_set_name +Set the character set from which to convert file names when loading an +image and to which to convert when writing an image. +.TP +\fB\-local_charset\fR character_set_name +Override the system assumption of the local character set name. +If this appears necessary, one should consider to set -backslash_codes to +"on" in order to avoid dangerous binary codes being sent to the terminal. +.TP +.B Exception processing: +.PP +Since the tasks of xorriso are manifold and prone to external influence, there +may arise the need for xorriso to report and handle problem events. +.br +Those events get classified when they are detected by one of the software +modules and forwarded to reporting and evaluation modules which decide about +reactions. Event classes are sorted by severity: +.br +"NEVER" The upper end of the severity spectrum. +.br +"ABORT" The program is being aborted and on its way to end. +.br +"FATAL" The main purpose of the run failed +or an important resource failed unexpectedly. +.br +"FAILURE" An important part of the job could not be performed. +.br +"MISHAP" A FAILURE which can be tolerated during ISO image generation. +.br +"SORRY" A less important part of the job could not be performed. +.br +"WARNING" A situation is suspicious of being not intended by the user. +.br +"HINT" A proposal to the user how to achieve better results. +.br +"NOTE" A harmless information about noteworthy circumstances. +.br +"UPDATE" A pacifier message during long running operations. +.br +"DEBUG" A message which would only interest the program developers. +.br +"ALL" The lower end of the severity spectrum. +.TP +\fB\-abort_on\fR severity +Set the severity threshold for events to abort the program. +.br +Useful: "NEVER", "ABORT", "FATAL", "FAILURE" , "MISHAP", "SORRY" +.br +It may become necessary to abort the program anyway, despite +the setting by this option. Expect not many "ABORT" events to +be ignorable. +.br +A special property of this option is that it works preemptive if given as +program start argument. I.e. the first -abort_on setting among the +start arguments is in effect already when the first operations of xorriso +begin. Only "-abort_on" with dash "-" is recognized that way. +.TP +\fB\-return_with\fR severity exit_value +Set the threshold and exit_value to be returned at program end if no abort +has happened. This is to allow xorriso to go on after problems but to get +a failure indicating exit value from the program, nevertheless. +Useful is a value lower than the -abort_on threshold, down to "WARNING". +.br +exit_value may be either 0 (indicating success to the starter of the program) +or a number between 32 and 63. Some other exit_values are used by xorriso if +it decides to abort the program run: +.br +1=abort due to external signal +.br +2=no program arguments given +.br +3=creation of xorriso main object failed +.br +4=failure to start libburnia-project.org libraries +.br +5=program abort during argument processing +.br +6=program abort during dialog processing +.TP +\fB\-report_about\fR severity +Set the threshold for events to be reported. +.br +Useful: "SORRY", "WARNING", "HINT", "NOTE", "UPDATE", "DEBUG", "ALL" +.br +Regardless what is set by -report_about, messages get always reported if they +reach the severity threshold of -abort_on . +.br +Event messages are sent to the info channel "I" which is usually stderr +but may be influenced by command -pkt_output. +Info messages which belong to no event get attributed severity "NOTE". +.br +A special property of this option is that the first -report_about setting +among the start arguments is in effect already when the first operations +of xorriso begin. Only "-report_about" with dash "-" is recognized that way. +.TP +\fB\-error_behavior\fR occasion behavior +Control the program behavior at problem event occasions. +For now this applies to occasions "image_loading" which is given while +an image tree is read from the input device, and to "file_extraction" which +is given with osirrox options like -extract. +.br +With "image_loading" there are three behaviors available: +.br +"best_effort" goes on with reading after events with severity below FAILURE +if the threshold of option -abort_on allows this. +.br +"failure" aborts image tree reading on first event of at least SORRY. +It issues an own FAILURE event. +.br +"fatal" acts like "failure" but issues the own event as FATAL. +This is the default. +.br +With occasion "file_extraction" there are three behaviors: +.br +"keep" maintains incompletely extracted files on disk. This is the default. +.br +"delete" removes files which encountered errors during content extraction. +.br +"best_effort" starts a revovery attempt by means of -extract_cut. +.TP +.B Dialog mode control: +.TP +\fB\-dialog\fR "on"|"off"|"single_line" +Enable or disable to enter dialog mode after all arguments are processed. +In dialog mode input lines get prompted via readline or from stdin. +.br +Mode "on" supports input of newline characters within quotation marks and +line continuation by trailing backslash outside quotation marks. +Mode "single_line" does not. +.TP +\fB\-page\fR length width +Describe terminal to the text pager. See also above, paragraph Result pager. +.br +If parameter length is nonzero then the user gets prompted after that +number of terminal lines. Zero length disables paging. +.br +Parameter width is the number of characters per terminal line. It is used +to compute the number of terminal lines which get occupied by an output line. +A usual terminal width is 80. +.TP +\fB\-use_readline\fR "on"|"off" +If "on" then use readline for dialog. Else use plain stdin. +.br +See also above, paragraph Dialog, Readline, Result pager. +.TP +\fB\-reassure\fR "on"|"tree"|"off" +If "on" then ask the user for "y" or "n": +.br +before deleting or overwriting any file in the ISO image, +.br +before overwriting any disk file during restore operations, +.br +before rolling back pending image changes, +.br +before committing image changes to media, +.br +before changing the input drive, +.br +before blanking or formatting media, +.br +before ending the program. +.br +With setting "tree" the reassuring prompt will appear for an eventual +directory only once and not for each file in its whole subtree. +.br +Setting "off" silently kills any kind of image file object resp. performs +above irrevocable actions. +.br +To really produce user prompts, option -dialog needs to be set to "on". +Note that the prompt does not appear in situations where file removal +is forbidden by option -overwrite. -reassure only imposes an additional +curb for removing existing file objects. +.br +Be aware that file objects get deleted from the ISO image immediately +after confirmation. They are gone even if the running command gets aborted +and its desired effect gets revoked. In case of severe mess-up, consider to +use -rollback to revoke the whole session. +.TP +.B Drive and media related inquiry actions: +.TP +\fB\-devices\fR +Show list of available MMC drives with the addresses of +their libburn standard device files. +.br +This is only possible when no ISO image changes are pending. +After this option was executed, there is no drive current +and no image loaded. Eventually one has to aquire a drive again. +.br +In order to be visible, a device has to offer rw-permissions +with its libburn standard device file. Thus it might be only the +.B superuser +who is able to see all drives. +.br +Drives which are occupied by other processes get not shown. +.TP +\fB\-toc\fR +.br +Show media specific table of content. This is the media session history, +not the ISO image directory tree. +.br +In case of overwriteable media holding a valid ISO image, a single session +gets fabricated from the ISO image size info. But if the first session on the +overwriteable media was written by xorriso then in most cases a complete +session history can be emulated. +.br +A drive which is incapable of writing may show any media as CD-ROM or DVD-ROM +with only one or two sessions on it. The last of these sessions is supposed +to be the most recent real session then. +.br +Some read-only drives and media show no usable session history at all. +Eventually option -rom_toc_scan might help. +.TP +\fB\-mount_cmd\fR drive entity id path +Emit an appropriate command line for mounting the ISO session +indicated by drive, entity and id. +The result will be different on Linux and on FreeBSD. +.br +drive can be "indev" or "outdev" to indicate already aquired drives, +or it can be the path of a not yet acquired drive. +Prefix "stdio:" for non-MMC drives is not mandatory. +.br +entity must be either "sbsector" , "track" , "session" , "volid" +or "auto". See also option -load. +.br +id gives the superblock sector address, the track number, the session number, +or a search pattern for the volume id respectively. +.br +path will be used as mount point and must already exist as a directory. +.br +The command gets printed to the result channel. See option -mount +for direct execution of this command. +.TP +\fB\-session_string\fR drive entity id format +Print to the result channel a text which gets composed according to +format and the parameters of the addressed session. +.br +Formats "linux:"path or "freebsd:"path produce the output of -mount_cmd +for the given operating systems. +.br +In other texts xorriso will substitute the following parameter names. +An optional prefix "string:" will be removed. +.br +"%device%" will be substituted by the mountable device path of the drive +address. +.br +"%sbsector%" will be substituted by the session start sector. +.br +"%track%", "%session%", "%volid%" will be substituted by track number, +session number, resp. volume id of the depicted session. +.TP +\fB\-print_size\fR +Print the foreseeable consumption of 2048 byte blocks +by next -commit. This can last a while as a -commit gets +prepared and only in last moment is revoked by this option. +.TP +\fB\-tell_media_space\fR +Print available space on output media and the free space after +subtracting already foreseeable consumption by next -commit. +.TP +.B Navigation in ISO image and disk filesystem: +.TP +\fB\-cd\fR iso_rr_path +Change the current working directory in the emerging ISO +image as it is at the moment. This is prepended to iso_rr_paths +which do not begin with '/'. +.br +It is possible to set the working directory to a path which does not exist +yet in the ISO image. The necessary parent directories will be created when +the first file object is inserted into that virtual directory. +Use -mkdir if you want to enforce the existence of the directory already at +first insertion. +.TP +\fB\-cdx\fR disk_path +Change the current working directory on filesystem. +To be prepended to disk_paths which do not begin with '/'. +.TP +\fB\-pwd\fR +.br +Tell the current working directory in the ISO image. +.TP +\fB\-pwdx\fR +.br +Tell the current working directory on local filesystem. +.TP +\fB\-ls\fR iso_rr_pattern [***] +List files in the ISO image which match shell patterns +(i.e. with wildcards '*' '?' '[a-z]'). +If a pattern does not begin with '/' then it is compared with addresses +relative to -cd, the current working directory in the ISO image. +.br +Directories are listed by their content rather than as single file item. +.br +Pattern expansion may be disabled by command -iso_rr_pattern. +.TP +\fB\-lsd\fR iso_rr_pattern [***] +Like -ls but listing directories as themselves and not by their content. +This resembles shell command ls -d. +.TP +\fB\-lsl\fR iso_rr_pattern [***] +Like -ls but also list some of the file attributes. +Output format resembles shell command ls -ln. +.TP +\fB\-lsdl\fR iso_rr_pattern [***] +Like -lsd but also list some of the file attributes. +Output format resembles shell command ls -dln. +.TP +\fB\-lsx\fR disk_pattern [***] +List files on local filesystem which match shell patterns. Patterns which do +not begin with '/' are used relative to -cdx, the current working directory in +the local filesystem. +.br +Directories are listed by their content rather than as single file item. +.br +Pattern expansion may be disabled by command -disk_pattern. +.TP +\fB\-lsdx\fR disk_pattern [***] +Like -lsx but listing directories as themselves and not by their content. +This resembles shell command ls -d. +.TP +\fB\-lslx\fR disk_pattern [***] +Like -lsx but also listing some of the file attributes. +Output format resembles shell command ls -ln. +.TP +\fB\-lsdlx\fR disk_pattern [***] +Like -lsdx but also listing some of the file attributes. +Output format resembles shell command ls -dln. +.TP +\fB\-du\fR iso_rr_pattern [***] +Recursively list size of directories and files in the ISO image +which match one of the patterns. +similar to shell command du -k. +.TP +\fB\-dus\fR iso_rr_pattern [***] +List size of directories and files in the ISO image +which match one of the patterns. +Similar to shell command du -sk. +.TP +\fB\-dux\fR disk_pattern [***] +Recursively list size of directories and files in the local filesystem +which match one of the patterns, similar to shell command du -k. +.TP +\fB\-dusx\fR disk_pattern [***] +List size of directories and files in the local filesystem +which match one of the patterns. +Similar to shell command du -sk. +.TP +\fB\-findx\fR disk_path [-name pattern] [-type t] [-exec action [params]] -- +Like -find but operating on local filesystem and not on the ISO image. +This is subject to the settings of -follow. +.br +Find accepts the same -type arguments as -find. Additionally it recognizes +type "mountpoint" (or "m"). It matches subdirectories which reside on a +different device than their parent. It never matches the disk_path +given as start address for -findx. +.br +-findx accepts the -exec actions as does -find. But except the following few +actions it will allways perform action "echo". +.br +"in_iso" iso_rr_path_start reports the path if its counterpart exist in +the ISO image. For this the disk_path of the -find command gets replaced +by iso_rr_path_start. E.g.: +.br + -findx /home -exec in_iso / +.br +"not_in_iso" iso_rr_path_start reports the path if its counterpart does +not exist in the ISO image. The report format is the same as with command +-compare. +E.g. +.br + -findx /home/thomas -exec not_in_iso /thomas_on_cd +.br +"add_missing" iso_rr_path_start adds the counterpart if it does not yet +exist in the ISO image. +E.g. +.br + -findx /home/thomas -exec add_missing /thomas_on_cd +.br +"is_full_in_iso" iso_rr_path_start reports if the counterpart in the ISO image +contains files. To be used with -type "m" to report mount points. +.br +"empty_iso_dir" iso_rr_path_start deletes all files from the counterpart +in the ISO image. To be used with -type "m" to truncate mount points. +.TP +\fB\-compare\fR disk_path iso_rr_path +Compare attributes and eventual data file content of a fileobject in the +local filesystem with a file object in the ISO image. The iso_rr_path may +well point to an image file object which is not yet committed, i.e. of which +the data content still resides in the local filesystem. Such data content is +prone to externally caused changes. +.br +If iso_rr_path is empty then disk_path is used as path in the ISO image too. +.br +Differing attributes are reported in detail, differing content is summarized. +Both to the result channel. In case of no differences no result lines are +emitted. +.TP +\fB\-compare_r\fR disk_path iso_rr_path +Like -compare but working recursively. I.e. all file objects below both +addresses get compared whether they have counterparts below the other address +and whether both counterparts match. +.TP +\fB\-compare_l\fR disk_prefix iso_rr_prefix disk_path [***] +Perform -compare_r with each of the disk_path arguments. iso_rr_path will be +composed from disk_path by replacing disk_prefix by iso_rr_prefix. +.TP +.B Evaluation of readability and recovery: +.PP +It is not uncommon that optical media produce read errors. The reasons may be +various and get obscured by error correction which is performed by the drives +and based on extra data on the media. If a drive returns data then one can +quite trust that they are valid. But at some degree of read problems the +correction will fail and the drive is supposed to indicate error. +.br +xorriso can scan the media for readable data blocks, classify them according +to their read speed, save them to a file, and keep track of successfuly saved +blocks for further tries on the same media. +.TP +\fB\-check_media\fR [option [option ...]] -- +Try to read data blocks from the indev drive, eventually copy them to a +disk file, and finally report about the encountered quality. Several options +may be used to modify the default behavior. +.br +The options given with this command override the default settings which +may have been changed by option -check_media_defaults. See there for a +description of options. +.br +The result list tells intervals of 2 KiB blocks with start address, number +of blocks and quality. Qualities which begin with "+" are +supposed to be valid readable data. Qualities with "-" are no valid data. +.br +Alternatively it is possible to report damaged files rather than blocks. +.TP +\fB\-check_media_defaults\fR [option [option ...]] -- +Preset options for runs of -check_media, -extract_cut and best_effort +file extraction. Eventual options given with -check_media will override the +preset options. -extract_cut will override some options automatically. +.br +An option consists of a keyword, a "=" character, and a value. Options +may override each other. So their sequence matters. +.br +The default setting at program start is: +.br +use=indev what=tracks min_lba=-1 max_lba=-1 retry=default +time_limit=28800 item_limit=100000 +.br +abort_file=/var/opt/xorriso/do_abort_check_media +.br +data_to='' sector_map='' map_with_volid=off patch_lba0=off report=blocks +.br +Option "reset=now" restores these startup defaults. +.br +Non-default options are: +.br +"report=files" lists the files which use damaged blocks (not with use=outdev). +The format is like with find -exec report_damage. +.br +"report=blocks_files" first lists damaged blocks and then affected files. +.br +"use=outdev" reads from the output drive instead of the input drive. This +avoids loading the ISO image tree from media. +.br +"what=disc" scans the payload range of a media without respecting track gaps. +.br +"min_lba=" omits all blocks with addresses lower than the option value. +.br +"max_lba=" switches to what=disc and omits all blocks above its option value. +.br +"retry=on" forces read retries with single blocks when the normal read +chunk produces a read error. By default, retries are only enabled with CD +media. "retry=off" forbits retries for all media types. +.br +"abort_file=" gives the path of the file which may abort a scan run. Abort +happens if the file exists and its mtime is not older than the start time +of the run. Use shell command "touch" to trigger this. +Other than an aborted program run, this will report the tested and untested +blocks and go on with running xorriso. +.br +"time_limit=" gives the number of seconds after which the scan shall be +aborted. This is useful for unattended scanning of media which may else +overwork the drive in its effort to squeeze out some readable blocks. +Abort may be delayed by the drive gnawing on the last single read operation. +Value -1 means unlimited time. +.br +"item_limit=" gives the number of report list items after which to abort. +Value -1 means unlimited item number. +.br +"data_to=" copies the valid blocks to the file which is given as option value. +.br +"sector_map=" tries to read the file given by option value as +sector bitmap and to store such a map file after the scan run. +The bitmap tells which blocks have been read successfully in previous runs. +It allows to do several scans on the same media, eventually with intermediate +eject, in order to collect readable blocks whenever the drive is lucky enough +to produce them. The stored file contains a human readable TOC of tracks +and their start block addresses, followed by binary bitmap data. +.br +"map_with_volid=on" examines tracks whether they are ISO images and eventually +prints their volume ids into the human readable TOC of sector_map=. +.br +"patch_lba0=on" transfers within the data_to= file a copy of the currently +loaded session head to the start of that file and patches it to be valid +at that position. +This makes the loaded session the default session of the image file +when it gets mounted or loaded as stdio: drive. But it usually makes +the original session 1 inaccessible. +.br +"patch_lba0=force" performs "patch_lba0=on" even if xorriso believes +that the copied data are not valid. +.br +"patch_lba0=" may also bear a number. If it is 32 or higher it is taken as +start address of the session to be copied. In this case it is not necessary to +have an -indev and a loaded image. ":force" may be appended after the number. +.br +"use=sector_map" does not read any media but loads the file given by option +sector_map= and processes this virtual outcome. +.TP +.B osirrox restore options: +.PP +Normally xorriso only writes to disk files which were given as stdio: +pseudo-drives or as log files. +But its alter ego, osirrox, is able to extract file objects +from ISO images and to create, overwrite, or delete file objects on disk. +.br +Disk file exclusions by -not_mgt, -not_leaf, -not_paths apply. +If disk file objects already exist then the settings of -overwrite and +-reassure apply. But -overwrite "on" only triggers the behavior +of -overwrite "nondir". I.e. directories cannot be deleted. +.br +Access permissions of files in the ISO image do not restrict restoring. +The directory permissions on disk have to allow rwx. +.TP +\fB\-osirrox\fR "on"|"device_files"|"off"[:option:...] +Setting "off" disables disk filesystem manipulations. This is the default +unless the program was started with leafname "osirrox". Elsewise +the capability to restore files can be enabled explicitly by -osirrox "on". +.br +To enable restoring of special files by "device_files" is potentially +dangerous. +The meaning of the number st_rdev (see man 2 stat) depends much on the +operating system. Best is to restore device files only to the same system +from where they were copied. If not enabled, device files in the ISO image +are ignored during restore operations. +.br +Due to a bug of previous versions, device files from previous sessions might +have been altered to major=0, minor=1. So this combination does not get +restored. +.br +Option "concat_split_on" is default. It enables restoring of split file +directories as data files if the directory contains a complete collection +of -cut_out part files. With option "concat_split_off" such directories are +handled like any other ISO image directory. +.br +Option "auto_chmod_off" is default. If "auto_chmod_on" is set then access +restrictions for disk directories get circumvented if those directories +are owned by the effective user who runs xorriso. This happens by temporarily +granting rwx permission to the owner. It will not work with ACL restrictions. +.TP +\fB\-extract\fR iso_rr_path disk_path +Restore the file objects at and underneath iso_rr_path to their corresponding +addresses at and underneath disk_path. +This is the inverse of -map or -update_r. +.br +If iso_rr_path is a directory and disk_path is an existing directory then +both trees will be merged. Directory attributes get extracted only if the disk +directory is newly created by the restore operation. +Disk files get removed only if they are to be replaced +by file objects from the ISO image. +.br +As many attributes as possible are copied together with restored +file objects. +.TP +\fB\-extract_single\fR iso_rr_path disk_path +Like -extract, but if iso_rr_path is a directory then its sub tree gets not +restored. +.TP +\fB\-extract_l\fR iso_rr_prefix disk_prefix iso_rr_path [***] +Perform -extract with each of the iso_rr_path arguments. disk_path will be +composed from iso_rr_path by replacing iso_rr_prefix by disk_prefix. +.TP +\fB\-extract_cut\fR iso_rr_path byte_offset byte_count disk_path +Copy a byte interval from a data file out of an ISO image into a newly created +disk file. +Two restrictions apply: +.br +The data bytes of iso_rr_path need to be already stored in the loaded ISO image +and byte_offset must be a multiple of 2048, e.g. an integer with suffix +s, m, or g. +.br +This option is implemented by a special run of -check_media and governed by +most of the options which can be set by -check_media_defaults. +Its main purpose is to allow handling of large files if they are not supported +by mount -t iso9660 and if the reading system is unable to buffer them as +a whole. +.TP +\fB\-cpx\fR iso_rr_path [***] disk_path +Extract single leaf file objects from the ISO image and store them under +the address given by disk_path. If more then one iso_rr_path is given then +disk_path must be a directory or non-existent. In the latter case it gets +created and the extracted files get installed in it with the same leafnames. +.br +Missing directory components in disk_path will get created, if possible. +.br +Directories are allowed as iso_rr_path only with -osirrox "concat_split_on" +and only if they actually represent a complete collection of -cut_out split +file parts. +.TP +\fB\-cpax\fR iso_rr_path [***] disk_path +Like -cpx but restoring mtime, atime as in ISO image and trying to set +ownership and group as in ISO image. +.TP +\fB\-cp_rx\fR iso_rr_path [***] disk_path +Like -cpx but also extracting whole directory trees from the ISO image. +.br +The resulting disk paths are determined as with shell command cp -r : +If disk_path is an existing directory then the trees will be inserted or merged +underneath this directory and will keep their leaf names. The ISO directory "/" +has no leaf name and thus gets mapped directly to disk_path. +.TP +\fB\-cp_rax\fR iso_rr_path [***] disk_path +Like -cp_rx but restoring mtime, atime as in ISO image and trying to set +ownership and group as in ISO image. +.TP +\fB\-paste_in\fR iso_rr_path disk_path byte_offset byte_count +Read the content of a ISO data file and write it into a data file on disk +beginning at the byte_offset. Write at most byte_count bytes. +This is the inverse of option -cut_out. +.TP +\fB\-mount\fR drive entity id path +Produce the same line as -mount_cmd and then execute it as external program run +after giving up the depicted drive. +This demands -osirrox to be enabled and normally will succeed only for the +superuser. For safety reasons the mount program is only executed if it is +reachable as /bin/mount or /sbin/mount. +.TP +.B Command compatibility emulations: +.PP +Writing of ISO 9660 on CD is traditionally done by program mkisofs +as ISO 9660 image producer and cdrecord as burn program. +xorriso does not strive for their comprehensive emulation. +Nevertheless it is ready to perform some of its core tasks under control +of commands which in said programs trigger comparable actions. +.TP +\fB\-as\fR personality option [options] -- +.br +Perform its variable length option list as sparse emulation of the program +depicted by the personality word. +.br + +Personality "\fBmkisofs\fR" accepts the options listed with: +.br + -as mkisofs -help -- +.br +Among them: -R (always on), -J, -o, -M, -C, -path-list, -m, -exclude-list, +-f, -print-size, -pad, -no-pad, -V, -v, -version, -graft-points, +-no-emul-boot, -b, -c, -boot-info-table, -boot-load-size, -input-charset, +-output-charset, pathspecs as with xorriso -add. +A lot of options are not supported and lead to failure of the mkisofs +emulation. Some are ignored, but better do not rely on this tolerance. +.br +-graft-points is equivalent to -pathspecs on. Note that pathspecs without "=" +are interpreted differently than with xorriso option -add. Directories get +merged with the root directory of the ISO image, other filetypes get mapped +into that root directory. +.br +Other than with the "cdrecord" personality there is no automatic -commit at +the end of a "mkisofs" option list. Verbosity settings -v (= "UPDATE") and +-quiet (= "SORRY") persist. The output file, eventually chosen with -o, +persists until things happen like -commit, -rollback, -dev, or end of xorriso. +-pacifier gets set to "mkisofs" if files are added to the image. +.br +If pathspecs are given and if no output file was chosen before or during the +"mkisofs" option list, then standard output (-outdev "-") will get into effect. +If -o points to a regular file, then it will be truncated to 0 bytes +when finally writing begins. This truncation does not happen if the drive +is chosen by xorriso options before or after -as mkisofs. +Directories and symbolic links are no valid -o targets. +.br +Writing to stdout is possible only if -as "mkisofs" was among the start +arguments or if other start arguments pointed the output drive to +standard output. +.br +Not original mkisofs options are --quoted_path_list (see -quoted_path_list) +and isolinux_mbr= (see -boot_image isolinux isohybrid=). +.br +Personalites "\fBxorrisofs\fR", "\fBgenisoimage\fR", and "\fBgenisofs\fR" +are aliases for "mkisofs". +.br +If xorriso is started with one of the leafnames "xorrisofs", "genisofs", +"mkisofs", or "genisoimage", then it automatically prepends -as "genisofs" +to the command line arguments. I.e. all arguments will be interpreted mkisofs +style until "--" is encountered. From then on, options are interpreted +as xorriso options. +.br + +Personality "\fBcdrecord\fR" accepts the options listed with: +.br + -as cdrecord -help -- +.br +Among them: -v, dev=, speed=, blank=, fs=, -eject, -atip, padsize=, tsize=, +-isosize, -multi, -msinfo, --grow_overwriteable_iso, write_start_address=, +track source file path or "-" for standard input as track source. +.br +It ignores most other options of cdrecord and cdrskin but refuses on +-audio, -scanbus, and on blanking modes unknown to xorriso. +.br +The scope is only a single data track per session to be written +to blank, overwriteable, or appendable media. The media gets closed if +closing is applicable and not option -multi is present. +.br +An eventually aquired input drive is given up. +This is only allowed if no image changes are pending. +.br +dev= must be given as xorriso device address. Adresses like 0,0,0 or ATA:1,1,0 +are not supported. +.br +If a track source is given, then an automatic -commit happens at the end of +the "cdrecord" option list. +.br +--grow_overwriteable_iso enables emulation of multi-session on overwriteable +media. To enable emulation of a TOC, the first session needs -C 0,32 with +-as mkisofs (but no -M) and --grow_overwriteable_iso write_start_address=32s +with -as cdrecord. +.br +A much more elaborate libburn based cdrecord emulator is the program cdrskin. +.br +Personalites "\fBxorrecord\fR", "\fBwodim\fR", and "\fBcdrskin\fR" are aliases +for "cdrecord". +.br +If xorriso is started with one of the leafnames "xorrecord", "cdrskin", +"cdrecord", or "wodim", then it automatically prepends -as "cdrskin" +to the command line arguments. I.e. all arguments will be interpreted cdrecord +style until "--" is encountered and an eventual commit happens. +From then on, options are interpreted as xorriso options. +.TP +\fB\-pacifier\fR behavior_code +Control behavior of UPDATE pacifiers during write operations. +The following behavior codes are defined: +.br +"xorriso" is the default format: +.br +Writing: sector XXXXX of YYYYYY [fifo active, nn% fill] +.br +"cdrecord" looks like: +.br +X of Y MB written (fifo nn%) [buf mmm%] +.br +"mkisofs" +.br +nn% done, estimate finish Tue Jul 15 20:13:28 2008 +.TP +.B Scripting, dialog and program control features: +.TP +\fB\-no_rc\fR +.br +Only if used as first command line argument this option +prevents reading and interpretation of eventual startup +files. See section FILES below. +.TP +\fB\-options_from_file\fR fileaddress +Read quoted input from fileaddress and executes it like dialog lines. +.TP +\fB\-help\fR +.br +Print helptext. +.TP +\fB\-version\fR +Print program name and version. +.TP +\fB\-history\fR textline +Copy textline into libreadline history. +.TP +\fB\-status\fR [mode|filter] +Print the current settings of xorriso. +Modes: +.br + short... print only important or altered settings +.br + long ... print all settings including defaults +.br + long_history like long plus history lines +.br +Filters begin with '-' and are compared literally against the +output lines of -status:long_history. A line is put out only +if its start matches the filter text. No wildcards. +.TP +\fB\-status_history_max\fR number +Set maximum number of history lines to be reported with -status "long_history". +.TP +\fB\-list_delimiter\fR word +Set the list delimiter to be used instead of "--". It has to be a single word, +must not be empty, not longer than 80 characters, and must not contain +quotation marks. +.br +For brevity the list delimiter is referred as "--" throughout this text. +.TP +\fB\-backslash_codes\fR "on"|"off"|mode[:mode] +Enable or disable the interpretation of symbolic representations of special +characters with quoted input, or with program arguments, or with program +text output. If enabled the following translations apply: +.br + \\a=bell(007) \\b=backspace(010) \\e=Escape(033) \\f=formfeed(014) +.br + \\n=linefeed(012) \\r=carriage_return(015) \\t=tab(011) +.br + \\v=vtab(013) \\\\=backslash(134) \\[0-7][0-7][0-7]=octal_code +.br + \\\\x[0-9a-f][0-9a-f]=hex_code \\cC=control-C +.br +Translations can occur with quoted input in 3 modes: +.br + "in_double_quotes" translates only inside " quotation. +.br + "in_quotes" translates inside " and ' quotation. +.br + "with_quoted_input" translates inside and outside quotes. +.br +With the start program arguments there is mode: +.br + "with_program_arguments" translates all program arguments. +.br +.br +Mode "encode_output" encodes output characters. It combines "encode_results" +with "encode_infos". Inside single or double quotation marks encoding applies +to ASCII characters octal 001 to 037 , 177 to 377 and to backslash(134). +Outside quotation marks some harmless control characters stay unencoded: +bell(007), backspace(010), tab(011), linefeed(012), formfeed(014), +carriage_return(015). +.br +Mode "off" is default and disables any translation. +Mode "on" is +"with_quoted_input:with_program_arguments:encode_output". +.TP +\fB\-temp_mem_limit\fR number["k"|"m"] +Set the maximum size of temporary memory to be used for image dependent +buffering. Currently this applies to pattern expansion only. +.br +Default is 16m = 16 MiB, minimum 64k = 64 kiB, maximum 1024m = 1 GiB. +.TP +\fB\-print\fR text +Print a text to result channel. +.TP +\fB\-prompt\fR text +Show text at beginning of output line and +wait for the user to hit the Enter key +resp. to send a line via stdin. +.TP +\fB\-errfile_log\fR mode path|channel +.br +If problem events are related to input files from the filesystem, then their +disk_paths can be logged to a file or to output channels R or I. +.br +Mode can either be "plain" or "marked". The latter causes marker lines which +give the time of log start, burn session start, burn session end, log end +or program end. In mode "plain", only the file paths are logged. +.br +If path is "-" or "-R" then the log is directed to the result channel. +Path "-I" directs it to the info message channel. Any text that does not +begin with "-" is used as path for a file to append the log lines. +.br +Problematic files can be recorded multiple times during one program run. +If the program run aborts then the list might not be complete because +some input file arguments might not have been processed at all. +.br +The errfile paths are transported as messages of very low priority "ERRFILE". +This transport becomes visible with -report_about "ALL". +.TP +\fB\-session_log\fR path +If path is not empty it gives the address of a plain text file where +a log record gets appended after each session. This log can be used to +determine the start_lba of a session for mount options -o sbsector= +resp. -s from date or volume id. +.br +Record format is: timestamp start_lba size volume-id +.br +The first three items are single words, the rest of the line is the volume id. +.TP +\fB\-end\fR +.br +End program immediately +.TP +\fB#\fR any text +In dialog or file execution mode only and only as first +non-whitespace in line: +Do not execute the line but eventually store it in history. +.TP +.B Support for frontend programs talking into stdin and listening at stdout: +.TP +\fB\-pkt_output\fR "on"|"off" +Consolidate text output on stdout and classify each +line by a channel indicator: +.br + 'R:' for result lines, +.br + 'I:' for notes and error messages, +.br + 'M:' for -mark texts. +.br +Next is a decimal number of which only bit 0 has a meaning for now. +0 means no newline at end of payload, 1 means that the newline character at +the end of the output line belongs to the payload. After another colon follows +the payload text. +.br +Example: +.br + I:1: enter option and arguments : +.TP +\fB\-logfile\fR channel fileaddress +Copy output of a channel to the given file. +.TP +\fB\-mark\fR text +If text is not empty it will get put out each time an +action has been completed. +.TP +\fB\-prog\fR text +Use text as this program's name in subsequent messages +.TP +\fB\-prog_help\fR text +Use text as this program's name and perform -help. +.br +.SH EXAMPLES +.SS +.B Overview of examples: +As superuser learn about available drives +.br +Blank media and compose a new ISO image as batch run +.br +A dialog session doing about the same +.br +Manipulating an existing ISO image on the same media +.br +Copy modified ISO image from one media to another +.br +Bring a prepared ISOLINUX tree onto media and make it bootable +.br +Change existing file name tree from ISO-8859-1 to UTF-8 +.br +Operate on storage facilities other than optical drives +.br +Perform multi-session runs as of cdrtools traditions +.br +Let xorriso work underneath growisofs +.br +Adjust thresholds for verbosity, exit value and program abort +.br +Examples of input timestrings +.br +Incremental backup of a few directory trees +.br +Restore directory trees from a particular ISO session to disk +.br +Try to retrieve as many blocks as possible from a damaged media +.SS +.B As superuser learn about available drives +Consider to give rw permissions to those users or groups +which shall be able to use the drives with xorriso. +.br +\fB$\fR xorriso -devices +.br +0 -dev '/dev/sr0' rwrw-- : '_NEC ' 'DVD_RW ND-4570A' +.br +1 -dev '/dev/sr1' rwrw-- : 'HL-DT-ST' 'DVDRAM GSA-4082B' +.br +2 -dev '/dev/sr2' rwrw-- : 'PHILIPS ' 'SPD3300L' +.SS +.B Blank media and compose a new ISO image as batch run +Aquire drive /dev/sr2, make media ready for writing a new image, +fill the image with the files from hard disk directories /home/me/sounds +and /home/me/pictures. +.br +Because no -dialog "on" is given, the program will then end by writing the +session to media. +.br +\fB$\fR xorriso -outdev /dev/sr2 \\ +.br + -blank as_needed \\ +.br + -map /home/me/sounds /sounds \\ +.br + -map /home/me/pictures /pictures +.br + +.br +The ISO image may be shaped in a more elaborate way like the following: +Omit some unwanted stuff by removing it from the image directory tree. +Re-add some wanted stuff. +.br +\fB$\fR cd /home/me +.br +\fB$\fR xorriso -outdev /dev/sr2 \\ +.br + -blank as_needed \\ +.br + -map /home/me/sounds /sounds \\ +.br + -map /home/me/pictures /pictures \\ +.br + -rm_r \\ +.br + /sounds/indecent \\ +.br + '/pictures/*private*' \\ +.br + /pictures/confidential \\ +.br + -- \\ +.br + -cd / \\ +.br + -add pictures/confidential/work* +.br +Note that '/pictures/*private*' is a pattern for iso_rr_paths +while pictures/confidential/work* gets expanded by the shell +with addresses from the hard disk. +.SS +.B A dialog session doing about the same +.br +-pathspecs is already given as start argument. The other activities +are done as dialog input. The pager gets set to 20 lines of 80 characters. +.br +The drive is aquired by option -dev rather than -outdev in order to see +the message about its current content. By option -blank this content is +made ready for being overwritten and the loaded ISO image is made empty. +.br +In order to be able to eject the media, the session needs to be committed +explicitely. +.br +.B $ xorriso -dialog on -page 20 80 -disk_pattern on +.br +enter option and arguments : +.br +.B \-dev /dev/sr2 +.br +enter option and arguments : +.br +.B \-blank as_needed +.br +enter option and arguments : +.br +.B \-map /home/me/sounds /sounds -map /home/me/pictures /pictures +.br +enter option and arguments : +.br +.B \-rm_r /sounds/indecent /pictures/*private* /pictures/confidential +.br +enter option and arguments : +.br +.B \-cdx /home/me/pictures -cd /pictures +.br +enter option and arguments : +.br +.B \-add confidential/office confidential/factory +.br +enter option and arguments : +.br +.B \-du / +.br +enter option and arguments : +.br +.B \-commit -eject all -end +.br +.SS +.B Manipulating an existing ISO image on the same media +Load image from drive. +Remove (i.e. hide) directory /sounds and its subordinates. +Rename directory /pictures/confidential to /pictures/restricted. +Change access permissions of directory /pictures/restricted. +Add new directory trees /sounds and /movies. Burn to the same media and eject. +.br +\fB$\fR xorriso -dev /dev/sr2 \\ +.br + -rm_r /sounds -- \\ +.br + -mv \\ +.br + /pictures/confidential \\ +.br + /pictures/restricted \\ +.br + -- \\ +.br + -chmod go-rwx /pictures/restricted -- \\ +.br + -map /home/me/prepared_for_dvd/sounds_dummy /sounds \\ +.br + -map /home/me/prepared_for_dvd/movies /movies \\ +.br + -commit -eject all +.SS +.B Copy modified ISO image from one media to another +Load image from input drive. Do the same manipulations as in the previous +example. Aquire output drive and blank it. Burn the modified image as +first and only session to the output drive. +.br +\fB$\fR xorriso -indev /dev/sr2 \\ +.br + -rm_r /sounds -- \\ +.br + ... +.br + -outdev /dev/sr0 -blank as_needed \\ +.br + -commit -eject all +.SS +.B Bring a prepared ISOLINUX tree onto media and make it bootable +The user has already created a suitable file tree on disk and copied the +ISOLINUX files into subdirectory ./boot/isolinux of that tree. +Now xorriso can burn an El Torito bootable media: +.br +\fB$\fR xorriso -outdev /dev/sr0 -blank as_needed \\ +.br + -map /home/me/ISOLINUX_prepared_tree / \\ +.br + -boot_image isolinux dir=/boot/isolinux +.SS +.B Change existing file name tree from ISO-8859-1 to UTF-8 +This example assumes that the existing ISO image was written with character +set ISO-8859-1 but that the readers expected UTF-8. Now a new session with +the same files gets added with converted file names. +In order to avoid any weaknesses of the local character set, this command +pretends that it uses already the final target set UTF-8. +Therefore strange file names may appear in eventual messages which +will be made terminal-safe by option -backslash_codes. +.br +\fB$\fR xorriso -in_charset ISO-8859-1 -local_charset UTF-8 \\ +.br + -out_charset UTF-8 -backslash_codes on -dev /dev/sr0 \\ +.br + -alter_date m +0 / -- -commit -eject all +.SS +.B Operate on storage facilities other than optical drives +Full read-write operation is possible with regular files and block devices: +.br +\fB$\fR xorriso -dev /tmp/regular_file ... +.br +Paths underneath /dev normally need prefix "stdio:" +.br +\fB$\fR xorriso -dev stdio:/dev/sdb ... +.br +If /dev/sdb is to be used frequently and /dev/sda is the system disk, +then consider to place the following lines in a xorriso Startup File. +They allow to use /dev/sdb without prefix and protect your disk from xorriso: +.br + -drive_class banned /dev/sda* + -drive_class harmless /dev/sdb +.br +Other writeable file types are supported write-only: +.br +\fB$\fR xorriso -outdev /tmp/named_pipe ... +.br +Among the write-only drives is standard output: +.br +\fB$\fR xorriso -outdev - \\ +.br + ... +.br + | gzip >image.iso.gz +.SS +.B Perform multi-session runs as of cdrtools traditions +Between both processes there can be performed arbitrary transportation +or filtering. +.br +The first session is written like this: +.br +\fB$\fR xorriso -as mkisofs prepared_for_iso/tree1 | \\ +.br + xorriso -as cdrecord -v dev=/dev/sr0 blank=fast -multi -eject - +.br +Follow-up sessions are written like this: +.br +\fB$\fR m=$(xorriso -as cdrecord dev=/dev/sr0 -msinfo) +.br +\fB$\fR xorriso -as mkisofs -M /dev/sr0 -C $m prepared_for_iso/tree2 | \\ +.br + xorriso -as cdrecord -v dev=/dev/sr0 -waiti -multi -eject - +.br +Always eject the drive tray between sessions. The old sessions +get read via stdio:/dev/sr0 and thus are prone to device driver +peculiarities. +.br +This example works for multi-session media only. +Add cdrskin option --grow_overwriteable_iso to all -as cdrecord runs +in order to enable multi-session emulation on overwriteable media. +.SS +.B Let xorriso work underneath growisofs +growisofs expects an ISO formatter program which understands options -C and +-M. If xorriso gets started by name "xorrisofs" then it is suitable for that. +.br +\fB$\fR export MKISOFS="xorrisofs" +.br +\fB$\fR growisofs -Z /dev/dvd /some/files +.br +\fB$\fR growisofs -M /dev/dvd /more/files +.br +If no "xorrisofs" is available on your system, then you will have to create +a link pointing to the xorriso binary and tell growisofs to use it. E.g. by: +.br +\fB$\fR ln -s $(which xorriso) "$HOME/xorrisofs" +.br +\fB$\fR export MKISOFS="$HOME/xorrisofs" +.br +One may quit mkisofs emulation by argument "--" and make +use of all xorriso commands. growisofs dislikes options which +start with "-o" but -outdev must be set to "-". +So use "outdev" instead: +.br +\fB$\fR growisofs -Z /dev/dvd -- outdev - -update_r /my/files /files +.br +\fB$\fR growisofs -M /dev/dvd -- outdev - -update_r /my/files /files +.br +growisofs has excellent burn capabilities with DVD and BD. +It does not emulate session history on overwriteable media, though. +.SS +.B Adjust thresholds for verbosity, exit value and program abort +Be quite verbous, exit 32 if severity "FAILURE" was encountered, +do not abort prematurely but forcibly go on until the end of commands. +.br +\fB$\fR xorriso ... \\ +.br + -report_about UPDATE \\ +.br + -return_with FAILURE 32 \\ +.br + -abort_on NEVER \\ +.br + ... +.SS +.B Examples of input timestrings +.br +As printed by program date: +.B 'Thu Nov 8 14:51:13 CET 2007' +.br +The same without ignored parts: +.B 'Nov 8 14:51:13 2007' +.br +The same as expected by date: +.B 110814512007.13 +.br +Four weeks in the future: +.B +4w +.br +The current time: +.B +0 +.br +Three hours ago: +.B \-3h +.br +Seconds since Jan 1 1970: +.B =1194531416 +.SS +.B Incremental backup of a few directory trees +This changes the directory trees /open_source_project and /personal_mail +in the ISO image so that they become exact copies of their disk counterparts. +ISO file objects get created, deleted or get their attributes adjusted +accordingly. +Files with names matching *.o or *.swp get excluded explicitely. +.br +Only media with the expected volume id or blank media are accepted. +.br +\fB$\fR xorriso -assert_volid 'PROJECTS_MAIL_*' FATAL \\ +.br + -dev /dev/sr0 \\ +.br + -volid PROJECTS_MAIL_"$(date '+%Y_%m_%d_%H%M%S')" \\ +.br + -not_leaf '*.o' -not_leaf '*.swp' \\ +.br + -update_r /home/thomas/open_source_projects /open_source_projects \\ +.br + -update_r /home/thomas/personal_mail /personal_mail \\ +.br + -commit -toc -eject all +.br +To be used several times on the same media, whenever an update of +the two disk trees to the media is desired. Begin with blank media and start +a new blank media when the run fails due to lack of remaining space on +the old one. +.br +This makes sense if the full backup leaves substantial remaining capacity +on media and if the expected changes are much smaller than the full backup. +An update run will probably save no time but last longer than a full backup. +.br +With \fBmount\fR option \fB-o "sbsector="\fR on Linux resp. \fB-s\fR on FreeBSD +it is possible to access the session trees which represent the older backup +versions. With CD media, Linux mount accepts session numbers directly by +its option "session=". +.br +Multi-session media and most overwriteable media written by xorriso can tell +the sbsectors of their sessions by xorriso option -toc. +Used after -commit the following option prints the matching mount command for +the newly written session (here for mount point /mnt): +.br + -mount_cmd "indev" "auto" "auto" /mnt +.br +Options -mount_cmd and -mount are also able to produce the mount commands for +older sessions in the table-of-content. E.g. as superuser: +.br + \fB$\fR osirrox -mount /dev/sr0 "volid" '*2008_12_05*' /mnt +.br +Sessions on multi-session media are separated by several MB of unused blocks. +So with small sessions the payload capacity can become substantially lower +than the overall media capacity. If the remaining space on media does not +suffice for the next gap, the drive is supposed to close the media +automatically. +.br +\fBBetter do not use your youngest backup for -update_r\fR. +Have at least two media which you use alternatingly. So only older backups +get endangered by the new write operation, while the newest backup is +stored safely on a different media. +Always have a blank media ready to perform a full backup in case the update +attempt fails due to insufficient remaining capacity. +.SS +.B Restore directory trees from a particular ISO session to disk +This is an alternative to mounting the media and using normal file operations. +.br +First check which backup sessions are on the media: +.br +\fB$\fR xorriso -outdev /dev/sr0 -toc +.br +Then load the desired session and copy the file trees to disk. +Avoid to eventually create /home/thomas/restored without rwx-permission. +.br +\fB$\fR xorriso -load volid 'PROJECTS_MAIL_2008_06_19*' \\ +.br + -indev /dev/sr0 \\ +.br + -osirrox on:auto_chmod_on \\ +.br + -chmod u+rwx / -- \\ +.br + -extract /open_source_projects \\ +.br + /home/thomas/restored/open_source_projects \\ +.br + -extract /personal_mail /home/thomas/restored/personal_mail +.br + -rollback_end +.SS +.B Try to retrieve as many blocks as possible from a damaged media +.br +\fB$\fR xorriso -abort_on NEVER -indev /dev/sr0 \\ +.br + -check_media time_limit=1800 report=blocks_files \\ +.br + data_to="$HOME"/dvd_copy sector_map="$HOME"/dvd_copy.map -- +.br +This can be repeated several times, eventually with -eject or with other +-indev drives. See the human readable part of "$HOME"/dvd_copy.map for +addresses which can be used on "$HOME"/dvd_copy with mount option -o sbsector= +resp. -s. +.br +If you want to make the newest session the default mount session, you +may add option "patch_lba0=on" to the final -check_media run. +.SH FILES +.SS +.B Startup files: +.br +If not -no_rc is given as the first argument then xorriso attempts on startup +to read and execute lines from the following files: +.br + /etc/default/xorriso +.br + /etc/opt/xorriso/rc +.br + /etc/xorriso/xorriso.conf +.br + $HOME/.xorrisorc +.br +The files are read in the sequence given above, but none of them is required +for xorriso to function properly. +.SS +.B Runtime control files: +.br +The default setting of -check_media abort_file= is: +.br + /var/opt/xorriso/do_abort_check_media +.br +.SH SEE ALSO +.TP +For mounting xorriso generated ISO 9660 images +.br +.BR mount(8) +.TP +Libreadline, a comfortable input line facility +.BR readline(3) +.TP +Other programs which produce ISO 9660 images +.br +.BR mkisofs(8), +.BR genisoimage(8) +.TP +Other programs which burn sessions to optical media +.BR growisofs(1), +.BR cdrecord(1), +.BR wodim(1), +.BR cdrskin(1) +.br +.SH AUTHOR +Thomas Schmitt <scdbackup@gmx.net> +.br +for libburnia-project.org +.SH CREDITS +xorriso is in part based on work by Vreixo Formoso who provides libisofs +together with Mario Danic who also leads the libburnia team. +Thanks to Andy Polyakov who invented emulated growing, +to Derek Foreman and Ben Jansens who once founded libburn. +.br +Compliments towards Joerg Schilling whose cdrtools served me for ten years. + diff --git a/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso.c b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso.c new file mode 100644 index 00000000..e3d6c09d --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso.c @@ -0,0 +1,16654 @@ + +/* + + ( cd .. ; libisoburn-develop/xorriso/compile_xorriso.sh -g ) + +or + + cc -g -DXorriso_with_maiN -DXorriso_with_readlinE \ + -DXorriso_build_timestamP='"'"$(date -u '+%Y.%m.%d.%H%M%S')"'"' \ + -Wall -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \ + -o xorriso/xorriso \ + xorriso/xorriso.c xorriso/xorrisoburn.c \ + -lpthread -lreadline -lburn -lisofs -lisoburn + +or + + cc -g -DXorriso_with_readlinE \ + -DXorriso_build_timestamP='"'"$(date -u '+%Y.%m.%d.%H%M%S')"'"' \ + -Wall -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \ + -c \ + xorriso/xorriso.c xorriso/xorrisoburn.c + +*/ + +/* Command line oriented batch and dialog tool which creates, loads, + manipulates and burns ISO 9660 filesystem images. + + Copyright 2007-2008 Thomas Schmitt, <scdbackup@gmx.net> + + Initial code of this program was derived from program src/askme.c out + of scdbackup-0.8.8, Copyright 2007 Thomas Schmitt, BSD-License. + + Provided under GPL version 2, with the announcement that this might + get changed in future. I would prefer BSD or a modified LGPL with no + option to choose any kind of future GPL version. + (This announcement affects only future releases of xorriso. + If you obtain a copy licensed as "GPL version 2" then this license is + not revocable for that particular copy, of course.) + + + Overview of xorriso architecture: + + libburn provides the ability to read and write data. + + libisofs interprets and manipulates ISO 9660 directory trees. It generates + the output stream which is handed over to libburn. + + libisoburn encapsulates the connectivity issues between libburn and + libisofs. It also enables multi-session emulation on overwritable media + and random access file objects. + xorriso is intended as reference application of libisoburn. + + xorrisoburn.[ch] encapsulate any usage of the libraries by xorriso. + + xorriso.h exposes the public functions of xorriso which are intended + to be used by programs which link with xorriso.o. These functions are + direct equivalents of the xorriso interpreter commands. + There is also the API for handling event messages. + + xorriso_private.h is not to be included by other software. It encapsulates + the inner interfaces of xorriso. + + xorriso.c provides the command interpreter as described in xorriso.1. + It performs any activity that does not demand a reference to a symbol + of the library APIs. This includes: + - Interpretation of user input from arguments, dialog, and scripting. + - Output of result text and event messages. + - POSIX filesystem operations. + - Public functions which perform the particular xorriso commands. + - The main() function, if enabled by #define Xorriso_with_maiN. + +*/ + + +#include <ctype.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/wait.h> +#include <dirent.h> +#include <time.h> +#include <utime.h> +#include <pwd.h> +#include <grp.h> +#include <signal.h> +#include <sys/utsname.h> + +/* for -charset */ +#include <iconv.h> +#include <langinfo.h> +#include <locale.h> + +/* eventually, this is done in xorriso_private.h : #include <regex.h> */ + +#ifdef Xorriso_with_readlinE +#ifdef Xorriso_with_old_readlinE +#include <readline.h> +#include <history.h> +#else /* Xorriso_with_old_readlinE */ +#include <readline/readline.h> +#include <readline/history.h> +#endif /* ! Xorriso_with_old_readlinE */ +#endif /* Xorriso_with_readlinE */ + +#define TSOB_FELD(typ,anz) (typ *) malloc((anz)*sizeof(typ)); + + +/* Diet facility: exclude help texts from binaries */ +/* This will eventually be redefined to eat up its content */ +#define AlN(x) x + + +/* There is only one stage of diet: Xorriso_no_helP */ +#ifdef Xorriso_no_helP +#undef AlN +#define AlN(x) +#endif + + +/* ------------------------------------------------------------------------ */ + + +/* The official xorriso options API. "No shortcuts" */ +#include "xorriso.h" + +/* The inner description of XorrisO */ +#define Xorriso_is_xorriso_selF 1 +#include "xorriso_private.h" + +/* The inner isofs- and burn-library interface */ +#include "xorrisoburn.h" + + +/* ------------------------------------------------------------------------ */ + + +#ifndef Xorriso_sfile_externaL +/* @param flag bit0= do not clip of carriage return at line end +*/ +char *Sfile_fgets_n(char *line, int maxl, FILE *fp, int flag) +{ + int l; + char *ret; + + ret= fgets(line,maxl,fp); + if(ret==NULL) + return(NULL); + l= strlen(line); + if(l > 0 && !(flag & 1)) if(line[l-1] == '\r') line[--l]= 0; + if(l > 0) if(line[l-1] == '\n') line[--l]= 0; + if(l > 0 && !(flag & 1)) if(line[l-1] == '\r') line[--l]= 0; + return(ret); +} + + +int Sfile_count_components(char *path, int flag) +/* + bit0= do not ignore trailing slash + bit1= do not ignore empty components (other than the empty root name) +*/ +{ + int l,count= 0; + char *cpt; + + l= strlen(path); + if(l==0) + return(0); + count= 1; + for(cpt= path+l-1;cpt>=path;cpt--) { + if(*cpt=='/') { + if(*(cpt+1)==0 && !(flag&1)) + continue; + if(*(cpt+1)=='/' && !(flag&2)) + continue; + count++; + } + } + return(count); +} + + +int Sfile_component_pointer(char *path, char **sourcept, int idx, int flag) +/* + bit0= do not ignore trailing slash + bit1= do not ignore empty components (other than the empty root name) + bit2= accept 0 as '/' +*/ +{ + int count= 0; + char *spt; + + for(spt= path;*spt!=0 || (flag&4);spt++) { + if(count>=idx) { + *sourcept= spt; + return(1); + } + if(*spt=='/' || *spt==0) { + if(*(spt+1)=='/' && !(flag&2)) + continue; + if(*(spt+1)==0 && !(flag&1)) + continue; + count++; + } + } + if((flag&1) && count>=idx) + return(1); + return(0); +} + + +int Sfile_leafname(char *path, char leafname[SfileadrL], int flag) +{ + int count, ret; + char *lpt; + + leafname[0]= 0; + count= Sfile_count_components(path, 0); + if(count==0) + return(0); + ret= Sfile_component_pointer(path, &lpt, count-1, 0); + if(ret<=0) + return(ret); + if(Sfile_str(leafname, lpt, 0)<=0) + return(0); + lpt= strchr(leafname, '/'); + if(lpt!=NULL) + *lpt= 0; + return(1); +} + + +int Sfile_add_to_path(char path[SfileadrL], char *addon, int flag) +{ + int l; + + l= strlen(path); + if(l+1>=SfileadrL) + return(0); + if(l==0) { + strcpy(path,"/"); + l= 1; + } else if(path[l-1]!='/') { + path[l++]= '/'; + path[l]= 0; + } + if(l+strlen(addon)>=SfileadrL) + return(0); + if(addon[0]=='/') + strcpy(path+l,addon+1); + else + strcpy(path+l,addon); + return(1); +} + + +int Sfile_prepend_path(char *prefix, char path[SfileadrL], int flag) +{ + int l, i; + + l= strlen(path)+strlen(prefix)+1; + if(l>=SfileadrL) { + +#ifdef Not_yeT + /* >>> ??? how to transport messages to xorriso ? */ + sprintf(xorriso->info_text, + "Combination of wd and relative address too long (%d > %d)", + l,SfileadrL-1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); +#endif + + return(-1); + } + l-= strlen(path); + for(i= strlen(path)+1; i>=0; i--) + path[i+l]= path[i]; + strcpy(path,prefix); + path[l-1]= '/'; + return(1); +} + +int Sfile_being_group_member(struct stat *stbuf, int flag) +{ + int i, suppl_groups; + gid_t *suppl_glist; + + if (getegid()==stbuf->st_gid) + return(1); + suppl_groups= getgroups(0, NULL); + suppl_glist= (gid_t *) malloc((suppl_groups + 1) * sizeof(gid_t)); + if (suppl_glist==NULL) + return(-1); + suppl_groups= getgroups(suppl_groups+1,suppl_glist); + for (i= 0; i<suppl_groups; i++) { + if (suppl_glist[i]==stbuf->st_gid) { + free((char *) suppl_glist); + return(1); + } + } + free((char *) suppl_glist); + return(0); +} + + +int Sfile_type(char *filename, int flag) +/* + bit0= return -1 if file is missing + bit1= return a hardlink with siblings as type 5 + bit2= evaluate eventual link target rather than the link object itself + bit3= return a socket or a char device as types 7 or 8 rather than 0 +*/ +/* + return: + 0=unknown + 1=regular + 2=directory + 3=symbolic link + 4=named pipe + 5=multiple hardlink (with bit1) + 6=block device + 7=socket (with bit3) + 8=character device (with bit3) +*/ +{ + struct stat stbuf; + if(flag&4) { + if(stat(filename,&stbuf)==-1) { + if(flag&1) return(-1); + else return(0); + } + } else { + if(lstat(filename,&stbuf)==-1) { + if(flag&1) return(-1); + else return(0); + } + } + if(S_ISREG(stbuf.st_mode)) { + if(flag&2) + if(stbuf.st_nlink>1) + return(5); + return(1); + } + if(S_ISDIR(stbuf.st_mode)) + return(2); + if((stbuf.st_mode&S_IFMT)==S_IFLNK) + return(3); + if(S_ISFIFO(stbuf.st_mode)) + return(4); + if(S_ISBLK(stbuf.st_mode)) + return(6); + if(flag&8) + if((stbuf.st_mode&S_IFMT)==S_IFSOCK) + return(7); + if(flag&8) + if(S_ISCHR(stbuf.st_mode)) + return(8); + return(0); +} + + +char *Sfile_datestr(time_t tim, short int flag) +/* + bit0=with hours+minutes + bit1=with seconds + + bit8= local time rather than UTC +*/ +{ + static char zeitcode[80]={"000000"}; + char puff[80]; + struct tm *azt; + + if(flag&256) + azt = localtime(&tim); + else + azt = gmtime(&tim); + + if(azt->tm_year>99) + sprintf(zeitcode,"%c%1.1d%2.2d%2.2d", + 'A'+(azt->tm_year-100)/10,azt->tm_year%10, + azt->tm_mon+1,azt->tm_mday); + else + sprintf(zeitcode,"%2.2d%2.2d%2.2d", + azt->tm_year,azt->tm_mon+1,azt->tm_mday); + if(flag&1){ + sprintf(puff,".%2.2d%2.2d",azt->tm_hour,azt->tm_min); + strcat(zeitcode,puff); + } + if(flag&2){ + sprintf(puff,"%2.2d",azt->tm_sec); + strcat(zeitcode,puff); + } + + return(zeitcode); +} + + +int Sfile_scale(double value, char *result, int siz, double thresh, int flag) +/* + bit0= eventually ommit 'b' + bit1= make text as short as possible + bit2= no fraction (if it would fit at all) +*/ +{ + char scale_c,scales[6],form[80], *negpt= NULL, *cpt; + int i,dec_siz= 0,avail_siz= 1; + + if(value<0) { + value= -value; + siz--; + result[0]= '-'; + negpt= result; + result++; + } + strcpy(scales,"bkmgtp"); + scale_c= scales[0]; + for(i=1;scales[i]!=0;i++) { + if(value<thresh-0.5) + break; + value/= 1024.0; + scale_c= scales[i]; + } + if(scale_c!='b' && !(flag&4)) { /* is there room for fractional part ? */ + avail_siz= siz-1; + sprintf(form,"%%.f"); + sprintf(result,"%.f",value); + if(strlen(result)<=avail_siz-2) + dec_siz= 1; /* we are very modest */ + } + if(scale_c=='b' && (flag&1)) { + if(flag&2) + sprintf(form,"%%.f"); + else + sprintf(form,"%%%d.f",siz); + sprintf(result,form,value); + } else { + if(flag&2) + sprintf(form,"%%.f%%c"); + else if(dec_siz>0) + sprintf(form,"%%%d.%df%%c",avail_siz,dec_siz); + else + sprintf(form,"%%%d.f%%c",siz-1); + sprintf(result,form,value,scale_c); + } + if(negpt != NULL) { + for(cpt= result; *cpt==' '; cpt++); + if(cpt > result) { + *negpt= ' '; + *(cpt - 1)= '-'; + } + } + return(1); +} + + +int Sfile_off_t_text(char text[80], off_t num, int flag) +{ + char *tpt; + off_t hnum, scale= 1; + int digits= 0, d, i; + + tpt= text; + hnum= num; + if(hnum<0) { + *(tpt++)= '-'; + hnum= -num; + } + if(hnum<0) { /* it can stay nastily persistent */ + strcpy(text, "_overflow_"); + return(0); + } + for(i= 0; i<23; i++) { /* good for up to 70 bit = 10 exp 21.07... */ + if(hnum==0) + break; + hnum/= 10; + if(hnum) + scale*= 10; + } + if(i==0) { + strcpy(text, "0"); + return(1); + } + if(i==23) { + strcpy(text, "_overflow_"); + return(0); + } + digits= i; + hnum= num; + for(; i>0; i--) { + d= hnum/scale; + tpt[digits-i]= '0'+d; + hnum= hnum%scale; + scale/= 10; + } + tpt[digits]= 0; + return(1); +} + + +/* Converts backslash codes into single characters: + \a BEL 7 , \b BS 8 , \e ESC 27 , \f FF 12 , \n LF 10 , \r CR 13 , + \t HT 9 , \v VT 11 , \\ \ 92 + \[0-9][0-9][0-9] octal code , \x[0-9a-f][0-9a-f] hex code , + \cX control-x (ascii(X)-64) + @param upto maximum number of characters to examine for backslash. + The scope of a backslash (0 to 3 characters) is not affected. + @param eaten returns the difference in length between input and output + @param flag bit0= only determine *eaten, do not convert +*/ +int Sfile_bsl_interpreter(char *text, int upto, int *eaten, int flag) +{ + char *rpt, *wpt, num_text[8], wdummy[8]; + unsigned int num= 0; + + *eaten= 0; + wpt= text; + for(rpt= text; *rpt != 0 && rpt - text < upto; rpt++) { + if(flag & 1) + wpt= wdummy; + if(*rpt == '\\') { + rpt++; + (*eaten)++; + if(*rpt == 'a') { + *(wpt++)= 7; + } else if(*rpt == 'b') { + *(wpt++)= 8; + } else if(*rpt == 'e') { + *(wpt++)= 27; + } else if(*rpt == 'f') { + *(wpt++)= 12; + } else if(*rpt == 'n') { + *(wpt++)= 10; + } else if(*rpt == 'r') { + *(wpt++)= 13; + } else if(*rpt == 't') { + *(wpt++)= 9; + } else if(*rpt == 'v') { + *(wpt++)= 11; + } else if(*rpt == '\\') { + *(wpt++)= '\\'; + } else if(rpt[0] >= '0' && rpt[0] <= '7' && + rpt[1] >= '0' && rpt[1] <= '7' && + rpt[2] >= '0' && rpt[2] <= '7') { + num_text[0]= '0'; + num_text[1]= *(rpt + 0); + num_text[2]= *(rpt + 1); + num_text[3]= *(rpt + 2); + num_text[4]= 0; + sscanf(num_text, "%o", &num); + if(num > 0 && num <= 255) { + rpt+= 2; + (*eaten)+= 2; + *(wpt++)= num; + } else + goto not_a_code; + } else if(rpt[0] == 'x' && + ((rpt[1] >= '0' && rpt[1] <= '9') || + (rpt[1] >= 'A' && rpt[1] <= 'F') || + (rpt[1] >= 'a' && rpt[1] <= 'f')) + && + ((rpt[2] >= '0' && rpt[2] <= '9') || + (rpt[2] >= 'A' && rpt[2] <= 'F') || + (rpt[2] >= 'a' && rpt[2] <= 'f')) + ) { + num_text[0]= *(rpt + 1); + num_text[1]= *(rpt + 2); + num_text[2]= 0; + sscanf(num_text, "%x", &num); + if(num > 0 && num <= 255) { + rpt+= 2; + (*eaten)+= 2; + *(wpt++)= num; + } else + goto not_a_code; + } else if(*rpt == 'c') { + if(rpt[1] > 64 && rpt[1] < 96) { + *(wpt++)= rpt[1] - 64; + rpt++; + (*eaten)++; + } else + goto not_a_code; + } else { +not_a_code:; + *(wpt++)= '\\'; + rpt--; + (*eaten)--; + } + } else + *(wpt++)= *rpt; + } + *wpt= *rpt; + return(1); +} + + +int Sfile_argv_bsl(int argc, char ***argv, int flag) +{ + int i, ret, eaten; + char **new_argv= NULL; + + if(argc <= 0) + return(0); + new_argv= (char **) Smem_malloC(argc * sizeof(char *)); + if(new_argv == NULL) + return(-1); + for(i= 0; i < argc; i++) { + new_argv[i]= strdup((*argv)[i]); + if(new_argv[i] == NULL) + {ret= -1; goto ex;} + ret= Sfile_bsl_interpreter(new_argv[i], strlen(new_argv[i]), &eaten, 0); + if(ret <= 0) + goto ex; + } + ret= 1; +ex:; + if(ret <= 0) { + if(new_argv != NULL) + free((char *) new_argv); + } else + *argv= new_argv; + return(ret); +} + + +/* @param flag bit0= only encode inside quotes + bit1= encode < 32 outside quotes except 7, 8, 9, 10, 12, 13 + bit2= encode in any case above 126 +*/ +int Sfile_bsl_encoder(char **result, char *text, int flag) +{ + char *rpt, *wpt; + int count, sq_open= 0, dq_open= 0; + + count= 0; + for(rpt= text; *rpt != 0; rpt++) { + count++; + if(*rpt >= 32 && *rpt <= 126 && *rpt != '\\') + continue; + if((*rpt >= 7 && *rpt <= 13) || *rpt == 27 || *rpt == '\\') + count++; + else + count+= 3; + } + (*result)= wpt= calloc(count + 1, 1); + if(wpt == NULL) + return(-1); + for(rpt= text; *rpt != 0; rpt++) { + if(*rpt == '\'') + sq_open= !(sq_open || dq_open); + if(*rpt == '"') + dq_open= !(sq_open || dq_open); + if(*rpt >= 32 && *rpt <= 126 && *rpt != '\\') { + *(wpt++)= *rpt; + continue; + } + if( ((flag & 1) && !(sq_open || dq_open)) && + !((flag & 2) && (*rpt >= 1 && * rpt <= 31 && + !(*rpt == 7 || *rpt == 8 || *rpt == 9 || *rpt == 10 || + *rpt == 12 || *rpt == 13))) && + !((flag & 4) && (*rpt > 126 || *rpt < 0)) && + !((flag & 6) && *rpt == '\\')) { + *(wpt++)= *rpt; + continue; + } + *(wpt++)= '\\'; + if((*rpt >= 7 && *rpt <= 13) || *rpt == 27 || *rpt == '\\') { + if(*rpt == 7) + *(wpt++)= 'a'; + else if(*rpt == 8) + *(wpt++)= 'b'; + else if(*rpt == 9) + *(wpt++)= 't'; + else if(*rpt == 10) { + *(wpt++)= 'n'; + } else if(*rpt == 11) + *(wpt++)= 'v'; + else if(*rpt == 12) + *(wpt++)= 'f'; + else if(*rpt == 13) + *(wpt++)= 'c'; + else if(*rpt == 27) + *(wpt++)= 'e'; + else if(*rpt == '\\') + *(wpt++)= '\\'; + } else { + sprintf(wpt, "%-3.3o", (unsigned int) *((unsigned char *) rpt)); + wpt+= 3; + } + } + *wpt= 0; + return(1); +} + + +int Sfile_destroy_argv(int *argc, char ***argv, int flag) +{ + int i; + + if(*argc>0 && *argv!=NULL){ + for(i=0;i<*argc;i++){ + if((*argv)[i]!=NULL) + Smem_freE((*argv)[i]); + } + Smem_freE((char *) *argv); + } + *argc= 0; + *argv= NULL; + return(1); +} + + +int Sfile_make_argv(char *progname, char *line, int *argc, char ***argv, + int flag) +/* + bit0= read progname as first argument from line + bit1= just release argument list argv and return + bit2= abort with return(0) if incomplete quotes are found + bit3= eventually prepend missing '-' to first argument read from line + bit4= like bit2 but only check quote completeness, do not allocate memory + bit5+6= interpretation of backslashes: + 0= no interpretation, leave unchanged + 1= only inside double quotes + 2= outside single quotes + 3= everywhere + bit7= append a NULL element to argv +*/ +{ + int i,pass,maxl=0,l,argzaehl=0,bufl,line_start_argc, bsl_mode, ret= 0, eaten; + char *cpt,*start; + char *buf= NULL; + + Sfile_destroy_argv(argc,argv,0); + if(flag&2) + {ret= 1; goto ex;} + + if(flag & 16) + flag|= 4; + bsl_mode= (flag >> 5) & 3; + + buf= calloc(strlen(line) + SfileadrL, 1); + if(buf == NULL) + {ret= -1; goto ex;} + for(pass=0;pass<2;pass++) { + cpt= line-1; + if(!(flag&1)){ + argzaehl= line_start_argc= 1; + if(pass==0) + maxl= strlen(progname); + else + strcpy((*argv)[0],progname); + } else { + argzaehl= line_start_argc= 0; + if(pass==0) maxl= 0; + } + while(*(++cpt)!=0){ + if(isspace(*cpt)) continue; + start= cpt; + buf[0]= 0; + cpt--; + while(*(++cpt)!=0) { + if(isspace(*cpt)) break; + if(*cpt=='"'){ + l= cpt-start; bufl= strlen(buf); + if(l>0) { + strncpy(buf + bufl, start, l); buf[bufl + l]= 0; + if(bsl_mode >= 3) { + ret= Sfile_bsl_interpreter(buf, l, &eaten, 0); + if(ret <= 0) + goto ex; + } + } + l= strlen(buf); + start= cpt+1; + while(*(++cpt)!=0) if(*cpt=='"') break; + if((flag&4) && *cpt==0) + {ret= 0; goto ex;} + l= cpt-start; bufl= strlen(buf); + if(l>0) { + strncpy(buf + bufl, start, l); + buf[bufl + l]= 0; + if(bsl_mode >= 1) { + ret= Sfile_bsl_interpreter(buf + bufl, l, &eaten, 0); + if(ret <= 0) + goto ex; + } + } + start= cpt+1; + }else if(*cpt=='\''){ + l= cpt-start; bufl= strlen(buf); + if(l>0) { + strncpy(buf + bufl, start, l); buf[bufl + l]= 0; + if(bsl_mode >= 3) { + ret= Sfile_bsl_interpreter(buf, l, &eaten, 0); + if(ret <= 0) + goto ex; + } + } + l= strlen(buf); + start= cpt+1; + while(*(++cpt)!=0) if(*cpt=='\'') break; + if((flag&4) && *cpt==0) + {ret= 0; goto ex;} + l= cpt-start; bufl= strlen(buf); + if(l>0) { + strncat(buf,start,l);buf[bufl+l]= 0; + if(bsl_mode >= 2) { + ret= Sfile_bsl_interpreter(buf + bufl, l, &eaten, 0); + if(ret <= 0) + goto ex; + } + } + start= cpt+1; + } + if(*cpt==0) break; + } + l= cpt-start; + bufl= strlen(buf); + if(l>0) { + strncpy(buf + bufl, start, l); buf[bufl + l]= 0; + if(bsl_mode >= 3) { + ret= Sfile_bsl_interpreter(buf, l, &eaten, 0); + if(ret <= 0) + goto ex; + } + } + l= strlen(buf); + if(pass==0){ + if(argzaehl==line_start_argc && (flag&8)) + if(buf[0]!='-' && buf[0]!=0 && buf[0]!='#') + l++; + if(l>maxl) maxl= l; + }else{ + strcpy((*argv)[argzaehl],buf); + if(argzaehl==line_start_argc && (flag&8)) + if(buf[0]!='-' && buf[0]!=0 && buf[0]!='#') + sprintf((*argv)[argzaehl],"-%s", buf); + } + argzaehl++; + if(*cpt==0) break; + } + if(pass==0){ + if(flag & 16) + {ret= 1; goto ex;} + *argc= argzaehl; + if(argzaehl>0 || (flag & 128)) { + *argv= (char **) Smem_malloC((argzaehl + !!(flag & 128)) + * sizeof(char *)); + if(*argv==NULL) + {ret= -1; goto ex;} + } + for(i=0;i<*argc;i++) { + (*argv)[i]= (char *) Smem_malloC((maxl+1)); + if((*argv)[i]==NULL) + {ret= -1; goto ex;} + } + if(flag & 128) + (*argv)[*argc]= NULL; + } + } + ret= 1; +ex: + if(buf != NULL) + free(buf); + return(ret); +} + + +/* @param flag bit0= append */ +int Sfile_str(char target[SfileadrL], char *source, int flag) +{ + int l; + + l= strlen(source); + if(flag&1) + l+= strlen(target); + if(l>=SfileadrL) { + fprintf(stderr, "--- Path string overflow (%d > %d). Malicious input ?\n", + l,SfileadrL-1); + return(0); + } + if(flag&1) + strcat(target, source); + else + strcpy(target, source); + return(1); +} + + +/** Combine environment variable HOME with given filename + @param filename Address relative to $HOME + @param fileadr Resulting combined address + @param fa_size Size of array fileadr + @param flag Unused yet + @return 1=ok , 0=no HOME variable , -1=result address too long +*/ +int Sfile_home_adr_s(char *filename, char *fileadr, int fa_size, int flag) +{ + char *home; + + strcpy(fileadr,filename); + home= getenv("HOME"); + if(home==NULL) + return(0); + if(strlen(home)+strlen(filename)+1>=fa_size) + return(-1); + strcpy(fileadr,home); + if(filename[0]!=0){ + strcat(fileadr,"/"); + strcat(fileadr,filename); + } + return(1); +} + + +/** Return a double representing seconds and microseconds since 1 Jan 1970 */ +double Sfile_microtime(int flag) +{ + struct timeval tv; + struct timezone tz; + gettimeofday(&tv,&tz); + return((double) (tv.tv_sec+1.0e-6*tv.tv_usec)); +} + + +int Sfile_decode_datestr(struct tm *reply, char *text, int flag) +/* YYMMDD[.hhmm[ss]] */ +{ + int i,l; + time_t current_time; + struct tm *now; + + current_time= time(0); + now= localtime(¤t_time); + for(i=0;i<sizeof(struct tm);i++) + ((char *) reply)[i]= ((char *) now)[i]; + + if(text[0]<'0'|| (text[0]>'9' && text[0]<'A') || text[0]>'Z') + return(0); + l= strlen(text); + for(i=1;i<l;i++) + if(text[i]<'0'||text[i]>'9') + break; + if(i!=6) + return(0); + if(text[i]==0) + goto decode; + if(text[i]!='.' || (l!=11 && l!=13)) + return(0); + for(i++;i<l;i++) + if(text[i]<'0'||text[i]>'9') + break; + if(i!=l) + return(0); + +decode:; + reply->tm_hour= 0; + reply->tm_min= 0; + reply->tm_sec= 0; + i= 0; + if(text[0]>='A') + reply->tm_year= 100+(text[i]-'A')*10+text[1]-'0'; + else + reply->tm_year= 10*(text[0]-'0')+text[1]-'0'; + reply->tm_mon= 10*(text[2]-'0')+text[3]-'0'-1; + reply->tm_mday= 10*(text[4]-'0')+text[5]-'0'; + if(l==6) + return(1); + reply->tm_hour= 10*(text[7]-'0')+text[8]-'0'; + reply->tm_min= 10*(text[9]-'0')+text[10]-'0'; + if(l==11) + return(1); + reply->tm_sec= 10*(text[11]-'0')+text[12]-'0'; + return(1); +} + +#endif /* Xorriso_sfile_externaL */ + + +/* --------------------------------- misc --------------------------------- */ + + +int Strcmp(const void *pt1, const void *pt2) +{ + return(strcmp(*((char **) pt1), *((char **) pt2))); +} + + +int Sort_argv(int argc, char **argv, int flag) +{ + if(argc<=0) + return(2); + qsort(argv,(size_t) argc,sizeof(char *),Strcmp); + return(1); +} + + +/** Convert a text into a number of type double and multiply it by unit code + [kmgtpe] (2^10 to 2^60) or [s] (2048). (Also accepts capital letters.) + @param text Input like "42", "2k", "3.14m" or "-1g" + @param flag Bitfield for control purposes: + bit0= return -1 rathern than 0 on failure + @return The derived double value +*/ +double Scanf_io_size(char *text, int flag) +/* + bit0= default value -1 rather than 0 +*/ +{ + int c; + double ret= 0.0; + + if(flag&1) + ret= -1.0; + if(text[0]==0) + return(ret); + sscanf(text,"%lf",&ret); + c= text[strlen(text)-1]; + if(c=='k' || c=='K') ret*= 1024.0; + if(c=='m' || c=='M') ret*= 1024.0*1024.0; + if(c=='g' || c=='G') ret*= 1024.0*1024.0*1024.0; + if(c=='t' || c=='T') ret*= 1024.0*1024.0*1024.0*1024.0; + if(c=='p' || c=='P') ret*= 1024.0*1024.0*1024.0*1024.0*1024.0; + if(c=='e' || c=='E') ret*= 1024.0*1024.0*1024.0*1024.0*1024.0*1024.0; + if(c=='s' || c=='S') ret*= 2048.0; + return(ret); +} + + +int Decode_date_input_format(struct tm *erg, char *text, int flag) +/* MMDDhhmm[[CC]YY][.ss]] */ +{ + int i,l,year; + time_t current_time; + struct tm *now; + + current_time= time(0); + now= localtime(¤t_time); + for(i=0;i<sizeof(struct tm);i++) + ((char *) erg)[i]= ((char *) now)[i]; + + l= strlen(text); + for(i=0;i<l;i++) + if(text[i]<'0'||text[i]>'9') + break; + if(i!=8 && i!=10 && i!=12) + return(0); + if(text[i]==0) + goto decode; + if(text[i]!='.' || l!=15) + return(0); + i++; + if(text[i]<'0'||text[i]>'9') + return(0); + i++; + if(text[i]<'0'||text[i]>'9') + return(0); + +decode:; + /* MMDDhhmm[[CC]YY][.ss]] */ + i= 0; + erg->tm_mon= 10*(text[0]-'0')+text[1]-'0'-1; + erg->tm_mday= 10*(text[2]-'0')+text[3]-'0'; + erg->tm_hour= 10*(text[4]-'0')+text[5]-'0'; + erg->tm_min= 10*(text[6]-'0')+text[7]-'0'; + erg->tm_sec= 0; + if(l==8) + return(1); + if(l>10){ + year= 1000*(text[8]-'0')+100*(text[9]-'0')+10*(text[10]-'0')+(text[11]-'0'); + }else{ + year= 1900+10*(text[8]-'0')+(text[9]-'0'); + if(year<1970) + year+= 100; + } + erg->tm_year= year-1900; + if(l<=12) + return(1); + erg->tm_sec= 10*(text[13]-'0')+text[14]-'0'; + return(1); +} + + +int Decode_date_weekday(char *text, int flag) +{ + int i; + static char days[][4]= {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", ""}; + + for(i= 0; days[i][0]!=0; i++) + if(strncmp(text,days[i],3)==0) + return(i); + if((strlen(text)==3 || (strlen(text)==4 && text[3]==',')) && + isalpha(text[0]) && isalpha(text[1]) && isalpha(text[2])) + return(7); + return(-1); +} + + +int Decode_date_month(char *text, int flag) +{ + int i; + static char months[][4]= {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ""}; + + for(i= 0; months[i][0]!=0; i++) + if(strncmp(text,months[i],3)==0) + return(i); + return(-1); +} + + +/* @return -1=not a number, -2=not a day , 1 to 31 day of month */ +int Decode_date_mday(char *text, int flag) +{ + int ret, i; + + for(i= 0; text[i]!=0; i++) + if(!isdigit(text[i])) + return(-1); + if(strlen(text)>2 || text[0]==0) + return(-2); + sscanf(text, "%d", &ret); + if(ret<=0 || ret>31) + return(-2); + return(ret); +} + +int Decode_date_hms(char *text, struct tm *erg, int flag) +{ + int i, hour= -1, minute= -1, second= 0; + + for(i= 0; i<9; i+= 3) { + if(i==6&&text[i]==0) + break; + if(!isdigit(text[i])) + return(-1); + if(!isdigit(text[i+1])) + return(-1); + if(text[i+2]!=':' && !(text[i+2]==0 && i>=3)) + return(-1); + if(i==0) + sscanf(text+i,"%d",&hour); + else if(i==3) + sscanf(text+i,"%d",&minute); + else + sscanf(text+i,"%d",&second); + } + if(hour<0 || hour>23 || minute<0 || minute>59 || second>59) + return(-1); + erg->tm_hour= hour; + erg->tm_min= minute; + erg->tm_sec= second; + return(1); +} + + +/* @return -1=not a number, -2=not a year , >=0 years AD */ +int Decode_date_year(char *text, int flag) +{ + int ret, i; + + for(i= 0; text[i]!=0; i++) + if(!isdigit(text[i])) + return(-1); + if(strlen(text)!=4) + return(-2); + sscanf(text, "%d", &ret); + if(ret<0 || ret>3000) + return(-2); + return(ret); +} + + +int Decode_date_timezone(char *text, struct tm *erg, int flag) +{ + int i; + static char tzs[][5]= {"GMT", "CET", "CEST", "0000", ""}; + + for(i= 0; tzs[i][0]!=0; i++) + if(strcmp(text,tzs[i])==0) { + + /* ??? >>> what to do with timezone info ? Add to ->tm_hour ? */ + + return(1); + } + if(text[0]=='+' || text[0]=='-') { + for(i= 1; text[i]!=0; i++) + if(!isdigit(text[i])) + return(-1); + if(i!=5) + return(-1); + + /* ??? >>> what to do with timezone info ? Add to ->tm_hour ? */ + + return(1); + } else { + for(i= 0; text[i]!=0; i++) + if(text[i]<'A' || text[i]>'Z') + return(-1); + if(i!=3 && i!=4) + return(-1); + return(2); + } +} + + +int Decode_date_output_format(struct tm *erg, char *text, int flag) +/* Thu Nov 8 09:07:50 CET 2007 */ +/* Sat, 03 Nov 2007 08:58:30 +0100 */ +/* Nov 7 23:24 */ +{ + int ret, i, argc= 0, seen_year= 0, seen_month= 0, seen_day= 0, seen_time= 0; + char **argv= NULL; + struct tm *now; + time_t timep; + + memset(erg, 0, sizeof(*erg)); + erg->tm_isdst= -1; + ret= Sfile_make_argv("xorriso", text, &argc, &argv, 0); + if(ret<=0) + goto ex; + for(i= 1; i<argc; i++) { + if(!seen_month) { + ret= Decode_date_month(argv[i], 0); + if(ret>=0) { + seen_month= 1; + erg->tm_mon= ret; + continue; + } + } + if(!seen_day) { + ret= Decode_date_mday(argv[i], 0); + if(ret>0) { + seen_day= 1; + erg->tm_mday= ret; + continue; + } + if(ret==-2) /* first pure number must be day of month */ + {ret= 0; goto ex;} + } + if(!seen_time) { + ret= Decode_date_hms(argv[i], erg, 0); + if(ret>0) { + seen_time= 1; + continue; + } + } + if(!seen_year) { + ret= Decode_date_year(argv[i], 0); + if(ret>0) { + erg->tm_year= ret-1900; + seen_year= 1; + continue; + } + } + + /* ignorants have to stay at the end of the loop */ + + ret= Decode_date_timezone(argv[i], erg, 0); + if(ret>=0) + continue; + ret= Decode_date_weekday(argv[i], 0); + if(ret>=0) + continue; /* ignore weekdays */ + + {ret= 0; goto ex;} /* unrecognizable component */ + } + + if(!(seen_day && seen_month)) + {ret= 0; goto ex;} + if(!seen_year) { /* then use this year */ + timep= time(NULL); + now= localtime(&timep); + erg->tm_year= now->tm_year; + } + ret= 1; +ex: + Sfile_make_argv("", "", &argc, &argv, 2); /* release storage */ + return(ret); +} + + +int Decode_xorriso_timestamp(struct tm *erg, char *code, int flag) + /* 2007.11.07.225624 */ +{ + char buf[20]; + int year,month,day,hour= 0,minute= 0,second= 0, i, l, mem; + + memset(erg, 0, sizeof(*erg)); + erg->tm_isdst= -1; + + l= strlen(code); + if(l>17 || l<10) + return(0); + strcpy(buf, code); + for(i= 0; buf[i]!=0 && i<4; i++) + if(!isdigit(buf[i])) + return(0); + if(buf[4]!='.') + return(0); + buf[4]= 0; + sscanf(buf, "%d", &year); + if(year<1900 || year>3000) + return(0); + if(!(isdigit(buf[5]) && isdigit(buf[6]) && buf[7]=='.')) + return(0); + buf[7]= 0; + sscanf(buf+5, "%d", &month); + if(month<1 || month>12) + return(0); + if(!(isdigit(buf[8]) && isdigit(buf[9]) && (buf[10]=='.' || buf[10]==0))) + return(0); + buf[10]= 0; + sscanf(buf+8, "%d", &day); + if(day<1 || day>31) + return(0); + if(l==10) + goto done; + if(!(isdigit(buf[11]) && isdigit(buf[12]) && + (isdigit(buf[13]) || buf[13]==0))) + return(0); + mem= buf[13]; + buf[13]= 0; + sscanf(buf+11, "%d", &hour); + buf[13]= mem; + if(hour<0 || hour>23) + return(0); + if(l==13) + goto done; + if(!(isdigit(buf[13]) && isdigit(buf[14]) && + (isdigit(buf[15]) || buf[15]==0))) + return(0); + mem= buf[15]; + buf[15]= 0; + sscanf(buf+13, "%d", &minute); + buf[15]= mem; + if(minute<0 || minute>59) + return(0); + if(l==15) + goto done; + if(!(isdigit(buf[15]) && isdigit(buf[16]) && buf[17]==0)) + return(0); + sscanf(buf+15, "%d", &second); + if(second<0 || second>59) + return(0); + +done:; + erg->tm_year= year-1900; + erg->tm_mon= month-1; + erg->tm_mday= day; + erg->tm_hour= hour; + erg->tm_min= minute; + erg->tm_sec= second; + return(1); +} + + +time_t Decode_timestring(char *code, time_t *date, int flag) +{ + char *cpt,scale_chr; + double value,seconds; + struct tm result_tm; + int seconds_valid= 0; + + *date= 0; + cpt= code; + if(code[0]=='-' || code[0]=='+' || code[0]=='=' || code[0]=='@'){ + if(code[1]==0) + return(0); + if(!isdigit(code[1])) + return(0); + value= -1; + if(code[0]=='=' || code[0]=='@') { + seconds= 0; + sscanf(code+1,"%lf",&value); + } else { + seconds= time(NULL); + sscanf(code,"%lf",&value); + } + scale_chr= code[strlen(code)-1]; + if(isalpha(scale_chr)) + scale_chr= tolower(scale_chr); + if (scale_chr=='s') seconds+= 1.0*value; + else if(scale_chr=='h') seconds+= 3600.0*value; + else if(scale_chr=='d') seconds+= 86400.0*value; + else if(scale_chr=='w') seconds+= 86400.0*7.0*value; + else if(scale_chr=='m') seconds+= 86400.0*31.0*value; + else if(scale_chr=='y') seconds+= 86400.0*(365.25*value+1.0); + else seconds+= 1.0*value; + seconds_valid= 1; + goto completed; + } else if(Sfile_decode_datestr(&result_tm,code,0)>0) { + /* YYMMDD[.hhmm[ss]] */ + result_tm.tm_isdst= -1; + seconds= mktime(&result_tm); + seconds_valid= 1; + goto completed; + } else if(Decode_date_input_format(&result_tm,code,0)>0) { + /* MMDDhhmm[[CC]YY][.ss]] */ + result_tm.tm_isdst= -1; + seconds= mktime(&result_tm); + seconds_valid= 1; + goto completed; + } else if(Decode_xorriso_timestamp(&result_tm, code, 0)>0) { + /* 2007.11.07.225624 */ + seconds= mktime(&result_tm); + seconds_valid= 1; + goto completed; + } else if(Decode_date_output_format(&result_tm, code, 0)>0) { + /* Thu Nov 8 09:07:50 CET 2007 */; + /* Sat, 03 Nov 2007 08:58:30 +0100 */; + /* Nov 7 23:24 */; + seconds= mktime(&result_tm); + seconds_valid= 1; + goto completed; + } + return(0); +completed:; + if(!seconds_valid) + return(0); + *date= seconds; + return(1); +} + + +/* @param flag bit0=with year and seconds + bit1-3= form + 0= ls -l format + 1= timestamp format YYYY.MM.DD.hhmmss + 2= Wdy Mon Day hh:mm:ss Year +*/ +char *Ftimetxt(time_t t, char timetext[40], int flag) +{ + char *rpt; + struct tm tms, *tmpt; + static char months[12][4]= { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + static char days[7][4]= {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; + int form; + + form= (flag>>1)&7; + tmpt= localtime_r(&t, &tms); + rpt= timetext; + rpt[0]= 0; + if(tmpt==0) + sprintf(rpt+strlen(rpt), "%12.f", (double) t); + else if (form==1) + sprintf(rpt+strlen(rpt), "%4.4d.%2.2d.%2.2d.%2.2d%2.2d%2.2d", + 1900+tms.tm_year, tms.tm_mon+1, tms.tm_mday, + tms.tm_hour, tms.tm_min, tms.tm_sec); + else if (form==2) + sprintf(rpt+strlen(rpt), "%s %s %2.2d %2.2d:%2.2d:%2.2d %4.4d", + days[tms.tm_wday], months[tms.tm_mon], tms.tm_mday, + tms.tm_hour, tms.tm_min, tms.tm_sec, 1900+tms.tm_year); + else if (flag&1) + sprintf(rpt+strlen(rpt), "%2d %3s %4.4d %2.2d:%2.2d:%2.2d", + tms.tm_mday, months[tms.tm_mon], 1900+tms.tm_year, + tms.tm_hour, tms.tm_min, tms.tm_sec); + else if(time(NULL)-t < 180*86400 && time(NULL)-t >= 0) + sprintf(rpt+strlen(rpt), "%3s %2d %2.2d:%2.2d", + months[tms.tm_mon], tms.tm_mday, tms.tm_hour, tms.tm_min); + else + sprintf(rpt+strlen(rpt), "%3s %2d %4.4d", + months[tms.tm_mon], tms.tm_mday, 1900+tms.tm_year); + return(timetext); +} + + +/* @param flag bit0= single letters */ +char *Ftypetxt(mode_t st_mode, int flag) +{ + if(flag&1) + goto single_letters; + if(S_ISDIR(st_mode)) + return("directory"); + else if(S_ISREG(st_mode)) + return("regular_file"); + else if(S_ISLNK(st_mode)) + return("symbolic_link"); + else if(S_ISBLK(st_mode)) + return("block_device"); + else if(S_ISCHR(st_mode)) + return("char_device"); + else if(S_ISFIFO(st_mode)) + return("name_pipe"); + else if(S_ISSOCK(st_mode)) + return("unix_socket"); + return("unknown"); +single_letters:; + if(S_ISDIR(st_mode)) + return("d"); + else if(S_ISREG(st_mode)) + return("-"); + else if(S_ISLNK(st_mode)) + return("l"); + else if(S_ISBLK(st_mode)) + return("b"); + else if(S_ISCHR(st_mode)) + return("c"); + else if(S_ISFIFO(st_mode)) + return("p"); + else if(S_ISSOCK(st_mode)) + return("s"); + return("?"); +} + + +int Wait_for_input(int fd, int microsec, int flag) +{ + struct timeval wt; + fd_set rds,wts,exs; + int ready; + + FD_ZERO(&rds); + FD_ZERO(&wts); + FD_ZERO(&exs); + FD_SET(fd,&rds); + FD_SET(fd,&exs); + wt.tv_sec= microsec/1000000; + wt.tv_usec= microsec%1000000; + ready= select(fd+1,&rds,&wts,&exs,&wt); + if(ready<=0) + return(0); + if(FD_ISSET(fd,&exs)) + return(-1); + if(FD_ISSET(fd,&rds)) + return(1); + return(0); +} + + +int System_uname(char **sysname, char **release, char **version, + char **machine, int flag) +{ + int ret; + static struct utsname uts; + static int initialized= 0; + + if(initialized == 0) { + ret= uname(&uts); + if(ret != 0) + initialized = -1; + } + if(initialized == -1) + return(0); + if(sysname != NULL) + *sysname= uts.sysname; + if(release != NULL) + *release= uts.release; + if(version != NULL) + *version= uts.version; + if(machine != NULL) + *machine= uts.machine; + return(1); +} + +/* ------------------------------------------------------------------------ */ + + +#ifndef Xorriso_sregex_externaL + +#ifndef Smem_malloC +#define Smem_malloC malloc +#endif +#ifndef Smem_freE +#define Smem_freE free +#endif + + +int Sregex_string_cut(char **handle, char *text, int len, int flag) +/* + bit0= append (text!=NULL) +*/ +{ + int l=0; + char *old_handle; + + if((flag&1)&&*handle!=NULL) + l+= strlen(*handle); + old_handle= *handle; + if(text!=NULL) { + l+= len; + *handle= TSOB_FELD(char,l+1); + if(*handle==NULL) { + *handle= old_handle; + return(0); + } + if((flag&1) && old_handle!=NULL) + strcpy(*handle,old_handle); + else + (*handle)[0]= 0; + if(len>0) + strncat(*handle,text,len); + } else { + *handle= NULL; + } + if(old_handle!=NULL) + Smem_freE(old_handle); + return(1); +} + + +int Sregex_string(char **handle, char *text, int flag) +/* + bit0= append (text!=NULL) +*/ +{ + int ret,l=0; + + if(text!=NULL) + l= strlen(text); + +/* #define Sregex_looking_for_contenT 1 */ +#ifdef Sregex_looking_for_contenT + /* a debugging point if a certain text content has to be caught */ + if(text!=NULL) + if(strcmp(text,"clear")==0) + ret= 0; +#endif + + ret= Sregex_string_cut(handle,text,l,flag&1); + return(ret); +} + + +/* + vars[][0] points to the variable names, vars[][1] to their contents. + start marks the begin of variable names. It must be non-empty. esc before + start disables this meaning. start and esc may be equal but else they must + have disjoint character sets. + end marks the end of a variable name. It may be empty but if non-empty it + must not appear in vars[][0]. + @param flag bit0= Substitute unknown variables by empty text + (else copy start,name,end unaltered to result). + Parameter end must be non-empty for that. +*/ +int Sregex_resolve_var(char *form, char *vars[][2], int num_vars, + char *start, char *end, char *esc, + char *result, int result_size, int flag) +{ + int l_e, l_v, l_s, l_esc, i, start_equals_esc; + char *rpt, *wpt, *spt, *npt, *ept; + + if(start[0] == 0) /* It is not allowed to have no start marker */ + return(-1); + l_s= strlen(start); + l_e= strlen(end); + l_esc= strlen(esc); + start_equals_esc= !strcmp(start, esc); + rpt= form; + wpt= result; + wpt[0]= 0; + while(1) { + + /* look for start mark */ + spt= strstr(rpt, start); + if(spt == NULL) { + if((wpt - result) + strlen(rpt) >= result_size) + return(0); + strcpy(wpt, rpt); + wpt+= strlen(wpt); + break; + } + + /* copy cleartext part up to next variable */ + if((wpt - result) + (spt - rpt) >= result_size) + return(0); + strncpy(wpt, rpt, spt - rpt); + wpt+= spt - rpt; + *wpt= 0; + rpt= spt; + npt= spt + l_s; + + /* handle eventual escape */ + if(start_equals_esc) { + if(strncmp(spt + l_s, esc, l_esc) == 0) { + /* copy esc and start */ + if((wpt - result) + l_esc + l_s >= result_size) + return(0); + strncpy(wpt, spt, l_esc + l_s); + wpt+= l_esc + l_s; + rpt+= l_esc + l_s; + *wpt= 0; + continue; + } + } else { + /* escape would be already copied */ + if(l_esc > 0 && spt - form >= l_esc) { + if(strncmp(spt - l_esc, esc, l_esc) == 0) { + /* copy start */ + if((wpt - result) + l_s >= result_size) + return(0); + strncpy(wpt, spt, l_s); + wpt+= l_s; + rpt+= l_s; + *wpt= 0; + continue; + } + } + } + + /* Memorize eventual end mark for default handling */; + ept= NULL; + if(l_e > 0) + ept= strstr(npt, end); + + /* Look for defined variable name */ + for(i = 0; i < num_vars; i++) { + if(strncmp(npt, vars[i][0], strlen(vars[i][0])) == 0 + && (l_e == 0 || strncmp(npt + strlen(vars[i][0]), end, l_e) == 0)) + break; + } + if(i < num_vars) { + /* substitute found variable */ + l_v= strlen(vars[i][0]); + if((wpt - result) + strlen(vars[i][1]) >= result_size) + return(0); + strcpy(wpt, vars[i][1]); + rpt= npt + strlen(vars[i][0]) + l_e; + } else if((flag & 1) && ept != NULL) { + /* skip up to end mark */ + rpt= ept + l_e; + } else if(ept != NULL) { + /* copy start,name,end */ + if((wpt - result) + (ept - rpt) + l_e >= result_size) + return(0); + strncpy(wpt, rpt, (ept - rpt) + l_e); + rpt= ept + l_e; + } else { + /* copy start marker only */ + if((wpt - result) + l_s >= result_size) + return(0); + strncpy(wpt, rpt, l_s); + rpt= rpt + l_s; + } + wpt+= strlen(wpt); + *wpt= 0; + } + return(1); +} + + +/* @param flag bit0= only test expression whether compilable +*/ +int Sregex_match(char *pattern, char *text, int flag) +{ + int ret; + char re_text[2*SfileadrL]; + regex_t re; + regmatch_t match[1]; + + Xorriso__bourne_to_reg(pattern, re_text, 0); + ret= regcomp(&re, re_text, 0); + if(ret != 0) + return(-1); + if(flag & 1) { + regfree(&re); + return(1); + } + ret= regexec(&re, text, 1, match, 0); + regfree(&re); + if(ret != 0) + return(0); + return(1); +} + + +#endif /* Xorriso_sregex_externaL */ + + + +/* @param flag bit0= append to out_text rather than overwrite it +*/ +char *Text_shellsafe(char *in_text, char *out_text, int flag) +{ + int l,i,ol= 0,w=0; + + if(flag&1) + ol= w= strlen(out_text); + /* enclose everything by hard quotes */ + l= strlen(in_text); + out_text[w++]= '\''; + for(i=0;i<l;i++){ + if(in_text[i]=='\''){ + if(w+7>5*SfileadrL+ol) + goto overflow; + /* escape hard quote within the text */ + out_text[w++]= '\''; + out_text[w++]= '"'; + out_text[w++]= '\''; + out_text[w++]= '"'; + out_text[w++]= '\''; + } else { + if(w+3>5*SfileadrL) { +overflow:; + strncpy(out_text, "'xorriso: TEXT MUCH TOO LONG ... ",33); + break; + } + out_text[w++]= in_text[i]; + } + } + out_text[w++]= '\''; + out_text[w++]= 0; + return(out_text); +} + + +#ifndef Xorriso_fileliste_externaL + +/* ??? ts A71006 : Is this compatible with mkisofs pathspecs ? + I dimly remember so */ + +int Fileliste__target_source_limit(char *line, char sep, char **limit_pt, + int flag) +{ + char *npt; + + for(npt= line;*npt!=0;npt++) { + if(*npt=='\\') { + if(*(npt+1)!=0) + npt++; + continue; + } + if(*npt=='=') + break; + } + if(*npt==0) + npt= NULL; + (*limit_pt)= npt; + return(npt!=NULL); +} + +#endif /* ! Xorriso_fileliste_externaL */ + + +/* ------------------------------------------------------------------------ */ +/* DirseQ : crawl along a directory's content list */ + +static int Dirseq_buffer_sizE= 100; + +struct DirseQ { + char adr[SfileadrL]; + DIR *dirpt; + int count; + char **buffer; + int buffer_size; + int buffer_fill; + int buffer_rpt; + + struct DirseQ *next; +}; + +int Dirseq_destroy(struct DirseQ **o, int flag); +int Dirseq_next_adrblock(struct DirseQ *o, char *replies[], int *reply_count, + int max_replies, int flag); + + +int Dirseq_new(struct DirseQ **o, char *adr, int flag) +/* + bit0= with non-fatal errors do not complain about failed opendir() +*/ +{ + int ret,i,severe_error; + struct DirseQ *m; + + m= *o= TSOB_FELD(struct DirseQ,1); + if(m==NULL) + return(-1); + m->adr[0]= 0; + m->dirpt= NULL; + m->count= 0; + m->buffer= NULL; + m->buffer_size= 0; + m->buffer_fill= 0; + m->buffer_rpt= 0; + m->next= NULL; + if(Sfile_str(m->adr, adr, 0)<=0) + {ret= 0; goto failed;} + m->buffer= TSOB_FELD(char *,Dirseq_buffer_sizE); + if(m->buffer==NULL) + {ret= -1; goto failed;} + m->buffer_size= Dirseq_buffer_sizE; + for(i= 0;i<m->buffer_size;i++) + m->buffer[i]= NULL; + if(adr[0]==0) + m->dirpt= opendir("."); + else + m->dirpt= opendir(adr); + if(m->dirpt==NULL) { + severe_error= (errno && errno!=ENOENT && errno!=EACCES && errno!=ENOTDIR); + if(severe_error || !(flag&1)) + fprintf(stderr,"opendir(%s) failed : %s\n",adr,strerror(errno)); + ret= -severe_error; + goto failed; + } + return(1); +failed:; + Dirseq_destroy(o,0); + return(ret); +} + + +int Dirseq_destroy(struct DirseQ **o, int flag) +{ + int i; + + if(*o==NULL) + return(0); + if((*o)->dirpt!=NULL) + closedir((*o)->dirpt); + if((*o)->buffer!=NULL) { + for(i=0;i<(*o)->buffer_size;i++) + if((*o)->buffer[i]!=NULL) + free((*o)->buffer[i]); + free((char *) (*o)->buffer); + } + free((char *) *o); + (*o)= NULL; + return(1); +} + + +int Dirseq_set_next(struct DirseQ *o, struct DirseQ *next, int flag) +{ + o->next= next; + return(1); +} + + +int Dirseq_get_next(struct DirseQ *o, struct DirseQ **next, int flag) +{ + *next= o->next; + return(1); +} + + +int Dirseq_get_adr(struct DirseQ *o, char **adrpt, int flag) +{ + *adrpt= o->adr; + return(1); +} + + +int Dirseq_rewind(struct DirseQ *o, int flag) +{ + rewinddir(o->dirpt); + return(1); +} + + +int Dirseq_next_adr(struct DirseQ *o, char reply[SfileadrL], int flag) +/* +flag: + bit0= permission to use buffer + bit1= do not increment counter + bit2= ignore buffer in any case + bit3= do not exclude '.' and '..' + bit4= sort buffer + bit5= sort only incomplete last buffer +return: + <0 error + 0= no more entries available + 1= ok, reply is valid +*/ +{ + int ret; + struct dirent *entry; + char *name; + + static int override_flag_0= 0,override_flag_1= 32; + flag= (flag&~override_flag_0)|override_flag_1; + + if((flag&1) && o->buffer_rpt>=o->buffer_fill) { + /* permission to buffer and buffer empty : load a buffer */ + ret= Dirseq_next_adrblock(o,o->buffer,&(o->buffer_fill), + o->buffer_size,2|4|(flag&16)); + if(ret<=0) + return(ret); + o->buffer_rpt= 0; + if((flag&32) && o->buffer_fill<o->buffer_size && o->buffer_fill>0) + Sort_argv(o->buffer_fill,o->buffer,0); + } + if(o->buffer_rpt<o->buffer_fill && !(flag&4)) { + ret= Sfile_str(reply,o->buffer[o->buffer_rpt],0); + Sregex_string(&(o->buffer[o->buffer_rpt]),NULL,0); + if(ret<=0) + return(-1); + (o->buffer_rpt)++; + if(!(flag&2)) + o->count++; + return(1); + } + do { + entry= readdir(o->dirpt); + if(entry==NULL) { + /* >>> how to distinguish error from EOF , do i need a (FILE *) ? */ + return(0); + } + if(strlen(entry->d_name)>=SfileadrL) { + fprintf(stderr,"--- oversized directory entry (number %d) :\n %s", + o->count+1,entry->d_name); + return(-1); + } + name= entry->d_name; + if(flag&8) + break; + /* skip "." and ".." */ + } while(name[0]=='.' && ((name[1]=='.' && name[2]==0) || name[1]==0)); + if(Sfile_str(reply,name,0)<=0) + return(-1); + if(!(flag&2)) + o->count++; + return(1); +} + + +int Dirseq_next_adrblock(struct DirseQ *o, char *replies[], int *reply_count, + int max_replies, int flag) +/* @param replies A vector of Sregex_string pointers */ +/* +flag: + bit0= permission to use buffer + bit1= do not increment counter + bit2= ignore buffer in any case + bit4= sort replies +return: + <0 error + 0= no more entries available + 1= ok, reply is valid +*/ +{ + int i,ret; + char reply[SfileadrL]; + + *reply_count= 0; + for(i=0;i<max_replies;i++) { + ret= Dirseq_next_adr(o,reply,flag&(1|2|4)); + if(ret<0) + return(ret); + if(ret==0) + break; + if(Sregex_string(&(replies[i]),reply,0)<=0) + return(-1); + (*reply_count)++; + } + if((*reply_count)==0) + return(0); + if(flag&16) + Sort_argv(*reply_count,replies,0); + return(1); +} + + +/* --------------------------------- Xorriso_lsT --------------------------- */ + + +/* + @param flag Bitfield for control purposes + bit0= insert before link rather than after it + bit1= do not copy data (e.g. because *data is invalid) +*/ +int Xorriso_lst_new_binary(struct Xorriso_lsT **lstring, char *data, + int data_len, struct Xorriso_lsT *link, int flag) +{ + int ret; + struct Xorriso_lsT *s; + + s= TSOB_FELD(struct Xorriso_lsT,1); + if(s==NULL) + return(-1); + s->text= NULL; + s->next= s->prev= NULL; + + if(data_len<=0) + {ret= -1; goto failed;} + s->text= Smem_malloC(data_len); + if(s->text==NULL) + {ret= -1; goto failed;} + if(!(flag&2)) + memcpy(s->text,data,data_len); + + if(link==NULL) { + ; + } else if(flag&1) { + s->next= link; + s->prev= link->prev; + if(link->prev!=NULL) + link->prev->next= s; + link->prev= s; + } else { + s->prev= link; + s->next= link->next; + if(link->next!=NULL) + link->next->prev= s; + link->next= s; + } + *lstring= s; + return(1); +failed:; + *lstring= s; + Xorriso_lst_destroy(lstring,0); + return(-1); +} + + +/* + @param flag Bitfield for control purposes + bit0= insert before link rather than after it +*/ +int Xorriso_lst_new(struct Xorriso_lsT **lstring, char *text, + struct Xorriso_lsT *link, int flag) +{ + int ret; + + ret= Xorriso_lst_new_binary(lstring,text,strlen(text)+1,link,flag&1); + return(ret); +} + + +/* + @param flag Bitfield for control purposes + bit0= do not set *lstring to NULL +*/ +int Xorriso_lst_destroy(struct Xorriso_lsT **lstring, int flag) +{ + struct Xorriso_lsT *s; + + s= *lstring; + if(s==NULL) + return(0); + if(s->prev!=NULL) + s->prev->next= s->next; + if(s->next!=NULL) + s->next->prev= s->prev; + if(s->text!=NULL) + Smem_freE(s->text); + Smem_freE((char *) s); + if(!(flag&1)) + *lstring= NULL; + return(1); +} + + +int Xorriso_lst_destroy_all(struct Xorriso_lsT **lstring, int flag) +{ + struct Xorriso_lsT *s,*next; + + if(lstring==NULL) + return(-1); + if((*lstring)==NULL) + return(0); + for(s= *lstring; s->prev!=NULL; s= s->prev); + for(;s!=NULL;s= next){ + next= s->next; + Xorriso_lst_destroy(&s,0); + } + *lstring= NULL; + return(1); +} + + +int Xorriso_lst_append_binary(struct Xorriso_lsT **entry, + char *data, int data_len, int flag) +{ + struct Xorriso_lsT *target= NULL,*newby; + + if(*entry!=NULL) + for(target= *entry; target->next!=NULL; target= target->next); + if(Xorriso_lst_new_binary(&newby, data, data_len, target, 0)<=0) + return(-1); + if(*entry==NULL) + *entry= newby; + return(1); +} + + +struct Xorriso_lsT *Xorriso_lst_get_next(struct Xorriso_lsT *entry, int flag) +{ + return(entry->next); +} + + +struct Xorriso_lsT *Xorriso_lst_get_prev(struct Xorriso_lsT *entry, int flag) +{ + return(entry->prev); +} + + +char *Xorriso_lst_get_text(struct Xorriso_lsT *entry, int flag) +{ + return(entry->text); +} + + +/* ------------------------------ LinkiteM -------------------------------- */ + +struct LinkiteM { + char *link_path; + dev_t target_dev; + ino_t target_ino; + int link_count; + struct LinkiteM *next; +}; + +int Linkitem_destroy(struct LinkiteM **o, int flag); + + +int Linkitem_new(struct LinkiteM **o, char *link_path, dev_t target_dev, + ino_t target_ino, struct LinkiteM *next, int flag) +{ + struct LinkiteM *m; + + m= *o= TSOB_FELD(struct LinkiteM,1); + if(m==NULL) + return(-1); + m->target_dev= target_dev; + m->target_ino= target_ino; + m->next= next; + m->link_count= 1; + if(next!=NULL) + m->link_count= m->next->link_count+1; + m->link_path= strdup(link_path); + if(m->link_path==NULL) + goto failed; + return(1); +failed:; + Linkitem_destroy(o, 0); + return(-1); +} + + +int Linkitem_destroy(struct LinkiteM **o, int flag) +{ + if((*o)==NULL) + return(0); + if((*o)->link_path!=NULL) + free((*o)->link_path); + free((char *) (*o)); + *o= NULL; + return(1); +} + + +int Linkitem_reset_stack(struct LinkiteM **o, struct LinkiteM *to, int flag) +{ + struct LinkiteM *m, *m_next= NULL; + + /* Prevent memory corruption */ + for(m= *o; m!=to; m= m->next) + if(m==NULL) { /* this may actually not happen */ + *o= to; + return(-1); + } + + for(m= *o; m!=to; m= m_next) { + m_next= m->next; + Linkitem_destroy(&m, 0); + } + *o= to; + return(1); +} + + +int Linkitem_find(struct LinkiteM *stack, dev_t target_dev, ino_t target_ino, + struct LinkiteM **result, int flag) +{ + struct LinkiteM *m; + + for(m= stack; m!=NULL; m= m->next) { + if(target_dev == m->target_dev && target_ino == m->target_ino) { + *result= m; + return(1); + } + } + return(0); +} + + +/* ------------------------------- FindjoB -------------------------------- */ + + +struct FindjoB { + char *start_path; + + char *name_expr; + regex_t name_re; + regmatch_t name_match; + + /* b = blockdev + c = chardev + d = directory + p = fifo + f = reg + - = reg + s = socket + m = subordinate mountpoint (does never match find start directory) + X = other + 0x0 = test inactive + */ + char file_type; + + int start_lba; + int end_lba; + int damage_filter; /* -1=only undamaged , 0=all , 1=only damaged */ + int commit_filter; /* bit0= test -pending_data : uncommitted regular files */ + + void *wanted_node; /* if not NULL, then only this node address matches */ + + /* 0= echo + 1= rm (also rmdir) + 2= rm_r +>>> 3= mv target + 4= chown user + 5= chgrp group + 6= chmod mode_and mode_or + 7= alter_date type date + 8= lsdl + 9= chown_r user + 10= chgrp_r group + 11= chmod_r mode_and mode_or + 12= alter_date_r type date + 13= find + 14= compare disk_equivalent_of_start_path + 15= in_iso iso_rr_equivalent_of_start_path + 16= not_in_iso iso_rr_equiv + 17= update disk_equiv + 18= add_missing iso_rr_equiv + 19= empty_iso_dir iso_rr_equiv + 20= is_full_in_iso iso_rr_equiv + 21= report_damage + 22= report_lba + 23= internal:memorize path of last matching node in found_path + */ + int action; + char *target; + uid_t user; + gid_t group; + mode_t mode_and, mode_or; + int type; /* see Xorriso_set_time flag */ + time_t date; + char *found_path; + struct FindjoB *subjob; +}; + + +int Findjob_new(struct FindjoB **o, char *start_path, int flag) +{ + struct FindjoB *m; + + m= *o= TSOB_FELD(struct FindjoB,1); + if(m==NULL) + return(-1); + m->start_path= NULL; + m->name_expr= NULL; + m->file_type= 0; + m->start_lba= -1; + m->end_lba= -1; + m->damage_filter= 0; + m->commit_filter= 0; + m->wanted_node= NULL; + m->action= 0; /* print */ + m->target= NULL; /* a mere pointer, not managed memory */ + m->user= 0; + m->group= 0; + m->type= 0; + m->date= 0; + m->start_path= strdup(start_path); + if(m->start_path==NULL) + goto failed; + m->found_path= NULL; + m->subjob= NULL; + return(1); +failed:; + Findjob_destroy(o, 0); + return(-1); +} + + +int Findjob_destroy(struct FindjoB **o, int flag) +{ + struct FindjoB *m; + + m= *o; + if(m==NULL) + return(0); + if(m->start_path!=NULL) + free(m->start_path); + if(m->name_expr!=NULL) { + regfree(&(m->name_re)); + free(m->name_expr); + } + Findjob_destroy(&(m->subjob), 0); + free((char *) m); + *o= NULL; + return(1); +} + + +int Findjob_set_start_path(struct FindjoB *o, char *start_path, int flag) +{ + if(o->start_path!=NULL) + free(o->start_path); + if(start_path!=NULL) { + o->start_path= strdup(start_path); + if(o->start_path==NULL) + return(-1); + } else + o->start_path= NULL; + return(1); +} + + +int Findjob_get_start_path(struct FindjoB *o, char **start_path, int flag) +{ + *start_path= o->start_path; + return(1); +} + + +int Findjob_set_name_expr(struct FindjoB *o, char *name_expr, int flag) +{ + char regexpr[2*SfileadrL+2]; + + if(o->name_expr!=NULL) { + regfree(&(o->name_re)); + free(o->name_expr); + o->name_expr= NULL; + } + if(strlen(name_expr)>=SfileadrL) + return(0); + o->name_expr= strdup(name_expr); + if(o->name_expr==NULL) + return(-1); + Xorriso__bourne_to_reg(name_expr, regexpr, 0); + if(regcomp(&(o->name_re), regexpr, 0)!=0) + return(0); + return(1); +} + + +int Findjob_set_file_type(struct FindjoB *o, char file_type, int flag) +{ + static char known[]= {"bcdpf-lsmeX"}; + + if(file_type!=0) + if(strchr(known, file_type)==NULL) + return(0); + o->file_type= file_type; + return(1); +} + + +int Findjob_set_lba_range(struct FindjoB *o, int start_lba, int count, + int flag) +{ + o->start_lba= start_lba; + o->end_lba= start_lba + count - 1; + return(1); +} + + +/* @param value -1= only undamaged files, 0= all files, 1= only damaged files +*/ +int Findjob_set_damage_filter(struct FindjoB *o, int value, int flag) +{ + if(value < 0) + o->damage_filter= -1; + else if(value > 0) + o->damage_filter= 1; + else + o->damage_filter= 0; + return(1); +} + + +int Findjob_get_lba_damage_filter(struct FindjoB *o, int *start_lba, + int *end_lba, int *damage_filter, int flag) +{ + *start_lba= o->start_lba; + *end_lba= o->end_lba; + *damage_filter= o->damage_filter; + return(1); +} + + +int Findjob_set_commit_filter(struct FindjoB *o, int mask, int values, + int flag) +{ + o->commit_filter&= ~mask; + o->commit_filter|= (mask & values); + return(1); +} + + +int Findjob_get_commit_filter(struct FindjoB *o, int *commit_filter, int flag) +{ + *commit_filter= o->commit_filter; + return(1); +} + + +int Findjob_set_wanted_node(struct FindjoB *o, void *wanted_node, int flag) +{ + o->wanted_node= wanted_node; + return(1); +} + + +int Findjob_get_wanted_node(struct FindjoB *o, void **wanted_node, int flag) +{ + *wanted_node= o->wanted_node; + return(1); +} + + +int Findjob_set_found_path(struct FindjoB *o, char *path, int flag) +{ + if(o->found_path != NULL) + free(o->found_path); + if(path != NULL) { + o->found_path= strdup(path); + if(o->found_path == NULL) + return(-1); + } else + o->found_path= NULL; + return(1); +} + + +int Findjob_get_found_path(struct FindjoB *o, char **path, int flag) +{ + *path= o->found_path; + return(1); +} + + +/* @flag bit0=recognize type "e" = El-Torito + @return 0=no match , 1=match , <0 = error +*/ +int Findjob_test(struct FindjoB *o, char *name, + struct stat *boss_stbuf, struct stat *stbuf, + int depth, int flag) +{ + int ret; + + if(o->name_expr!=NULL) { + ret= regexec(&(o->name_re),name,1,&(o->name_match),0); + if(ret!=0) + return(0); + } + + if(o->file_type!=0) { + if(S_ISBLK(stbuf->st_mode)) { + if(o->file_type!='b') + return(0); + } else if(S_ISCHR(stbuf->st_mode)) { + if(o->file_type!='c') + return(0); + } else if(S_ISDIR(stbuf->st_mode)) { + if(o->file_type=='m') { + if(boss_stbuf==NULL) + return(0); + if(boss_stbuf->st_dev == stbuf->st_dev) + return(0); + } else if(o->file_type!='d') + return(0); + } else if(S_ISFIFO(stbuf->st_mode)) { + if(o->file_type!='p') + return(0); + } else if(S_ISREG(stbuf->st_mode)) { + if(o->file_type!='f' && o->file_type!='-') + return(0); + } else if(((stbuf->st_mode)&S_IFMT)==S_IFLNK) { + if(o->file_type!='l') + return(0); + } else if(((stbuf->st_mode)&S_IFMT)==S_IFSOCK) { + if(o->file_type!='s') + return(0); + } else if((flag & 1) && ((stbuf->st_mode) & S_IFMT) == Xorriso_IFBOOT) { + if(o->file_type!='e') + return(0); + } else { + if(o->file_type!='X') + return(0); + } + } + + /* ??? >>> more tests to come ?*/; + + return(1); +} + + +int Findjob_get_action(struct FindjoB *o, int flag) +{ + return(o->action); +} + + +/* @return <0 error, >=0 see above struct FindjoB.action +*/ +int Findjob_get_action_parms(struct FindjoB *o, char **target, + uid_t *user, gid_t *group, + mode_t *mode_and, mode_t *mode_or, + int *type, time_t *date, struct FindjoB **subjob, + int flag) +{ + *target= o->target; + *user= o->user; + *group= o->group; + *mode_and= o->mode_and; + *mode_or= o->mode_or; + *type= o->type; + *date= o->date; + *subjob= o->subjob; + return(o->action); +} + + +int Findjob_set_action_target(struct FindjoB *o, int action, char *target, + int flag) +{ + o->action= action; + o->target= target; + return(1); +} + + +/* @param flag bit0= recursive +*/ +int Findjob_set_action_chown(struct FindjoB *o, uid_t user,int flag) +{ + int ret; + + if(flag&1) { + o->action= 0; + Findjob_destroy(&(o->subjob), 0); + ret= Findjob_new(&(o->subjob), "", 0); + if(ret<=0) + return(-1); + Findjob_set_action_chown(o->subjob, user, 0); + o->action= 9; + } else { + o->action= 4; + o->user= user; + } + return(1); +} + + +/* @param flag bit0= recursive +*/ +int Findjob_set_action_chgrp(struct FindjoB *o, gid_t group, int flag) +{ + int ret; + + if(flag&1) { + o->action= 0; + Findjob_destroy(&(o->subjob), 0); + ret= Findjob_new(&(o->subjob), "", 0); + if(ret<=0) + return(-1); + Findjob_set_action_chgrp(o->subjob, group, 0); + o->action= 10; + } else { + o->action= 5; + o->group= group; + } + return(1); +} + + +/* @param flag bit0= recursive +*/ +int Findjob_set_action_chmod(struct FindjoB *o, + mode_t mode_and, mode_t mode_or, int flag) +{ + int ret; + + if(flag&1) { + o->action= 0; + Findjob_destroy(&(o->subjob), 0); + ret= Findjob_new(&(o->subjob), "", 0); + if(ret<=0) + return(-1); + Findjob_set_action_chmod(o->subjob, mode_and, mode_or, 0); + o->action= 11; + } else { + o->action= 6; + o->mode_and= mode_and; + o->mode_or= mode_or; + } + return(1); +} + + +/* @param flag bit0= recursive +*/ +int Findjob_set_action_ad(struct FindjoB *o, int type, time_t date, int flag) +{ + int ret; + + if(flag&1) { + o->action= 0; + Findjob_destroy(&(o->subjob), 0); + ret= Findjob_new(&(o->subjob), "", 0); + if(ret<=0) + return(-1); + Findjob_set_action_ad(o->subjob, type, date, 0); + o->action= 12; + } else { + o->action= 7; + o->type= type; + o->date= date; + } + return(1); +} + + +int Findjob_set_action_subjob(struct FindjoB *o, int action, + struct FindjoB *subjob, int flag) +{ + o->action= action; + Findjob_destroy(&(o->subjob), 0); + o->subjob= subjob; + return(1); +} + + +int Findjob_set_action_found_path(struct FindjoB *o, int flag) +{ + o->action= 23; + Findjob_set_found_path(o, NULL, 0); + return(1); +} + + +/* ---------------------------- SplitparT ------------------------- */ + + +struct SplitparT { + char *name; + int partno; + int total_parts; + off_t offset; + off_t bytes; + off_t total_bytes; +}; + + +int Splitparts_new(struct SplitparT **o, int count, int flag) +{ + int i; + + (*o)= TSOB_FELD(struct SplitparT, count); + if((*o)==NULL) + return(-1); + for(i= 0; i<count; i++) { + (*o)[i].name= NULL; + (*o)[i].partno= 0; + (*o)[i].total_parts= 0; + (*o)[i].offset= 0; + (*o)[i].bytes= 0; + (*o)[i].total_bytes= 0; + } + return(1); +} + + +int Splitparts_destroy(struct SplitparT **o, int count, int flag) +{ + int i; + + if((*o)==NULL) + return(0); + for(i= 0; i<count; i++) { + if((*o)[i].name!=NULL) + free((*o)[i].name); + } + free(*o); + *o= NULL; + return(1); +} + + +int Splitparts_set(struct SplitparT *o, int idx, + char *name, int partno, int total_parts, + off_t offset, off_t bytes, off_t total_bytes, int flag) +{ + if(o[idx].name!=NULL) + free(o[idx].name); + o[idx].name= strdup(name); + if(o[idx].name==NULL) + return(-1); + o[idx].partno= partno; + o[idx].total_parts= total_parts; + o[idx].offset= offset; + o[idx].bytes= bytes; + o[idx].total_bytes= total_bytes; + return(1); +} + + +int Splitparts_get(struct SplitparT *o, int idx, char **name, int *partno, + int *total_parts, off_t *offset, off_t *bytes, + off_t *total_bytes, int flag) +{ + *name= o[idx].name; + *partno= o[idx].partno; + *total_parts= o[idx].total_parts; + *offset= o[idx].offset; + *bytes= o[idx].bytes; + *total_bytes= o[idx].total_bytes; + return(1); +} + + +int Splitpart__read_next_num(char *base_pt, char **next_pt, off_t *num, + int flag) +{ + char *cpt, *ept, scale[4]; + + *num= 0; + for(cpt= base_pt; *cpt!=0 && !isdigit(*cpt); cpt++); + if(*cpt==0) + return(0); + for(ept= cpt; *ept!=0 && isdigit(*ept); ept++) + *num= (*num)*10+(*ept)-'0'; + scale[0]= '1'; + scale[1]= *ept; + scale[2]= 0; + *num *= (off_t) Scanf_io_size(scale, 0); + if(*ept!=0) + ept++; + *next_pt= ept; + return(1); +} + + +int Splitpart__parse(char *name, int *partno, int *total_parts, + off_t *offset, off_t *bytes, off_t *total_bytes, int flag) + +{ + int ret; + off_t num; + char *cpt, *ept; + + cpt= name; + ret= Splitpart__read_next_num(cpt, &ept, &num, 0); + if(ret<=0) + return(ret); + *partno= num; + cpt= ept; + ret= Splitpart__read_next_num(cpt, &ept, &num, 0); + if(ret<=0) + return(ret); + *total_parts= num; + cpt= ept; + ret= Splitpart__read_next_num(cpt, &ept, offset, 0); + if(ret<=0) + return(ret); + cpt= ept; + ret= Splitpart__read_next_num(cpt, &ept, bytes, 0); + if(ret<=0) + return(ret); + cpt= ept; + ret= Splitpart__read_next_num(cpt, &ept, total_bytes, 0); + if(ret<=0) + return(ret); + return(1); +} + + +int Splitpart__compose(char *adr, int partno, int total_parts, + off_t offset, off_t bytes, off_t total_bytes, int flag) +{ + sprintf(adr, "part_%d_of_%d_at_", partno, total_parts); + if((offset % (1024*1024))==0 && offset>0) { + Sfile_off_t_text(adr+strlen(adr), offset / (1024*1024), 0); + strcat(adr, "m"); + } else + Sfile_off_t_text(adr+strlen(adr), offset, 0); + strcat(adr, "_with_"); + if((bytes % (1024*1024))==0) { + Sfile_off_t_text(adr+strlen(adr), bytes / (1024*1024), 0); + strcat(adr, "m"); + } else + Sfile_off_t_text(adr+strlen(adr), bytes, 0); + strcat(adr, "_of_"); + Sfile_off_t_text(adr+strlen(adr), total_bytes, 0); + return(1); +} + + +int Splitparts_cmp(const void *v1, const void *v2) +{ + struct SplitparT *p1, *p2; + + p1= (struct SplitparT *) v1; + p2= (struct SplitparT *) v2; + + if(p1->partno>p2->partno) + return(1); + if(p1->partno<p2->partno) + return(-1); + if(p1->offset>p2->offset) + return(1); + if(p1->offset<p2->offset) + return(-1); + return(0); +} + + +int Splitparts_sort(struct SplitparT *o, int count, int flag) +{ + qsort(o, (size_t) count, sizeof(struct SplitparT), Splitparts_cmp); + return(1); +} + + +/* ---------------------------- End SplitparT ------------------------- */ + +/* ------------------------------ ExclusionS ------------------------------ */ + +struct ExclusionS { + + /* Absolute input patterns which lead to not_paths */ + struct Xorriso_lsT *not_paths_descr; + + /* Actually banned absolute paths */ + struct Xorriso_lsT *not_paths; + + /* Input patterns which lead to not_leafs */ + struct Xorriso_lsT *not_leafs_descr; + + /* Compiled not_leaf patterns. Caution: not char[] but regex_t */ + struct Xorriso_lsT *not_leafs; + +}; + + +int Exclusions_new(struct ExclusionS **o, int flag) +{ + struct ExclusionS *m; + + m= *o= TSOB_FELD(struct ExclusionS, 1); + if(m==NULL) + return(-1); + m->not_paths_descr= NULL; + m->not_paths= NULL; + m->not_leafs_descr= NULL; + m->not_leafs= NULL; + return(1); +} + + +int Exclusions_destroy(struct ExclusionS **o, int flag) +{ + struct Xorriso_lsT *s,*next; + + if((*o)==NULL) + return(0); + Xorriso_lst_destroy_all(&((*o)->not_paths_descr), 0); + Xorriso_lst_destroy_all(&((*o)->not_paths), 0); + Xorriso_lst_destroy_all(&((*o)->not_leafs_descr), 0); + for(s= (*o)->not_leafs; s!=NULL; s= next){ + next= s->next; + regfree((regex_t *) s->text); + Xorriso_lst_destroy(&s, 0); + } + (*o)= NULL; + return(1); +} + + +int Exclusions_add_not_paths(struct ExclusionS *o, int descrc, char **descrs, + int pathc, char **paths, int flag) +{ + struct Xorriso_lsT *s, *new_s; + int i, ret; + + s= NULL; + if(o->not_paths_descr!=NULL) + for(s= o->not_paths_descr; s->next!=NULL; s= s->next); + for(i= 0; i<descrc; i++) { + ret= Xorriso_lst_new(&new_s, descrs[i], s, 0); + if(ret<=0) + return(ret); + if(o->not_paths_descr==NULL) + o->not_paths_descr= new_s; + s= new_s; + } + s= NULL; + if(o->not_paths!=NULL) + for(s= o->not_paths; s->next!=NULL; s= s->next); + for(i= 0; i<pathc; i++) { + ret= Xorriso_lst_new(&new_s, paths[i], s, 0); + if(ret<=0) + return(ret); + if(o->not_paths==NULL) + o->not_paths= new_s; + s= new_s; + } + return(1); +} + + +/* @return -1=cannot store , 0=cannot compile regex , 1=ok +*/ +int Exclusions_add_not_leafs(struct ExclusionS *o, char *not_leafs_descr, + regex_t *re, int flag) +{ + int ret; + + ret= Xorriso_lst_append_binary(&(o->not_leafs_descr), + not_leafs_descr, strlen(not_leafs_descr)+1, 0); + if(ret<=0) + return(-1); + ret= Xorriso_lst_append_binary(&(o->not_leafs), (char *) re, sizeof(regex_t), 0); + if(ret<=0) + return(-1); + return(1); +} + + +/* @param flag bit0= whole subtree is banned with -not_paths + @return 0=no match , 1=not_paths , 2=not_leafs, <0=error +*/ +int Exclusions_match(struct ExclusionS *o, char *abs_path, int flag) +{ + struct Xorriso_lsT *s; + char leaf[SfileadrL], *leaf_pt; + regmatch_t match[1]; + int ret, was_non_slash, l; + + /* test abs_paths */ + if(flag&1) { + for(s= o->not_paths; s!=NULL; s= s->next) { + l= strlen(s->text); + if(strncmp(abs_path, s->text, l)==0) + if(abs_path[l]=='/' || abs_path[l]==0) + return(1); + } + } else { + for(s= o->not_paths; s!=NULL; s= s->next) + if(strcmp(abs_path, s->text)==0) + return(1); + } + + /* determine leafname */ + was_non_slash= 0; + for(leaf_pt= abs_path+strlen(abs_path); leaf_pt>abs_path; leaf_pt--) { + if(*leaf_pt=='/') { + if(was_non_slash) { + leaf_pt++; + break; + } + } else if(*leaf_pt!=0) + was_non_slash= 1; + } + if(strlen(leaf_pt)>=SfileadrL) + return(-1); + strcpy(leaf, leaf_pt); + leaf_pt= strchr(leaf, '/'); + if(leaf_pt!=NULL) + *leaf_pt= 0; + + /* test with leaf expressions */ + for(s= o->not_leafs; s!=NULL; s= s->next) { + ret= regexec((regex_t *) s->text, leaf, 1, match, 0); + if(ret==0) + return(2); + } + return(0); +} + + +int Exclusions_get_descrs(struct ExclusionS *o, + struct Xorriso_lsT **not_paths_descr, + struct Xorriso_lsT **not_leafs_descr, int flag) +{ + *not_paths_descr= o->not_paths_descr; + *not_leafs_descr= o->not_leafs_descr; + return(1); +} + + +/* ---------------------------- End ExclusionS ---------------------------- */ + +/* ------------------------------ PermstacK ------------------------------- */ + + +struct PermiteM { + char *disk_path; + struct stat stbuf; + struct PermiteM *next; +}; + + +int Permstack_push(struct PermiteM **o, char *disk_path, struct stat *stbuf, + int flag) +{ + struct PermiteM *m; + + m= TSOB_FELD(struct PermiteM,1); + if(m==NULL) + return(-1); + m->disk_path= NULL; + memcpy(&(m->stbuf), stbuf, sizeof(struct stat)); + m->next= *o; + + m->disk_path= strdup(disk_path); + if(m->disk_path==NULL) + goto failed; + + *o= m; + return(1); +failed:; + if(m->disk_path!=NULL) + free(m->disk_path); + free((char *) m); + return(-1); +} + + +/* @param flag bit0= minimal transfer: access permissions only + bit1= do not set timestamps +*/ +int Permstack_pop(struct PermiteM **o, struct PermiteM *stopper, + struct XorrisO *xorriso, int flag) +{ + int ret; + char sfe[5*SfileadrL]; + struct utimbuf utime_buffer; + struct PermiteM *m, *m_next; + + if((*o)==stopper) + return(1); + for(m= *o; m!=NULL; m= m->next) + if(m->next==stopper) + break; + if(m==NULL) { + sprintf(xorriso->info_text, + "Program error: Permstack_pop() : cannot find stopper"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(-1); + } + + for(m= *o; m!=stopper; m= m_next) { + ret= chmod(m->disk_path, m->stbuf.st_mode); + if(ret==-1) { + if(xorriso!=NULL) { + sprintf(xorriso->info_text, + "Cannot change access permissions of disk directory: chmod %o %s", + m->stbuf.st_mode & 07777, Text_shellsafe(m->disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", + 0); + } + } + if(!(flag&1)) { + chown(m->disk_path, m->stbuf.st_uid, m->stbuf.st_gid); + /* don't complain if it fails */ + if(!(flag&2)) { + utime_buffer.actime= m->stbuf.st_atime; + utime_buffer.modtime= m->stbuf.st_mtime; + ret= utime(m->disk_path,&utime_buffer); + if(ret==-1 && xorriso!=NULL) { + sprintf(xorriso->info_text, + "Cannot change timestamps of disk directory: %s", + Text_shellsafe(m->disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", + 0); + } + } + } + m_next= m->next; + free(m->disk_path); + free((char *) m); + *o= m_next; + } + return(1); +} + + +/* ---------------------------- End PermstacK ----------------------------- */ + +/* ------------------------------ SpotlisT -------------------------------- */ + +struct SpotlistiteM { + int start_lba; + int blocks; + int quality; + struct SpotlistiteM *next; +}; + + +int Spotlistitem_new(struct SpotlistiteM **o, int start_lba, int blocks, + int quality, int flag) +{ + struct SpotlistiteM *m; + + m= TSOB_FELD(struct SpotlistiteM,1); + if(m==NULL) + return(-1); + *o= m; + m->start_lba= start_lba; + m->blocks= blocks; + m->quality= quality; + m->next= NULL; + return(1); +} + + +int Spotlistitem_destroy(struct SpotlistiteM **o, int flag) +{ + if((*o) == NULL) + return(0); + free((char *) *o); + *o= NULL; + return(1); +} + + +struct SpotlisT { + struct SpotlistiteM *list_start; + struct SpotlistiteM *list_end; + int list_count; + struct SpotlistiteM *current_item; + int current_idx; +}; + + +int Spotlist_new(struct SpotlisT **o, int flag) +{ + struct SpotlisT *m; + + m= TSOB_FELD(struct SpotlisT,1); + if(m==NULL) + return(-1); + *o= m; + m->list_start= NULL; + m->list_end= NULL; + m->list_count= 0; + m->current_item= NULL; + m->current_idx= -1; + return(1); +} + + +int Spotlist_destroy(struct SpotlisT **o, int flag) +{ + struct SpotlisT *m; + struct SpotlistiteM *li, *next_li; + + if((*o) == NULL) + return(0); + m= *o; + for(li= m->list_start; li != NULL; li= next_li) { + next_li= li->next; + Spotlistitem_destroy(&li, 0); + } + free((char *) *o); + *o= NULL; + return(1); +} + + +int Spotlist_add_item(struct SpotlisT *o, int start_lba, int blocks, + int quality, int flag) +{ + int ret; + struct SpotlistiteM *li; + static int debug_verbous= 0; + + ret= Spotlistitem_new(&li, start_lba, blocks, quality, 0); + if(ret <= 0) + return(ret); + if(o->list_end != NULL) + o->list_end->next= li; + o->list_end= li; + if(o->list_start == NULL) + o->list_start= li; + (o->list_count)++; + + if(debug_verbous) {char quality_name[80]; + fprintf(stderr, "debug: lba %10d , size %10d , quality %s\n", + start_lba, blocks, Spotlist__quality_name(quality, quality_name, 0)); + } + + return(1); +} + + +int Spotlist_count(struct SpotlisT *o, int flag) +{ + return o->list_count; +} + + +int Spotlist_block_count(struct SpotlisT *o, int flag) +{ + int list_blocks= 0; + struct SpotlistiteM *li; + + for(li= o->list_start; li != NULL; li= li->next) { + if(li->start_lba + li->blocks > list_blocks) + list_blocks= li->start_lba + li->blocks; + } + return(list_blocks); +} + + +int Spotlist_sector_size(struct SpotlisT *o, int read_chunk, int flag) +{ + int sector_size; + struct SpotlistiteM *li; + + sector_size= read_chunk * 2048; + for(li= o->list_start; li != NULL; li= li->next) { + if((li->start_lba % read_chunk) || (li->blocks % read_chunk)) { + sector_size= 2048; + break; + } + } + return(sector_size); +} + + +int Spotlist_get_item(struct SpotlisT *o, int idx, + int *start_lba, int *blocks, int *quality, int flag) +{ + int i; + struct SpotlistiteM *li; + + if(idx < 0 || idx > o->list_count) + return(0); + if(idx == o->current_idx) + li= o->current_item; + else if(idx == o->current_idx) { + li= o->current_item->next; + } else { + li= o->list_start; + for(i= 0; i < idx; i++) + li= li->next; + } + o->current_item= li; + o->current_idx= idx; + *start_lba= li->start_lba; + *blocks= li->blocks; + *quality= li->quality; + return(1); +} + + +char *Spotlist__quality_name(int quality, char name[80], int flag) +{ + if(quality == Xorriso_read_quality_gooD) + strcpy(name, "+ good"); + else if(quality == Xorriso_read_quality_sloW) + strcpy(name, "+ slow"); + else if(quality == Xorriso_read_quality_partiaL) + strcpy(name, "+ partial"); + else if(quality == Xorriso_read_quality_valiD) + strcpy(name, "+ valid"); + else if(quality == Xorriso_read_quality_untesteD) + strcpy(name, "0 untested"); + else if(quality == Xorriso_read_quality_invaliD) + strcpy(name, "- invalid"); + else if(quality == Xorriso_read_quality_tao_enD) + strcpy(name, "- tao end"); + else if(quality == Xorriso_read_quality_off_tracK) + strcpy(name, "- off track"); + else if(quality == Xorriso_read_quality_unreadablE) + strcpy(name, "- unreadable"); + else + sprintf(name, "0x%8.8X", (unsigned) quality); + return(name); +} + + +/* ---------------------------- End SpotlisT ------------------------------ */ + +/* ---------------------------- SectorbitmaP ------------------------------ */ + +struct SectorbitmaP { + int sectors; + int sector_size; + unsigned char *map; + int map_size; +}; + + +int Sectorbitmap_new(struct SectorbitmaP **o, int sectors, int sector_size, + int flag) +{ + struct SectorbitmaP *m; + + m= TSOB_FELD(struct SectorbitmaP,1); + if(m==NULL) + return(-1); + *o= m; + m->sectors= sectors; + m->sector_size= sector_size; + m->map= NULL; + m->map_size= sectors / 8 + 1; + + m->map= calloc(m->map_size, 1); + if(m->map == NULL) + goto failure; + return(1); +failure:; + Sectorbitmap_destroy(o, 0); + return(-1); +} + + +int Sectorbitmap_destroy(struct SectorbitmaP **o, int flag) +{ + if((*o) == NULL) + return(0); + if((*o)->map != NULL) + free((char *) (*o)->map); + free((char *) *o); + *o= NULL; + return(1); +} + + +int Sectorbitmap_from_file(struct SectorbitmaP **o, char *path, char *msg, + int *os_errno, int flag) +{ + int ret, fd= -1, sectors, sector_size, i, todo, map_size, skip; + unsigned char *map; + unsigned char buf[1024]; + + *os_errno= 0; + if(msg != NULL) + msg[0]= 0; + fd= open(path, O_RDONLY); + if(fd == -1) { + *os_errno= errno; + if(msg != NULL) { + strcpy(msg, "Cannot open path "); + Text_shellsafe(path, msg+strlen(msg), 0); + } + return(0); + } + ret= read(fd, buf, 32); + if(ret < 32) { +wrong_filetype:; + if(ret == -1) + *os_errno= errno; + if(msg != NULL) { + strcpy(msg, "Not a sector bitmap file: "); + Text_shellsafe(path, msg+strlen(msg), 0); + } + ret= 0; goto ex; + } + if(strncmp((char *) buf, "xorriso sector bitmap v1 ", 32) == 0) + /* ok */; + else if(strncmp((char *) buf, "xorriso sector bitmap v2 ", 25) == 0) { + skip= -1; + sscanf(((char *) buf) + 25, "%d", &skip); + if(skip < 0) + {ret= 0; goto wrong_filetype;} + for(i= 0; i < skip; i+= sizeof(buf)) { + todo= sizeof(buf); + if(i + todo > skip) + todo= skip - i; + ret= read(fd, buf, todo); + if(ret < todo) + goto wrong_filetype; + } + } else + {ret= 0; goto wrong_filetype;} + ret= read(fd, buf, 8); + if(ret < 4) + goto wrong_filetype; + sectors= (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + sector_size= (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]; + if(sectors <= 0 || sector_size <= 0) + goto wrong_filetype; + ret= Sectorbitmap_new(o, sectors, sector_size, 0); + if(ret <= 0) { + if(msg != NULL) + sprintf(msg, "Cannot allocate bitmap memory for %d sectors", sectors); + ret= -1; goto ex; + } + map= (*o)->map; + map_size= (*o)->map_size; + for(i= 0; i < map_size; i+= sizeof(buf)) { + todo= sizeof(buf); + if(i + todo > map_size) + todo= map_size - i; + ret= read(fd, buf, todo); + if(ret != todo) + goto wrong_filetype; + memcpy(map + i, buf, todo); + } + ret= 1; +ex:; + if(fd != -1) + close(fd); + if(ret <= 0) + Sectorbitmap_destroy(o, 0); + return(ret); +} + + +int Sectorbitmap_to_file(struct SectorbitmaP *o, char *path, char *info, + char *msg, int *os_errno, int flag) +{ + int ret, fd= -1, j, l; + unsigned char buf[40]; + + *os_errno= 0; + fd= open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + if(fd == -1) { + *os_errno= errno; + if(msg != NULL) { + strcpy(msg, "Cannot open path "); + Text_shellsafe(path, msg+strlen(msg), 0); + } + return(0); + } + + l= 0; + if(info != NULL) + l= strlen(info); + if(l > 999999) { + strcpy(msg, "Info string is longer than 999999 bytes"); + return(0); + } + sprintf((char *) buf, "xorriso sector bitmap v2 %-6d\n", l); + + ret= write(fd, buf, 32); + if(ret != 32) { +cannot_write:; + *os_errno= errno; + if(msg != NULL) { + strcpy(msg, "Cannot write to "); + Text_shellsafe(path, msg+strlen(msg), 0); + } + ret= 0; goto ex; + } + if(l > 0) { + ret= write(fd, info, l); + if(ret != l) + goto cannot_write; + } + + for(j= 0; j < 4; j++) { + buf[j]= o->sectors >> (24 - j * 8); + buf[j+4]= o->sector_size >> (24 - j * 8); + } + ret= write(fd, buf, 8); + if(ret != 8) + goto cannot_write; + ret= write(fd, o->map, o->map_size); + if(ret != o->map_size) + goto cannot_write; + + ret= 1; +ex:; + if(fd != -1) + close(fd); + return(ret); +} + + +/* @param flag bit0= sector bit value +*/ +int Sectorbitmap_set(struct SectorbitmaP *o, int sector, int flag) +{ + if(sector < 0 || sector >= o->sectors) + return(0); + if(flag & 1) + o->map[sector / 8]|= 1 << (sector % 8); + else + o->map[sector / 8]&= ~(1 << (sector % 8)); + return(1); +} + + +/* @param flag bit0= sector bit value +*/ +int Sectorbitmap_set_range(struct SectorbitmaP *o, + int start_sector, int sectors, int flag) +{ + int start_i, end_i, i; + unsigned char value; + + if(start_sector < 0 || start_sector + sectors > o->sectors || sectors < 1) + return(0); + if(flag & 1) + value= ~0; + else + value= 0; + start_i= start_sector / 8; + end_i= (start_sector + sectors - 1) / 8; + for(i= start_sector; i / 8 == start_i && i < start_sector + sectors; i++) + Sectorbitmap_set(o, i, flag & 1); + for(i= start_i + 1; i < end_i; i++) + o->map[i]= value; + if(end_i > start_i) + for(i= end_i * 8; i < start_sector + sectors; i++) + Sectorbitmap_set(o, i, flag & 1); + return(1); +} + + +int Sectorbitmap_is_set(struct SectorbitmaP *o, int sector, int flag) +{ + if(sector < 0 || sector >= o->sectors) + return(0); + return(!! (o->map[sector / 8] & (1 << (sector % 8)))); +} + + +int Sectorbitmap_bytes_are_set(struct SectorbitmaP *o, + off_t start_byte, off_t end_byte, int flag) +{ + int end_sector, i; + + end_sector= end_byte / o->sector_size; + for(i= start_byte / o->sector_size; i <= end_sector; i++) + if(!Sectorbitmap_is_set(o, i, 0)) + return(0); + return(1); +} + + +int Sectorbitmap_get_layout(struct SectorbitmaP *o, + int *sectors, int *sector_size, int flag) +{ + *sectors= o->sectors; + *sector_size= o->sector_size; + return(1); +} + + +int Sectorbitmap_copy(struct SectorbitmaP *from, struct SectorbitmaP *to, + int flag) +{ + int i, run_start, run_value, start_sec, limit_sec, start_aligned; + int end_complete; + + if(((off_t) from->sectors) * ((off_t) from->sector_size) > + ((off_t) to->sectors) * ((off_t) to->sector_size)) + return(-1); + if(from->sector_size == to->sector_size) { + for(i= 0; i < from->map_size; i++) + to->map[i]= from->map[i]; + return(1); + } + run_start= 0; + run_value= Sectorbitmap_is_set(from, 0, 0); + for(i= 1; i <= from->sectors; i++) { + if(i < from->sectors) + if(Sectorbitmap_is_set(from, i, 0) == run_value) + continue; + start_sec= run_start * from->sector_size / to->sector_size; + start_aligned= + (start_sec * to->sector_size == run_start * from->sector_size); + limit_sec= i * from->sector_size / to->sector_size; + end_complete= (limit_sec * to->sector_size == i * from->sector_size); + if(run_value) { + if(!start_aligned) + start_sec++; + } else { + if(!end_complete) + limit_sec++; + } + if(start_sec < limit_sec) + Sectorbitmap_set_range(to, start_sec, limit_sec - 1 - start_sec, + !!run_value); + run_value= !run_value; + run_start= i; + } + return(1); +} + + +int Sectorbitmap_clone(struct SectorbitmaP *from, struct SectorbitmaP **clone, + int flag) +{ + int ret; + + ret= Sectorbitmap_new(clone, from->sectors, from->sector_size, 0); + if(ret <= 0) + return(ret); + ret= Sectorbitmap_copy(from, *clone, 0); + if(ret <= 0) + Sectorbitmap_destroy(clone, 0); + return(ret); +} + + +/* -------------------------- End SectorbitmaP ---------------------------- */ + +/* ---------------------------- CheckmediajoB ----------------------------- */ + +int Checkmediajob_new(struct CheckmediajoB **o, int flag) +{ + struct CheckmediajoB *m; + + m= TSOB_FELD(struct CheckmediajoB,1); + if(m==NULL) + return(-1); + *o= m; + m->use_dev= 0; + m->min_lba= -1; + m->max_lba= -1; + m->min_block_size= 16; + m->mode= 0; + m->start_time= time(NULL); + m->time_limit= 28800; + m->item_limit= 100000; + strcpy(m->abort_file_path, "/var/opt/xorriso/do_abort_check_media"); + m->data_to_path[0]= 0; + m->data_to_fd= -1; + m->data_to_offset= 0; + m->data_to_limit= -1; + m->patch_lba0= 0; + m->patch_lba0_msc1= -1; + m->sector_map_path[0]= 0; + m->sector_map= NULL; + m->map_with_volid= 0; + m->retry= 0; + m->report_mode= 0; + return(1); +} + + +int Checkmediajob_destroy(struct CheckmediajoB **o, int flag) +{ + if((*o) == NULL) + return(0); + if((*o)->data_to_fd != -1) + close((*o)->data_to_fd); + Sectorbitmap_destroy(&((*o)->sector_map), 0); + free((char *) *o); + *o= NULL; + return(1); +} + + +int Checkmediajob_copy(struct CheckmediajoB *from, struct CheckmediajoB *to, + int flag) +{ + to->use_dev= from->use_dev; + to->min_lba= from->min_lba; + to->max_lba= from->max_lba; + to->min_block_size= from->min_block_size; + to->mode= from->mode; + to->time_limit= from->time_limit; + to->item_limit= from->item_limit; + strcpy(to->abort_file_path, from->abort_file_path); + strcpy(to->data_to_path, from->data_to_path); + /* not copied: data_to_fd */ + to->data_to_offset= from->data_to_offset; + to->data_to_limit= from->data_to_limit; + to->patch_lba0= from->patch_lba0; + to->patch_lba0_msc1= from->patch_lba0_msc1; + strcpy(to->sector_map_path, from->sector_map_path); + /* not copied: sector_map */ + to->map_with_volid= from->map_with_volid; + to->retry= from->retry; + to->report_mode= from->report_mode; + return(1); +} + + +/* -------------------------- End CheckmediajoB --------------------------- */ + +/* ------------------------------- Xorriso -------------------------------- */ + + +/** The list of startup file names */ +#define Xorriso_rc_nuM 4 + +static char Xorriso_sys_rc_nameS[Xorriso_rc_nuM][80]= { + "/etc/default/xorriso", + "/etc/opt/xorriso/rc", + "/etc/xorriso/xorriso.conf", + "placeholder for $HOME/.xorrisorc" +}; + + +int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag) +{ + int i, ret; + struct XorrisO *m; + char leafname[SfileadrL]; + + *xorriso= m= TSOB_FELD(struct XorrisO,1); + if(m==NULL) + return(-1); + m->libs_are_started= 0; + strncpy(m->progname,progname,sizeof(m->progname)-1); + m->progname[sizeof(m->progname)-1]= 0; + if(getcwd(m->initial_wdx,sizeof(m->initial_wdx)-1)==NULL) + m->initial_wdx[0]= 0; + m->no_rc= 0; + m->argument_emulation= 0; + + m->rc_filename_count= Xorriso_rc_nuM; + for(i=0;i<m->rc_filename_count-1;i++) + strcpy(m->rc_filenames[i],Xorriso_sys_rc_nameS[i]); + m->rc_filenames[m->rc_filename_count-1][0]= 0; + + m->wdi[0]= 0; + strcpy(m->wdx, m->initial_wdx); + m->did_something_useful= 0; + m->add_plainly= 0; + m->split_size= 0; + strcpy(m->list_delimiter, "--"); + m->do_joliet= 0; + m->relax_compliance= 0; + m->do_follow_pattern= 1; + m->do_follow_param= 0; + m->do_follow_links= 0; + m->follow_link_limit= 100; + m->do_follow_mount= 1; + m->do_global_uid= 0; + m->global_uid= 0; + strcpy(m->volid, "ISOIMAGE"); + m->volid_default= 1; + m->loaded_volid[0]= 0; + m->assert_volid[0]= 0; + m->assert_volid_sev[0]= 0; + m->publisher[0]= 0; + m->application_id[0]= 0; + m->session_logfile[0]= 0; + m->session_lba= -1; + m->session_blocks= 0; + m->do_global_gid= 0; + m->global_gid= 0; + m->do_global_mode= 0; + m->global_dir_mode= 0555; + m->global_file_mode= 0444; + m->do_overwrite= 2; + m->do_reassure= 0; + m->drive_blacklist= NULL; + m->drive_greylist= NULL; + m->drive_whitelist= NULL; + m->toc_emulation_flag= 0; + m->image_start_mode= 0; + m->image_start_value[0]= 0; + m->indev[0]= 0; + m->in_drive_handle= NULL; + m->in_volset_handle= NULL; + m->in_charset= NULL; + m->volset_change_pending= 0; + m->no_volset_present= 0; + m->in_sector_map= NULL; + m->check_media_default= NULL; + m->outdev[0]= 0; + m->out_drive_handle= NULL; + m->out_charset= NULL; + m->dev_fd_1= -1; + m->grow_blindly_msc2= -1; + m->ban_stdio_write= 0; + m->do_dummy= 0; + m->do_close= 0; + m->speed= 0; + m->fs= 4*512; /* 4 MiB */ + m->padding= 300*1024; + m->alignment= 0; + m->do_stream_recording= 0; + m->keep_boot_image= 0; + m->patch_isolinux_image= 0; + m->boot_image_bin_path[0]= 0; + m->boot_image_emul= 0; + m->boot_image_cat_path[0]= 0; + m->boot_image_load_size= 4 * 512; /* hearsay out of libisofs/demo/iso.c */ + m->boot_image_isohybrid= 1; + m->loaded_boot_bin_lba= 0; + m->loaded_boot_cat_path[0]= 0; + m->allow_graft_points= 0; + m->allow_restore= 0; + m->do_concat_split= 1; + m->do_auto_chmod= 0; + m->dialog= 0; + m->bsl_interpretation= 0; + m->search_mode= 0; + m->structured_search= 1; + m->do_iso_rr_pattern= 1; + m->do_disk_pattern= 2; + m->temp_mem_limit= 16*1024*1024; + m->file_size_limit= Xorriso_default_file_size_limiT; + m->disk_exclusions= NULL; + m->disk_excl_mode= 1; + m->use_stdin= 0; + m->result_page_length= 0; + m->result_page_width= 80; + m->mark_text[0]= 0; + m->packet_output= 0; + for(i=0; i<4; i++) { + m->logfile[i][0]= 0; + m->logfile_fp[i]= NULL; + } + m->pktlog_fp= NULL; + for(i= 0; i < Xorriso_max_outlist_stacK; i++) { + m->result_msglists[i]= NULL; + m->info_msglists[i]= NULL; + m->msglist_flags[i]= 0; + } + m->msglist_stackfill= 0; + m->status_history_max= Xorriso_status_history_maX; + strcpy(m->report_about_text, "UPDATE"); + Xorriso__text_to_sev(m->report_about_text, &m->report_about_severity, 0); + m->library_msg_direct_print= 0; + strcpy(m->abort_on_text,"FATAL"); + Xorriso__text_to_sev(m->abort_on_text, &m->abort_on_severity, 0); + m->problem_status= 0; + m->problem_status_text[0]= 0; + m->errfile_log[0]= 0; + m->errfile_fp= NULL; + m->img_read_error_mode= 2; /* abort faulty image reading with FATAL */ + m->extract_error_mode= 1; /* keep extracted files after read error */ + strcpy(m->return_with_text, "SORRY"); + Xorriso__text_to_sev(m->return_with_text, &m->return_with_severity, 0); + m->return_with_value= 32; + m->eternal_problem_status= 0; + m->eternal_problem_status_text[0]= 0; + m->re= NULL; + /* >>> ??? how to initialize m->match[0] ? */ + m->re_constants= NULL; + m->re_count= 0; + m->re_fill= 0; + m->reg_expr[0]= 0; + m->run_state= 0; + m->is_dialog= 0; + m->bar_is_fresh= 0; + m->pending_option[0]= 0; + m->request_to_abort= 0; + m->request_not_to_ask= 0; + m->idle_time= 0.0; + m->re_failed_at= -1; + m->prepended_wd= 0; + m->insert_count= 0; + m->insert_bytes= 0; + m->error_count= 0; + m->pacifier_style= 0; + m->pacifier_interval= 1.0; + m->pacifier_count= 0; + m->pacifier_total= 0; + m->pacifier_byte_count= 0; + m->pacifier_fifo= NULL; + m->start_time= 0.0; + m->last_update_time= 0.0; + m->find_compare_result= 1; + m->perm_stack= NULL; + m->result_line[0]= 0; + m->result_line_counter= 0; + m->result_page_counter= 0; + m->result_open_line_len= 0; + m->info_text[0]= 0; + + ret= Sfile_leafname(progname, leafname, 0); + if(ret<=0) + goto failure; + if(strcmp(leafname, "osirrox")==0) + m->allow_restore= 1; + else if(strcmp(leafname, "xorrisofs")==0 || strcmp(leafname, "genisofs")==0 || + strcmp(leafname, "mkisofs")==0 || strcmp(leafname, "genisoimage")==0) { + m->argument_emulation= 1; + m->pacifier_style= 1; + Xorriso_protect_stdout(*xorriso, 0); + } else if(strcmp(leafname, "xorrecord")==0 || strcmp(leafname, "wodim")==0 || + strcmp(leafname, "cdrecord")==0 || strcmp(leafname, "cdrskin")==0) { + m->argument_emulation= 2; + m->pacifier_style= 2; + } + ret= Exclusions_new(&(m->disk_exclusions), 0); + if(ret<=0) + goto failure; + Xorriso_relax_compliance(m, "default", 0); + ret= Xorriso_lst_new(&(m->drive_greylist), "/dev", m->drive_greylist, 1); + if(ret <= 0) + goto failure; + + return(1); +failure:; + Xorriso_destroy(xorriso, 0); + return(-1); +} + + +int Xorriso_destroy_re(struct XorrisO *m, int flag) +{ + int i; + + if(m->re!=NULL) { + for(i=0;i<m->re_fill;i++) { + if(m->re_constants!=NULL) + if(m->re_constants[i]!=NULL) + continue; /* ,->re[i] was never subject to regcomp() */ + regfree(&(m->re[i])); + } + free((char *) m->re); + m->re= NULL; + } + + if(m->re_constants!=NULL) { + for(i=0;i<m->re_fill;i++) + if(m->re_constants[i]!=NULL) + free(m->re_constants[i]); + free((char *) m->re_constants); + m->re_constants= NULL; + } + m->re_count= 0; + m->re_fill= 0; + return(1); +} + + +/* @param flag bit0= global shutdown of libraries */ +int Xorriso_destroy(struct XorrisO **xorriso, int flag) +{ + struct XorrisO *m; + + m= *xorriso; + if(m==NULL) + return(0); + if(m->in_charset!=NULL) + free(m->in_charset); + if(m->out_charset!=NULL) + free(m->out_charset); + Xorriso_destroy_re(m,0); + Exclusions_destroy(&(m->disk_exclusions), 0); + Xorriso_lst_destroy_all(&(m->drive_blacklist), 0); + Xorriso_lst_destroy_all(&(m->drive_greylist), 0); + Xorriso_lst_destroy_all(&(m->drive_whitelist), 0); + Xorriso_detach_libraries(m, flag&1); + + free((char *) m); + *xorriso= NULL; + return(1); +} + + +int Xorriso_dialog_input(struct XorrisO *xorriso, char line[], int linesize, + int flag) +/* + bit0= do not write to history + bit1= do not read input (but eventually write to history) + bit2= do not write to history line which begin with "-history:" or "-history " +*/ +{ + char *cpt= NULL, **argv= NULL, *linept, *why_append= ""; + int ret, argc= 0, base_length= 0, l, append_line; +#ifdef Xorriso_with_readlinE + static char last_input[SfileadrL]= {""}; +#endif /* ! Xorriso_with_readlinE */ + double tdiff; + struct timeval tv; + struct timezone tz; + + gettimeofday(&tv,&tz); + tdiff= tv.tv_sec+(1.e-6*(double) tv.tv_usec); + + fflush(stdout); + linept= line; + +get_single:; +#ifdef Xorriso_with_readlinE + + if(xorriso->use_stdin || xorriso->dev_fd_1>=0) { + if(flag&2) + {ret= 1; goto ex;} + if(Sfile_fgets_n(linept,linesize - base_length - 1, stdin, + (xorriso->dialog == 2)) == NULL) { + /* need a very dramatic end */ + kill(getpid(),SIGHUP); + {ret= -1; goto ex;} + } + goto process_single; + } + if(flag&2) { + cpt= NULL; + } else { + cpt= readline(""); + if(cpt==NULL) { + /* need a very dramatic end */ + kill(getpid(),SIGHUP); + {ret= -1; goto ex;} + } + l= strlen(cpt); + if(l >= linesize - base_length - 1) { + strncpy(linept, cpt, linesize - 1); + line[sizeof(line)-1]= 0; + sprintf(xorriso->info_text,"Input line too long !"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + goto new_empty; + } else + strcpy(linept, cpt); + } + +process_single:; + +#else /* Xorriso_with_readlinE */ + + if(flag&2) + {ret= 1; goto ex;} + if(Sfile_fgets_n(linept, linesize - base_length - 1, stdin, + (xorriso->dialog == 2)) == NULL) { + /* need a very dramatic end */ + kill(getpid(),SIGHUP); + {ret= -1; goto ex;} + } + +#endif /* ! Xorriso_with_readlinE */ + + if(xorriso->dialog == 2) { + append_line= 0; + if(linept != line && strcmp(linept, "@@@") == 0) { + sprintf(xorriso->info_text, "Incomplete input line cleared by %s", + linept); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE",0); +new_empty:; + line[0]= 0; + linept= line; + sprintf(xorriso->info_text, "-------------------------------------\n"); + Xorriso_info(xorriso,0); + sprintf(xorriso->info_text, "Enter new text for empty input line :\n"); + Xorriso_info(xorriso,0); + goto get_single; + } + l= strlen(line); + ret= Sfile_make_argv("", line, &argc, &argv, 16); + if(ret < 0) + goto ex; + if(ret == 0 && !append_line) { + /* append a newline character */ + if(l >= linesize - 1) { + sprintf(xorriso->info_text,"Input line too long !"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + goto new_empty; + } + line[l]= '\n'; + line[l + 1]= 0; + append_line= 1; + why_append= "Quoted newline char"; + } + if(l > 0 && !append_line) + if(line[l - 1] == '\\') { + line[l - 1]= 0; + append_line= 1; + why_append= "Trailing backslash "; + } + if(append_line) { + base_length= strlen(line); + linept= line + base_length; + sprintf(xorriso->info_text, + "---------------------------------------------------------------\n"); + Xorriso_info(xorriso,0); + sprintf(xorriso->info_text, + "%s : Enter rest of line (or @@@ to clear it) :\n", why_append); + Xorriso_info(xorriso,0); + goto get_single; + } + } + +#ifdef Xorriso_with_readlinE + + if(line[0]!=0 && strcmp(last_input,line)!=0 && !(flag&1)) + if(!((flag&4) && + (strncmp(line,"-history:",9)==0 || strncmp(line,"-history ",9)==0))) { + add_history(line); + strncpy(last_input,line,sizeof(last_input)-1); + last_input[sizeof(last_input)-1]= 0; + } + +#endif /* ! Xorriso_with_readlinE */ + + ret= 1; +ex:; + if(cpt!=NULL) + free(cpt); + gettimeofday(&tv,&tz); + xorriso->idle_time+= tv.tv_sec+(1.e-6*(double) tv.tv_usec)-tdiff; + return(ret); +} + + +int Xorriso_request_confirmation(struct XorrisO *xorriso, int flag) +/* + bit0= important operation going on: + demand confirmation of abort, only abort on @@@ + bit1= mark '@' and '@@' by return 4 + bit2= accept: i|n= ignore | do not remove , r|y= retry | remove , q|x= abort + bit3= @@@ = 'done reading' rather than 'abort' + bit4= in non-dialog mode return 6 rather than 1 +*/ +/* return: <=0 error + 1= go on | do not remove existing file + 2= abort + 3= redo request for confirmation + 4= see flag bit1 + (5= skip volume) + 6= retry failed operation | remove existing file + */ +{ + int ret; + char line[SfileadrL],*cpt,previous_line[SfileadrL]; + char *abort_req_text,*abort_really_text; + + if(!xorriso->dialog) { + if(flag&16) + return(6); + return(1); + } + if(flag&8) { + abort_req_text= "request to end"; + abort_really_text= "done reading"; + } else { + abort_req_text= "request to abort"; + abort_really_text= "abort this command"; + } + ret= Xorriso_dialog_input(xorriso,line,sizeof(line),1); + xorriso->result_line_counter= 0; + xorriso->result_page_counter++; + if(ret<=0) + if(xorriso->result_page_length>0) + xorriso->result_page_length= -xorriso->result_page_length; + + cpt= line; + if(strcmp(cpt,"@@@")==0 || + strcmp(cpt,"x")==0 || strcmp(cpt,"X")==0 || + strcmp(cpt,"q")==0 || strcmp(cpt,"Q")==0) { + if(flag&1) { + strcpy(previous_line,cpt); + sprintf(xorriso->info_text, + "... [%s = %s registered. Really %s ? (y/n) ] ...\n", + cpt,abort_req_text,abort_really_text); + Xorriso_info(xorriso,0); + ret= Xorriso_dialog_input(xorriso,line,sizeof(line),1); + if(ret<=0) + return(ret); + cpt= line; + if(strcmp(cpt,previous_line)==0 || + ((*cpt=='Y' || *cpt=='y' || *cpt=='j' || *cpt=='J' || *cpt=='1') && + *(cpt+1)==0)) { + xorriso->request_to_abort= 1; + sprintf(xorriso->info_text, + "------- ( %s confirmed )\n",abort_req_text); + Xorriso_info(xorriso,0); + return(2); + } + sprintf(xorriso->info_text, "....... ( %s revoked )\n",abort_req_text); + Xorriso_info(xorriso,0); + return(3); + } + xorriso->request_to_abort= 1; + sprintf(xorriso->info_text, +"----------- [%s = request to abort registered. Operation ends ] ------------\n", + cpt); + Xorriso_info(xorriso,0); + return(2); + } else if(*cpt=='@') { + if(strcmp(cpt,"@@")==0) { + goto klammer_affe; + + } else if(strcmp(cpt,"@")==0) { +klammer_affe:; + if(xorriso->result_page_length>0) + xorriso->result_page_length= -xorriso->result_page_length; + if(flag&1) { + sprintf(xorriso->info_text, +"... [@ = prompt suppression registered. Prompting disabled temporarily ] ...\n"); + Xorriso_info(xorriso,0); + } + + } else { + Xorriso_dialog_input(xorriso,cpt,strlen(line)+1,2); /* write to history */ + sprintf(xorriso->info_text, + "--- Unrecognized input beginning with @. Please enter someting else.\n"); + Xorriso_info(xorriso,0); + return(3); + } + if(flag&2) + return(4); + if(flag&1) + return(3); + return(1); + } else if(flag&4) { + + if(strcmp(cpt,"i")==0 || strcmp(cpt,"I")==0 || + strcmp(cpt,"n")==0 || strcmp(cpt,"N")==0 || + *cpt==0) { + return(1); + } else if(strcmp(cpt,"r")==0 || strcmp(cpt,"R")==0 || + strcmp(cpt,"y")==0 || strcmp(cpt,"Y")==0) { + return(6); + } else { + /* >>> unknown input */ + sprintf(xorriso->info_text, + "--- Please enter one of : empty line, i,n, r,y, q,x, @, @@@\n"); + Xorriso_info(xorriso,0); + return(3); + } + + } else if(*cpt!=0 && !(flag&1)) { + Xorriso_dialog_input(xorriso,cpt,strlen(line)+1,2); /* write to history */ + strcpy(xorriso->pending_option,cpt); + xorriso->request_to_abort= 1; + sprintf(xorriso->info_text, +"-------------- [ Input of option registered. Operation ends ] ---------------\n"); + Xorriso_info(xorriso,0); + return(2); + + } else if(*cpt!=0) { + Xorriso_dialog_input(xorriso,cpt,strlen(line)+1,2); /* write to history */ + sprintf(xorriso->info_text, + "--- Please enter one of : empty line, @, @@@\n"); + Xorriso_info(xorriso,0); + return(3); + } + return(1); +} + + +/* @param flag bit0= quoted multiline mode + bit1= release allocated memory and return 1 + bit2= with bit0: warn of empty text arguments + bit3= deliver as single quoted text including all whitespace + and without any backslash interpretation + @return -1=out of memory , 0=line format error , 1=ok, go on , 2=done +*/ +int Xorriso_read_lines(struct XorrisO *xorriso, FILE *fp, int *linecount, + int *argc, char ***argv, int flag) +{ + char line[5 * SfileadrL + 2], *linept, *fgot; + int l, base_length, append_line, ret, mem_linecount, i; + + Sfile_make_argv("", line, argc, argv, 2); + if(flag & 2) + return(1); + + mem_linecount= *linecount; + linept= line; + base_length= 0; + while(1) { + fgot= Sfile_fgets_n(linept, SfileadrL - base_length + 1, fp, + !!(flag & (1 | 8))); + if(fgot == NULL) { + if(ferror(fp)) + return(0); + if(linept != line) { + sprintf(xorriso->info_text,"Open quotation mark at end of input"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + return(2); + } + l= strlen(line); + (*linecount)++; + append_line= 0; + if(flag & 1) { /* check whether the line is incomplete yet */ + ret= Sfile_make_argv("", line, argc, argv, 16); + if(ret < 0) + return(ret); + if(ret == 0 && !append_line) { + line[l]= '\n'; + line[l + 1]= 0; + append_line= 1; + } + if(l > 0 && !append_line) + if(line[l - 1] == '\\') { + line[l - 1]= 0; + append_line= 1; + } + } + if(l >= SfileadrL) { + sprintf(xorriso->info_text,"Input line too long !"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + if(!append_line) + break; + base_length= strlen(line); + linept= line + base_length; + } + if((flag & 1) && !(flag & 8)) { + ret= Sfile_make_argv("", line, argc, argv, + 1 | ((xorriso->bsl_interpretation & 3) << 5)); + if(ret < 0) + return(ret); + if(flag & 4) + for(i= 0; i < *argc; i++) { + if((*argv)[i][0] == 0) { + sprintf(xorriso->info_text, "Empty text as quoted argument in "); + } else if(strlen((*argv)[i]) >= SfileadrL) { + (*argv)[i][SfileadrL - 1]= 0; + sprintf(xorriso->info_text, + "Input text too long and now truncated in"); + } else + continue; + if(mem_linecount + 1 < *linecount) + sprintf(xorriso->info_text + strlen(xorriso->info_text), + "lines %d to %d", mem_linecount + 1, *linecount); + else + sprintf(xorriso->info_text + strlen(xorriso->info_text), + "line %d", mem_linecount + 1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); + } + } else { + (*argv)= Smem_malloC(sizeof(char *)); + if(argv == NULL) + return(-1); + (*argv)[0]= strdup(line); + if((*argv)[0] == NULL) + return(-1); + *argc= 1; + } + return(1); +} + + +int Xorriso_predict_linecount(struct XorrisO *xorriso, char *line, + int *linecount, int flag) +{ + int width,l; + char *spt,*ept; + + *linecount= 0; + spt= line; + width= xorriso->result_page_width; + while(1) { + ept= strchr(spt,'\n'); + if(ept==NULL) + l= strlen(spt); + else + l= ept-spt; + l+= xorriso->result_open_line_len; + if(ept!=NULL && l==0) + (*linecount)++; + else { + (*linecount)+= l/width; + if(ept==NULL) { + xorriso->result_open_line_len= l%width; + break; + } + (*linecount)+= !!(l%width); + } + xorriso->result_open_line_len= 0; + spt= ept+1; + } + return(1); +} + + +int Xorriso_pager(struct XorrisO *xorriso, char *line, int flag) +/* + bit1= mark '@' by return 4 +*/ +/* return: <=0 error , 1=go on , 2=abort , 4=see flag bit1*/ +{ + int ret,linecount; + char info_text[10*SfileadrL]; + + if(xorriso->result_page_length<=0 || xorriso->request_not_to_ask || + xorriso->dialog == 0) + return(1); + Xorriso_predict_linecount(xorriso,line,&linecount,0); + if(xorriso->result_line_counter+linecount>xorriso->result_page_length) { +ask_for_page:; + strcpy(info_text,xorriso->info_text); + sprintf(xorriso->info_text,"\n"); + Xorriso_info(xorriso,0); + sprintf(xorriso->info_text, +".... [Press Enter to continue. @,Enter avoids further stops. @@@ aborts] ....\n"); + Xorriso_info(xorriso,0); + ret= Xorriso_request_confirmation(xorriso,flag&2); + strcpy(xorriso->info_text,info_text); + if(ret<=0) + return(ret); + if(ret==2) + return(2); + if(ret==3) + goto ask_for_page; + } + xorriso->result_line_counter+= linecount; + return(1); +} + + +int Xorriso_write_to_channel(struct XorrisO *xorriso, + char *in_text, int channel_no, int flag) +/* + bit0= eventually backslash encode linefeeds + bit1= text is the name of the log file for the given channel + bit2= text is the name of the consolidated packet log file for all channels +bit15= with bit1 or bit2: close depicted log file +*/ +{ + char *rpt, *npt, *text; + int ret= 1, info_redirected= 0, result_redirected= 0; + char prefix[16]; + FILE *logfile_fp, *pktlog_fp; + struct Xorriso_lsT *msglist; + static int num_channels= 4; + static char channel_prefixes[4][4]= {".","R","I","M"}; + + if(channel_no<0 || channel_no>=num_channels) + {ret= -1; goto ex;} + + text= in_text; /* might change due to backslash encoding */ + + /* Logfiles */ + logfile_fp= xorriso->logfile_fp[channel_no]; + pktlog_fp= xorriso->pktlog_fp; + if((flag&2) && logfile_fp!=NULL) { + fprintf(logfile_fp, + "! end ! end ! end ! end ! end ! end ! end ! end xorriso log : %s : %s\n", + channel_prefixes[channel_no],Sfile_datestr(time(0),1|2|256)); + fclose(logfile_fp); + xorriso->logfile_fp[channel_no]= logfile_fp= NULL; + } + if((flag&4) && pktlog_fp!=NULL) { + fprintf(pktlog_fp, + "I:1:! end ! end ! end ! end ! end ! end ! end ! end xorriso log : %s : %s\n", + channel_prefixes[channel_no],Sfile_datestr(time(0),1|2|256)); + fclose(pktlog_fp); + xorriso->pktlog_fp= pktlog_fp= NULL; + } + if(flag&(1<<15)) + {ret= 1; goto ex;} + if((flag&2)) { + xorriso->logfile_fp[channel_no]= logfile_fp= fopen(text,"a"); + if(logfile_fp==NULL) + {ret= 0; goto ex;} + fprintf(logfile_fp, + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! xorriso log : %s : %s\n", + channel_prefixes[channel_no],Sfile_datestr(time(0),1|2|256)); + fflush(logfile_fp); + } + if((flag&4)) { + xorriso->pktlog_fp= pktlog_fp= fopen(text,"a"); + if(pktlog_fp==NULL) + {ret= 0; goto ex;} + fprintf(pktlog_fp, + "I:1:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! xorriso log : . : %s\n", + Sfile_datestr(time(0),1|2|256)); + fflush(pktlog_fp); + } + if(flag&(2|4)) + {ret= 1; goto ex;} + + /* Eventually perform backslash encoding of non-printable characters */ + if(((xorriso->bsl_interpretation & 32) && channel_no == 1) || + ((xorriso->bsl_interpretation & 64) && channel_no == 2)) { + ret= Sfile_bsl_encoder(&text, text, 1 | 2 | 4); + if(ret <= 0) + {ret= -1; goto ex;} + } + + /* Eventually perform messag redirection */ + if(xorriso->msglist_stackfill > 0) { + if(xorriso->msglist_flags[xorriso->msglist_stackfill - 1] & 1) + result_redirected= 1; + if(xorriso->msglist_flags[xorriso->msglist_stackfill - 1] & 2) + info_redirected= 1; + } + if(result_redirected) { + if(channel_no==1 || channel_no==3) { + msglist= xorriso->result_msglists[xorriso->msglist_stackfill - 1]; + ret= Xorriso_lst_append_binary(&msglist, text, strlen(text) + 1, 0); + if(ret <= 0) + {ret= -1; goto ex;} + if(xorriso->result_msglists[xorriso->msglist_stackfill - 1] == NULL) + xorriso->result_msglists[xorriso->msglist_stackfill - 1]= msglist; + } + } + if(info_redirected) { + if(channel_no==2 || channel_no==3) { + msglist= xorriso->info_msglists[xorriso->msglist_stackfill - 1]; + ret= Xorriso_lst_append_binary(&msglist, text, strlen(text) + 1, 0); + if(ret <= 0) + {ret= -1; goto ex;} + if(xorriso->info_msglists[xorriso->msglist_stackfill - 1] == NULL) + xorriso->info_msglists[xorriso->msglist_stackfill - 1]= msglist; + } + } + if((channel_no == 1 && result_redirected) || + (channel_no == 2 && info_redirected) || + (result_redirected && info_redirected)) + {ret= 1; goto ex;} + + /* Non-redirected output */ + if(!xorriso->packet_output) { + if(channel_no==1 || channel_no==3) { + printf("%s",text); + fflush(stdout); + } + if(channel_no==2 || channel_no==3) + fprintf(stderr,"%s",text); + if(logfile_fp!=NULL) { + fprintf(logfile_fp,"%s",text); + fflush(logfile_fp); + } + if(pktlog_fp==NULL) + {ret= 1; goto ex;} + } + rpt= text; + sprintf(prefix,"%s:x: ",channel_prefixes[channel_no]); + while(*rpt!=0) { + npt= strchr(rpt,'\n'); + if(npt==NULL) + prefix[2]= '0'; + else + prefix[2]= '1'; + if(xorriso->packet_output) { + ret= fwrite(prefix,5,1,stdout); + if(ret<=0) + {ret= 0; goto ex;} + } + if(pktlog_fp!=NULL) { + ret= fwrite(prefix,5,1,pktlog_fp); + if(ret<=0) + {ret= 0; goto ex;} + } + if(npt==NULL) { + if(xorriso->packet_output) { + ret= fwrite(rpt,strlen(rpt),1,stdout); + if(ret<=0) + {ret= 0; goto ex;} + ret= fwrite("\n",1,1,stdout); + if(ret<=0) + {ret= 0; goto ex;} + } + if(pktlog_fp!=NULL) { + ret= fwrite(rpt,strlen(rpt),1,pktlog_fp); + if(ret<=0) + {ret= 0; goto ex;} + ret= fwrite("\n",1,1,pktlog_fp); + if(ret<=0) + {ret= 0; goto ex;} + } + break; + } else { + if(xorriso->packet_output) { + ret= fwrite(rpt,npt+1-rpt,1,stdout); + if(ret<=0) + {ret= 0; goto ex;} + } + if(pktlog_fp!=NULL) { + ret= fwrite(rpt,npt+1-rpt,1,pktlog_fp); + if(ret<=0) + {ret= 0; goto ex;} + } + } + rpt= npt+1; + } + if(xorriso->packet_output) + fflush(stdout); + if(pktlog_fp!=NULL) + fflush(pktlog_fp); + ret= 1; +ex: + if(text != in_text && text != NULL) + free(text); + return(ret); +} + + +int Xorriso_push_outlists(struct XorrisO *xorriso, int *stack_handle, + int flag) +{ + if(xorriso->msglist_stackfill + 1 >= Xorriso_max_outlist_stacK) { + Xorriso_msgs_submit(xorriso, 0, + "Overflow of message output redirection stack", 0, "FATAL", 0); + return(-1); + } + if((flag & 3) == 0) + flag|= 3; + xorriso->msglist_stackfill++; + xorriso->result_msglists[xorriso->msglist_stackfill - 1]= NULL; + xorriso->info_msglists[xorriso->msglist_stackfill - 1]= NULL; + xorriso->msglist_flags[xorriso->msglist_stackfill - 1]= flag & 3; + *stack_handle= xorriso->msglist_stackfill - 1; + return(1); +} + + +int Xorriso_pull_outlists(struct XorrisO *xorriso, int stack_handle, + struct Xorriso_lsT **result_list, + struct Xorriso_lsT **info_list, int flag) +{ + int i; + + if(stack_handle < 0 || stack_handle >= xorriso->msglist_stackfill) { + Xorriso_msgs_submit(xorriso, 0, + "Program error: Wrong message output redirection stack handle", + 0, "FATAL", 0); + return(-1); + } + *result_list= xorriso->result_msglists[stack_handle]; + *info_list= xorriso->info_msglists[stack_handle]; + for(i = stack_handle + 1; i < xorriso->msglist_stackfill - 1; i++) { + xorriso->result_msglists[i - 1]= xorriso->result_msglists[i]; + xorriso->info_msglists[i - 1]= xorriso->info_msglists[i]; + } + xorriso->msglist_stackfill--; + return(1); +} + + +int Xorriso_result(struct XorrisO *xorriso, int flag) +/* + bit0= no considerations or computations or dialog. Just put out. +*/ +{ + int ret, redirected= 0; + + if(flag&1) + goto put_it_out; + if(xorriso->request_to_abort) + return(1); + if(xorriso->msglist_stackfill > 0) + if(xorriso->msglist_flags[xorriso->msglist_stackfill - 1] & 1) + redirected= 1; + if(xorriso->result_page_length>0 && !redirected) { + ret= Xorriso_pager(xorriso,xorriso->result_line,2); + if(ret<=0) + return(ret); + if(ret==2) + return(1); + if(xorriso->request_to_abort) + return(1); + } +put_it_out:; + xorriso->bar_is_fresh= 0; + ret= Xorriso_write_to_channel(xorriso, xorriso->result_line, 1,0); + return(ret); +} + + +int Xorriso_info(struct XorrisO *xorriso, int flag) +/* + bit0= use pager (as with result) + bit1= permission to suppress output + bit2= insist in showing output +*/ +{ + int ret; + static int note_sev= 0; + + if(flag&2) + if(xorriso->request_to_abort) + return(1); + + if(note_sev==0) + Xorriso__text_to_sev("NOTE", ¬e_sev, 0); + if(note_sev<xorriso->report_about_severity && + note_sev<xorriso->abort_on_severity && !(flag&4)) + return(1); + + if(flag&1) { + ret= Xorriso_pager(xorriso,xorriso->info_text,2); + if(ret<=0) + return(ret); + if(ret==2) + return(1); + if(flag&2) + if(xorriso->request_to_abort) + return(1); + } + xorriso->bar_is_fresh= 0; + ret=Xorriso_write_to_channel(xorriso, xorriso->info_text, 2, 0); + return(ret); +} + + +int Xorriso_mark(struct XorrisO *xorriso, int flag) +{ + int ret= 1,r_ret,i_ret; + + if(xorriso->mark_text[0]==0) + return(1); + if(xorriso->packet_output) + ret=Xorriso_write_to_channel(xorriso, xorriso->mark_text, 3, 0); + else { + sprintf(xorriso->result_line,"%s\n",xorriso->mark_text); + r_ret= Xorriso_result(xorriso,1); + strcpy(xorriso->info_text,xorriso->result_line); + i_ret= Xorriso_info(xorriso,0); + if(r_ret==0 || i_ret==0) + ret= 0; + } + return(ret); +} + + +int Xorriso_restxt(struct XorrisO *xorriso, char *text) +{ + int ret; + + strncpy(xorriso->result_line,text,sizeof(xorriso->result_line)-1); + xorriso->result_line[sizeof(xorriso->result_line)-1]= 0; + ret= Xorriso_result(xorriso,0); + return(ret); +} + + +int Xorriso_pacifier_reset(struct XorrisO *xorriso, int flag) +{ + xorriso->start_time= Sfile_microtime(0); + xorriso->last_update_time= xorriso->start_time; + xorriso->pacifier_count= 0; + xorriso->pacifier_total= 0; + xorriso->pacifier_byte_count= 0; + return(1); +} + + +/* This call is to be issued by long running workers in short intervals. + It will check whether enough time has elapsed since the last pacifier + message and eventually issue an update message. + @param what_done A sparse description of the action, preferrably in past + tense. E.g. "done" , "files added". + @param count The number of objects processed so far. + Is ignored if <=0. + @param todo The number of objects to be done in total. + Is ignored if <=0. + @param current_object A string telling the object currently processed. + Ignored if "". + @param flag bit0= report unconditionally, no time check + bit1= report count <=0 (no thank you for being patient then) + bit2= report xorriso->pacifier_byte_count + bit6= report with carriage return rather than line feed +*/ +int Xorriso_pacifier_callback(struct XorrisO *xorriso, char *what_done, + off_t count, off_t todo, char *current_object, + int flag) +{ + double current_time, since; + char count_text[80], byte_text[80]; + + current_time= Sfile_microtime(0); + if(current_time - xorriso->last_update_time < xorriso->pacifier_interval + && !(flag&1)) + return(1); + xorriso->last_update_time= Sfile_microtime(0); + since= current_time - xorriso->start_time; + if((flag&1)&&since<1.0) + since= 1.0; + byte_text[0]= 0; + if(flag&4) { + strcat(byte_text, " ("); + Sfile_scale((double) xorriso->pacifier_byte_count, + byte_text+strlen(byte_text), 7, 1e5, 0); + strcat(byte_text, ")"); + } + if(count<=0.0 && !(flag&2)) { + sprintf(xorriso->info_text, + "Thank you for being patient for %.f seconds", since); + } else if(todo<=0.0) { + if(count<10000000) + sprintf(count_text, "%.f", (double) count); + else + Sfile_scale((double) count, count_text, 7, 1e5, 1); + sprintf(xorriso->info_text, "%s %s%s in %.f %s", + count_text, what_done, byte_text, since, (flag&64) ? "s" : "seconds"); + } else { + sprintf(xorriso->info_text, "%.f of %.f %s%s in %.f seconds", + (double) count, (double) todo, what_done, byte_text, since); + } + if(current_object[0]!=0) + sprintf(xorriso->info_text+strlen(xorriso->info_text), + ", now at %s", current_object); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", (flag&64)); + return(1); +} + + +int Xorriso_reset_counters(struct XorrisO *xorriso, int flag) +{ + xorriso->error_count= 0; + xorriso->insert_count= 0; + xorriso->insert_bytes= 0; + Xorriso_pacifier_reset(xorriso, 0); + return(1); +} + + +int Xorriso__bourne_to_reg(char bourne_expr[], char reg_expr[], int flag) +/* reg_expr should be twice as large as bourne_expr ( + 2 to be exact) */ +/* return: 2= bourne_expr is surely a constant */ +{ + char *wpt,*lpt; + int backslash= 0,is_constant= 1,in_square_brackets= 0; + int first_in_square_brackets=0; + + wpt= reg_expr; + lpt= bourne_expr; + + *(wpt++)= '^'; + + while(*lpt!=0){ + if(first_in_square_brackets>0) + first_in_square_brackets--; + if(!backslash){ + switch(*lpt){ + case '?': + *(wpt++)= '.'; + is_constant= 0; + break;case '*': + *(wpt++)= '.'; + *(wpt++)= '*'; + is_constant= 0; + break;case '.': + *(wpt++)= '\\'; + *(wpt++)= '.'; + break;case '+': + *(wpt++)= '\\'; + *(wpt++)= '+'; + break;case '[': + *(wpt++)= *lpt; + first_in_square_brackets= 2; + in_square_brackets= 1; + is_constant= 0; + break;case ']': + *(wpt++)= *lpt; + in_square_brackets= 0; + break;case '!': + if(first_in_square_brackets) + *(wpt++)= '^'; + else if(in_square_brackets) + *(wpt++)= '!'; + else { + *(wpt++)= '\\'; + *(wpt++)= '!'; + } + break;case '^': + if(in_square_brackets) + *(wpt++)= '^'; + else + *(wpt++)= '\\'; + *(wpt++)= '^'; + break;case '$': + *(wpt++)= '\\'; + *(wpt++)= '$'; + break;case '\\': + backslash= 1; + *(wpt++)= '\\'; + is_constant= 0; + break;default: + *(wpt++)= *lpt; + } + } else { + backslash= 0; + *(wpt++)= *lpt; + } + lpt++; + } + *(wpt++)= '$'; + *wpt= 0; + return(1+(is_constant>0)); +} + + +/* @param flag bit0= do not augment relative structured search by xorriso->wdi + bit1= return 2 if bonked at start point by .. + (caller then aborts or retries without bit0) + bit2= eventually prepend wdx rather than wdi + @return <=0 error, 1= ok, 2= with bit1: relative pattern exceeds start point +*/ +int Xorriso_prepare_regex(struct XorrisO *xorriso, char *adr, int flag) +{ + int l,ret,i,count,bonked= 0,is_constant,is_still_relative= 0; + char *cpt,*npt,adr_part[2*SfileadrL],absolute_adr[2*SfileadrL],*adr_start,*wd; + + if(flag&4) + wd= xorriso->wdx; + else + wd= xorriso->wdi; + + if(xorriso->search_mode>=2 && xorriso->search_mode<=4) { + if(xorriso->search_mode==3 || xorriso->search_mode==4) { + l= strlen(adr)+strlen(wd)+1; + if(l*2+2>sizeof(xorriso->reg_expr) || l*2+2>sizeof(adr_part)) { + sprintf(xorriso->info_text,"Search pattern too long"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + } + Xorriso_destroy_re(xorriso,0); + if(xorriso->structured_search && xorriso->search_mode==3) { + if(adr[0]!='/') + is_still_relative= 1; + if(is_still_relative && !(flag&1)) { + /* relative expression : prepend working directory */ + sprintf(absolute_adr,"%s/%s",wd,adr); + adr_start= absolute_adr; + xorriso->prepended_wd= 1; + is_still_relative= 0; + } else + adr_start= adr; + /* count slashes */; + cpt= adr_start; + while(*cpt=='/') + cpt++; + for(i= 0;1;i++) { + cpt= strchr(cpt,'/'); + if(cpt==NULL) + break; + while(*cpt=='/') + cpt++; + } + count= i+1; + xorriso->re= TSOB_FELD(regex_t,count); + if(xorriso->re==NULL) + return(-1); + xorriso->re_constants= TSOB_FELD(char *,count); + if(xorriso->re_constants==NULL) + return(-1); + for(i= 0;i<count;i++) + xorriso->re_constants[i]= NULL; + xorriso->re_count= count; + xorriso->re_fill= 0; + + /* loop over slash chunks*/; + cpt= adr_start; + xorriso->re_fill= 0; + while(*cpt=='/') + cpt++; + for(i= 0;i<count;i++) { + npt= strchr(cpt,'/'); + if(npt==NULL) { + if(strlen(cpt)>=sizeof(adr_part)) + return(-1); + strcpy(adr_part,cpt); + } else { + if(npt-cpt>=sizeof(adr_part)) + return(-1); + strncpy(adr_part,cpt,npt-cpt); + adr_part[npt-cpt]= 0; + } + + if(adr_part[0]==0) + goto next_adr_part; + if(adr_part[0]=='.' && adr_part[1]==0 && + (xorriso->re_fill>0 || i<count-1)) + goto next_adr_part; + if(adr_part[0]=='.' && adr_part[1]=='.' && adr_part[2]==0) { + /* delete previous part */ + if(xorriso->re_fill<=1) { + bonked= 1; + goto next_adr_part; + } + if(xorriso->re_constants[xorriso->re_fill-1]!=NULL) { + free(xorriso->re_constants[xorriso->re_fill-1]); + xorriso->re_constants[xorriso->re_fill-1]= NULL; + } else + regfree(&(xorriso->re[xorriso->re_fill-1])); + (xorriso->re_fill)--; + goto next_adr_part; + } + if(strcmp(adr_part,"*")==0) { + adr_part[0]= 0; + ret= 2; + } else + ret= Xorriso__bourne_to_reg(adr_part,xorriso->reg_expr,0); + if(ret==2) { + if(Sregex_string(&(xorriso->re_constants[xorriso->re_fill]),adr_part,0) + <=0) + return(-1); + } else { + if(regcomp(&(xorriso->re[xorriso->re_fill]),xorriso->reg_expr,0)!=0) + goto cannot_compile; + } + xorriso->re_fill++; +next_adr_part:; + if(i==count-1) + break; + cpt= npt+1; + while(*cpt=='/') + cpt++; + } + if(bonked) { + if(flag&2) + return(2); + sprintf(xorriso->info_text, "Your '..' bonked at the %s directory.", + is_still_relative ? "working" : "root"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE",0); + return(0); + } + + Xorriso__bourne_to_reg(adr_start,xorriso->reg_expr,0); /* just for show */ + + } else { + is_constant= 0; + if(strcmp(adr,"*")==0 || adr[0]==0) { + is_constant= 1; + } else if(xorriso->search_mode==3 || xorriso->search_mode==4) { + ret= Xorriso__bourne_to_reg(adr,xorriso->reg_expr,0); + is_constant= (ret==2); + } else { + if(strlen(adr)>=sizeof(xorriso->reg_expr)) + return(-1); + strcpy(xorriso->reg_expr,adr); + } + xorriso->re_count= 0; /* tells matcher that this is not structured */ + xorriso->re_constants= TSOB_FELD(char *,1); + if(xorriso->re_constants==NULL) + return(-1); + xorriso->re_constants[0]= NULL; + if(is_constant) { + if(strcmp(adr,"*")==0) { + if(Sregex_string(&(xorriso->re_constants[0]),"",0)<=0) + return(-1); + } else { + if(Sregex_string(&(xorriso->re_constants[0]),adr,0)<=0) + return(-1); + } + xorriso->re_fill= 1; + } else { + xorriso->re= TSOB_FELD(regex_t,1); + if(xorriso->re==NULL) + return(-1); + if(regcomp(&(xorriso->re[0]),xorriso->reg_expr,0)!=0) { +cannot_compile:; + sprintf(xorriso->info_text, "Cannot compile regular expression : %s", + xorriso->reg_expr); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE",0); + return(0); + } + } + + } + } + return(1); +} + + +/* @param flag bit0= do not shortcut last component of to_match + bit1= consider match if regex matches parent of path + bit2= retry beginning at failed last component + + @return 0=match , else no match +*/ +int Xorriso_regexec(struct XorrisO *xorriso, char *to_match, int *failed_at, + int flag) +{ + int ret,i,re_start= 0,reg_nomatch= -1; + char *cpt,*npt,adr_part[SfileadrL],*mpt; + + reg_nomatch= REG_NOMATCH; + + *failed_at= 0; + if(!(xorriso->structured_search && xorriso->re_count>0)) { + if(xorriso->re_constants!=NULL) + if(xorriso->re_constants[0]!=NULL) { + if(xorriso->re_constants[0][0]==0) + return(0); + if(strcmp(xorriso->re_constants[0],to_match)!=0) + return(reg_nomatch); + return(0); + } + ret= regexec(&(xorriso->re[0]),to_match,1,xorriso->match,0); + return(ret); + } + + cpt= to_match; + while(*cpt=='/') + cpt++; + if(flag&4) + re_start= xorriso->re_failed_at; + if(re_start<0) + re_start= 0; + for(i= re_start;i<xorriso->re_fill;i++) { + *failed_at= i; + npt= strchr(cpt,'/'); + if(npt==NULL) { + if(i<xorriso->re_fill-1 && !(flag&1)) + return(reg_nomatch); /* this must be the last expression part */ + mpt= cpt; + } else { + strncpy(adr_part,cpt,npt-cpt); + adr_part[npt-cpt]= 0; + mpt= adr_part; + } + if(xorriso->re_constants[i]!=NULL) { + if(xorriso->re_constants[i][0]!=0) /* empty constant matches anything */ + if(strcmp(xorriso->re_constants[i],mpt)!=0) + return(reg_nomatch); + } else { + ret= regexec(&(xorriso->re[i]),mpt,1,xorriso->match,0); + if(ret!=0) + return(ret); + } + if(npt==NULL) { + if(i>=xorriso->re_fill-1) + return(0); /* MATCH */ + *failed_at= i+1; + return(reg_nomatch); + } + cpt= npt+1; + while(*cpt=='/') + cpt++; + } + *failed_at= xorriso->re_fill; + if(flag & 2) + return(0); /* MATCH */ + return(reg_nomatch); +} + + +int Xorriso_is_in_patternlist(struct XorrisO *xorriso, + struct Xorriso_lsT *patternlist, char *path, + int flag) +{ + int ret, failed_at, i= 0; + struct Xorriso_lsT *s; + + xorriso->search_mode= 3; + xorriso->structured_search= 1; + + for(s= patternlist; s != NULL; s= Xorriso_lst_get_next(s, 0)) { + ret= Xorriso_prepare_regex(xorriso, Xorriso_lst_get_text(s, 0), 0); + if(ret <= 0) + return(-1); + /* Match path or parent of path */ + ret= Xorriso_regexec(xorriso, path, &failed_at, 2); + if(ret == 0) + return(i + 1); + i++; + } + return(0); +} + + +char *Xorriso_get_pattern(struct XorrisO *xorriso, + struct Xorriso_lsT *patternlist, int index, int flag) +{ + int i= 0; + struct Xorriso_lsT *s; + + for(s= patternlist; s != NULL; s= Xorriso_lst_get_next(s, 0)) { + if(i == index) + return(Xorriso_lst_get_text(s, 0)); + i++; + } + return(NULL); +} + + +/* @param flag bit0= simple readlink(): no normalization, no multi-hop +*/ +int Xorriso_resolve_link(struct XorrisO *xorriso, + char *link_path, char result_path[SfileadrL], int flag) +{ + ssize_t l; + struct stat stbuf; + int link_count= 0, ret, show_errno= 0; + char buf[SfileadrL], dirbuf[SfileadrL], *lpt, *spt, sfe[5*SfileadrL]; + static int link_limit= 100; + + if(!(flag&1)) + if(stat(link_path, &stbuf)==-1) + if(errno==ELOOP) { + show_errno= errno; + goto too_many_hops; + } + lpt= link_path; + while(1) { + l= readlink(lpt, buf, SfileadrL-1); + if(l==-1) { +handle_error:; + Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, "Cannot obtain link target of : %s", + Text_shellsafe(link_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); +handle_abort:; + if(strcmp(lpt, link_path)!=0) { + sprintf(xorriso->info_text, + "Problem occured with intermediate path : %s", + Text_shellsafe(lpt, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE",0); + } + return(0); + } + buf[l]= 0; + if(l==0) { + Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, "Empty link target with : %s", + Text_shellsafe(link_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); + goto handle_abort; + } + + if(flag&1) { + strcpy(result_path, buf); + return(1); + } + + /* normalize relative to disk_path */ + if(Sfile_str(dirbuf, lpt, 0)<=0) + return(-1); + while(1) { + spt= strrchr(dirbuf,'/'); + if(spt!=NULL) { + *spt= 0; + if(*(spt+1)!=0) + break; + } else + break; + } + ret= Xorriso_normalize_img_path(xorriso, dirbuf, buf, result_path, 2|4); + if(ret<=0) + return(ret); + + if(lstat(result_path, &stbuf)==-1) { + lpt= result_path; + goto handle_error; + } + if(!S_ISLNK(stbuf.st_mode)) + break; + + lpt= result_path; + link_count++; + if(link_count>link_limit) { +too_many_hops:; + Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, "Too many link hops with : %s", + Text_shellsafe(link_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, show_errno, + "FAILURE",0); + return(0); + } + } + return(1); +} + + +int Xorriso_status_result(struct XorrisO *xorriso, char *filter, FILE *fp, + int flag) +/* +bit1= do only report to fp +*/ +{ + int ret,l; + + if(filter!=NULL) + if(filter[0]=='-') { + l= strlen(filter); + if(strncmp(filter,xorriso->result_line,l)!=0) + return(2); + } + if(!(flag&2)) + Xorriso_result(xorriso,0); + if(fp!=NULL) { + ret= fwrite(xorriso->result_line,strlen(xorriso->result_line),1,fp); + if(ret<=0) + return(ret); + } + return(1); +} + + +int Xorriso_check_media_setup_job(struct XorrisO *xorriso, + struct CheckmediajoB *job, + char **argv, int old_idx, int end_idx, int flag) +{ + int ret, i; + double num; + struct CheckmediajoB *default_job; + + if(xorriso->check_media_default != NULL) + Checkmediajob_copy(xorriso->check_media_default, job, 0); + for(i= old_idx; i < end_idx; i++) { + if(strncmp(argv[i], "abort_file=", 11) == 0) { + ret= Sfile_str(job->abort_file_path, argv[i] + 11, 0); + if(ret <= 0) + goto ex; + } else if(strncmp(argv[i], "data_to=", 8) == 0) { + ret= Sfile_str(job->data_to_path, argv[i] + 8, 0); + if(ret <= 0) + goto ex; + } else if(strncmp(argv[i], "map_with_volid=", 15) == 0) { + if(strcmp(argv[i] + 15, "on") == 0) + job->map_with_volid= 1; + else if(strcmp(argv[i] + 15, "off") == 0) + job->map_with_volid= 0; + else + goto unknown_value; + } else if(strncmp(argv[i], "max_lba=", 8) == 0 || + strncmp(argv[i], "min_lba=", 8) == 0) { + num= -1; + sscanf(argv[i] + 8, "%lf", &num); + if(num > 0x7fffffff || num < 0) + num= -1; + if(strncmp(argv[i], "max_lba=", 8) == 0) + job->max_lba= num; + else + job->min_lba= num; + } else if(strncmp(argv[i], "patch_lba0=", 11) == 0) { + job->patch_lba0_msc1= -1; + if(strcmp(argv[i] + 11, "on") == 0) + job->patch_lba0= 1; + else if(strcmp(argv[i] + 11, "off") == 0) + job->patch_lba0= 0; + else if(strcmp(argv[i] + 11, "force") == 0) + job->patch_lba0= 2; + else if(argv[i][11] >= '1' && argv[i][11] <= '9') { + num= -1; + sscanf(argv[i] + 11, "%lf", &num); + if(num > 0x7fffffff || num < 0) + goto unknown_value; + job->patch_lba0_msc1= num; + job->patch_lba0= (num >= 32) + (strstr(argv[i] + 11, ":force") != NULL); + } else + goto unknown_value; + } else if(strncmp(argv[i], "report=", 7) == 0) { + if(strcmp(argv[i] + 7, "blocks") == 0) + job->report_mode= 0; + else if(strcmp(argv[i] + 7, "files") == 0) + job->report_mode= 1; + else if(strcmp(argv[i] + 7, "blocks_files") == 0) + job->report_mode= 2; + else + goto unknown_value; + } else if(strcmp(argv[i], "reset=now") == 0) { + ret= Checkmediajob_new(&default_job, 0); + if(ret <= 0) { + sprintf(xorriso->info_text, + "-check_media: Cannot reset optionis due to lack of resources"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + ret= -1; goto ex; + } + Checkmediajob_copy(default_job, job, 0); + Checkmediajob_destroy(&default_job, 0); + } else if(strncmp(argv[i], "retry=", 6) == 0) { + if(strcmp(argv[i] + 6, "on") == 0) + job->retry= 1; + else if(strcmp(argv[i] + 6, "off") == 0) + job->retry= -1; + else if(strcmp(argv[i] + 6, "default") == 0) + job->retry= 0; + else + goto unknown_value; + } else if(strncmp(argv[i], "sector_map=", 11) == 0) { + ret= Sfile_str(job->sector_map_path, argv[i] + 11, 0); + if(ret <= 0) + goto ex; + } else if(strncmp(argv[i], "time_limit=", 11) == 0 || + strncmp(argv[i], "item_limit=", 11) == 0 ) { + num= -1; + sscanf(argv[i] + 11, "%lf", &num); + if(num > 0x7fffffff || num < 0) + num= -1; + if(strncmp(argv[i], "time_limit=", 11) == 0) + job->time_limit= num; + else + job->item_limit= num; + } else if(strncmp(argv[i], "use=", 4) == 0) { + if(strcmp(argv[i] + 4, "outdev") == 0) + job->use_dev= 1; + else if(strcmp(argv[i] + 4, "indev") == 0) + job->use_dev= 0; + else if(strcmp(argv[i] + 4, "sector_map") == 0) + job->use_dev= 2; + else + goto unknown_value; + } else if(strncmp(argv[i], "what=", 5) == 0) { + if(strcmp(argv[i]+5, "tracks") == 0) + job->mode= 0; + else if(strcmp(argv[i]+5, "disc")== 0) + job->mode= 1; + else { +unknown_value:; + sprintf(xorriso->info_text, + "-check_media: Unknown value with option %s", argv[i]); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + } else { + sprintf(xorriso->info_text, "-check_media: Unknown option '%s'", argv[i]); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + } + ret= 1; +ex:; + return(ret); +} + + +/* @param report Buffer of at least 10*SfileadrL + @param flag bit0= only report non-default settings + @return <=0 error , 1 ok , 2 with bit0: every option is on default setting +*/ +int Xorriso_check_media_list_job(struct XorrisO *xorriso, + struct CheckmediajoB *job, + char *report, int flag) +{ + int all, ret; + char default_report[161]; + struct CheckmediajoB *dflt= NULL; + + all= !(flag&1); + report[0]= 0; + ret= Checkmediajob_new(&dflt, 0); + if(ret <= 0) + return(-1); + sprintf(report, "-check_media_defaults"); + if(!all) + strcat(report, " reset=now"); + if(all || job->use_dev != dflt->use_dev) + sprintf(report + strlen(report), " use=%s", + job->use_dev == 1 ? "outdev" : + job->use_dev == 2 ? "sector_map" : "indev"); + if(all || job->mode != dflt->mode) + sprintf(report + strlen(report), " what=%s", + job->mode == 1 ? "disc" : "tracks"); + if(all || job->min_lba != dflt->min_lba) + sprintf(report + strlen(report), " min_lba=%d", job->min_lba); + if(all || job->max_lba != dflt->max_lba) + sprintf(report + strlen(report), " max_lba=%d", job->max_lba); + if(all || job->retry != dflt->retry) + sprintf(report + strlen(report), " retry=%s", + job->retry == 1 ? "on" : job->retry == -1 ? "off" : "default"); + if(all || job->time_limit != dflt->time_limit) + sprintf(report + strlen(report), " time_limit=%d", job->time_limit); + if(all || job->item_limit != dflt->item_limit) + sprintf(report + strlen(report), " item_limit=%d", job->item_limit); + if(all || strcmp(job->abort_file_path, dflt->abort_file_path)) { + strcat(report, " abort_file="); + Text_shellsafe(job->abort_file_path, report + strlen(report), 0); + } + if(strlen(report) > 4 * SfileadrL) + {ret= 0; goto ex;} + if(all || strcmp(job->data_to_path, dflt->data_to_path)) { + strcat(report, " data_to="); + Text_shellsafe(job->data_to_path, report + strlen(report), 0); + } + if(strlen(report) > 4 * SfileadrL) + {ret= 0; goto ex;} + if(all || strcmp(job->sector_map_path, dflt->sector_map_path)) { + strcat(report, " sector_map="); + Text_shellsafe(job->sector_map_path, report + strlen(report), 0); + } + if(all || job->map_with_volid != dflt->map_with_volid) + sprintf(report + strlen(report), " map_with_volid=%s", + job->map_with_volid == 1 ? "on" : "off"); + if(all || job->patch_lba0 != dflt->patch_lba0) { + sprintf(report + strlen(report), " patch_lba0="); + if(job->patch_lba0 == 0) + sprintf(report + strlen(report), "off"); + else if(job->patch_lba0_msc1 >= 0) + sprintf(report + strlen(report), "%d%s", + job->patch_lba0_msc1, job->patch_lba0 == 2 ? ":force" : ""); + else + sprintf(report + strlen(report), "%s", + job->patch_lba0 == 2 ? "force" : "on"); + } + if(all || job->report_mode != dflt->report_mode) + sprintf(report + strlen(report), " report=%s", + job->report_mode == 0 ? "blocks" : + job->report_mode == 1 ? "files" : "blocks_files"); + if(strlen(report) > 4 * SfileadrL) + {ret= 0; goto ex;} + ret= 1; +ex:; + strcat(report, xorriso->list_delimiter); + Checkmediajob_destroy(&dflt, 0); + sprintf(default_report, "-check_media_defaults reset=now %s", + xorriso->list_delimiter); + if(ret > 0 && strcmp(report, default_report) == 0) + return(2); + return(ret); +} + + +int Xorriso_status(struct XorrisO *xorriso, char *filter, FILE *fp, int flag) +/* + bit0= do only report non-default settings + bit1= do only report to fp + bit2= report current -resume status even if bit0 is set, but only if valid + bit3= report readline history + bit4= report -resume options indirectly as + -options_from_file:${resume_state_file}_pos +*/ +{ + int is_default, no_defaults, i, ret, adr_mode, bin_path_in_use= 0, do_single; + char *line, sfe[5 * SfileadrL + 80], mode[80], *form, *treatment; + char *in_pt, *out_pt, *nl_charset, *local_charset; + static char channel_prefixes[4][4]= {".","R","I","M"}; + static char load_names[][20]= {"auto", "session", "track", "lba", "volid"}; + static int max_load_mode= 4; + struct Xorriso_lsT *paths, *leafs, *s; + + no_defaults= flag&1; + line= xorriso->result_line; + + if(xorriso->no_rc) { + sprintf(line,"-no_rc\n"); + Xorriso_status_result(xorriso,filter,fp,flag&2); + } + + is_default= strcmp(xorriso->list_delimiter, "--") == 0; + sprintf(line,"-list_delimiter %s\n", xorriso->list_delimiter); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= 0; + if(xorriso->dialog == 2) + sprintf(line,"-dialog on\n"); + else if(xorriso->dialog == 1) + sprintf(line,"-dialog single_line\n"); + else { + sprintf(line,"-dialog off\n"); + is_default= 1; + } + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->result_page_length==0 && xorriso->result_page_width==80); + sprintf(line,"-page %d %d\n", + (xorriso->result_page_length>=0?xorriso->result_page_length + :-xorriso->result_page_length), + xorriso->result_page_width); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->use_stdin==0); + sprintf(line,"-use_readline %s\n", (xorriso->use_stdin?"off":"on")); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->bsl_interpretation == 0); + strcpy(line, "-backslash_codes "); + if(xorriso->bsl_interpretation == 0) + strcat(line, "off"); + else if(xorriso->bsl_interpretation == (3 | 16 | 32 | 64)) + strcat(line, "on"); + else { + if((xorriso->bsl_interpretation & 3) == 1) + strcat(line, "in_double_quotes"); + else if((xorriso->bsl_interpretation & 3) == 2) + strcat(line, "in_quotes"); + else if((xorriso->bsl_interpretation & 3) == 3) + strcat(line, "with_quoted_input"); + if(xorriso->bsl_interpretation & 16) { + if(strlen(line) > 17) + strcat(line, ":"); + strcat(line, "with_program_arguments"); + } + if((xorriso->bsl_interpretation & (32 | 64)) == (32 | 64)) { + if(strlen(line) > 17) + strcat(line, ":"); + strcat(line, "encode_output"); + } else { + if(xorriso->bsl_interpretation & 32) { + if(strlen(line) > 17) + strcat(line, ":"); + strcat(line, "encode_results"); + } + if(xorriso->bsl_interpretation & 64) { + if(strlen(line) > 17) + strcat(line, ":"); + strcat(line, "encode_infos"); + } + } + } + strcat(line, "\n"); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= !xorriso->packet_output; + sprintf(line,"-pkt_output %s\n",(xorriso->packet_output?"on":"off")); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + for(i=0;i<4;i++) { + is_default= (xorriso->logfile[i]!=0); + sprintf(line,"-logfile %s %s\n", + channel_prefixes[i],Text_shellsafe(xorriso->logfile[i],sfe,0)); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + } + + is_default= (xorriso->errfile_log[0]==0); + sprintf(line,"-errfile_log %s\n",Text_shellsafe(xorriso->errfile_log,sfe,0)); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + if(xorriso->check_media_default == NULL) { + is_default= 1; + sprintf(line, "-check_media_defaults reset=now %s\n", + xorriso->list_delimiter); + } else { + ret= Xorriso_check_media_list_job(xorriso, xorriso->check_media_default, + line, no_defaults); + is_default= (ret == 2); + strcat(line, "\n"); + } + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->img_read_error_mode==2); + treatment= "best_effort"; + if(xorriso->img_read_error_mode==1) + treatment= "failure"; + else if(xorriso->img_read_error_mode==2) + treatment= "fatal"; + sprintf(line,"-error_behavior image_loading %s\n", treatment); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + is_default= (xorriso->extract_error_mode == 1); + treatment= "keep"; + if(xorriso->extract_error_mode == 0) + treatment= "best_effort"; + else if(xorriso->extract_error_mode == 2) + treatment= "delete"; + sprintf(line,"-error_behavior file_extraction %s\n", treatment); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->mark_text[0]==0); + sprintf(line,"-mark %s\n",Text_shellsafe(xorriso->mark_text,sfe,0)); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->temp_mem_limit==16*1024*1024); + if((xorriso->temp_mem_limit/1024/1024)*1024*1024==xorriso->temp_mem_limit) + sprintf(line,"-temp_mem_limit %dm\n", xorriso->temp_mem_limit/1024/1024); + else + sprintf(line,"-temp_mem_limit %dk\n", xorriso->temp_mem_limit/1024); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + + sprintf(line,"-prog %s\n",Text_shellsafe(xorriso->progname,sfe,0)); + Xorriso_status_result(xorriso,filter,fp,flag&2); + + if(xorriso->ban_stdio_write) { + sprintf(line,"-ban_stdio_write\n"); + Xorriso_status_result(xorriso,filter,fp,flag&2); + } + + is_default= (xorriso->allow_restore==0 && xorriso->do_concat_split==1 && + xorriso->do_auto_chmod==0); + sprintf(line,"-osirrox %s:%s:%s\n", + xorriso->allow_restore ? xorriso->allow_restore==2 ? + "device_files" : "on" : "off", + xorriso->do_concat_split ? "concat_split_on" : "concat_split_off", + xorriso->do_auto_chmod ? "auto_chmod_on" : "auto_chmod_off" + ); + + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->keep_boot_image == 0 + && xorriso->patch_isolinux_image == 0 + && xorriso->boot_image_bin_path[0] == 0); + form= "any"; + treatment= "discard"; + if(xorriso->boot_image_bin_path[0]) { + form= "isolinux"; + if(strcmp(xorriso->boot_image_bin_path, "/isolinux.bin") == 0 && + strcmp(xorriso->boot_image_cat_path, "/boot.cat") == 0) + strcpy(sfe, "dir=/"); + else if(strcmp(xorriso->boot_image_bin_path, "/isolinux/isolinux.bin") == 0 + && strcmp(xorriso->boot_image_cat_path, "/isolinux/boot.cat") == 0) + strcpy(sfe, "dir=/isolinux"); + else if(strcmp(xorriso->boot_image_bin_path, + "/boot/isolinux/isolinux.bin") == 0 + && strcmp(xorriso->boot_image_cat_path, + "/boot/isolinux/boot.cat") == 0) + strcpy(sfe, "dir=/boot/isolinux"); + else { + strcpy(sfe, "bin_path="); + Text_shellsafe(xorriso->boot_image_bin_path, sfe + strlen(sfe), 0); + bin_path_in_use= 1; + } + treatment= sfe; + } else if(xorriso->patch_isolinux_image) { + form= "isolinux"; + treatment= "patch"; + } else if(xorriso->keep_boot_image) { + treatment= "keep"; + } + sprintf(line,"-boot_image %s %s\n", form, treatment); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + if(xorriso->boot_image_bin_path[0] && bin_path_in_use) { + is_default= 0; + sprintf(line,"-boot_image isolinux cat_path=%s\n", + Text_shellsafe(xorriso->boot_image_cat_path, sfe, 0)); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + is_default= xorriso->boot_image_load_size == 4 * 512; + sprintf(line,"-boot_image isolinux load_size=%.f\n", + (double) xorriso->boot_image_load_size); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + } + if(strcmp(form, "isolinux") == 0) { + static char modes[4][6]= {"off", "auto", "on", "force"}; + is_default= (xorriso->boot_image_isohybrid == 1); + sprintf(line,"-boot_image isolinux isohybrid=%s\n", + modes[xorriso->boot_image_isohybrid & 3]); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + } + + sprintf(line,"-cd %s\n", + (xorriso->wdi[0] ? Text_shellsafe(xorriso->wdi,sfe,0) : "'/'")); + Xorriso_status_result(xorriso,filter,fp,flag&2); + sprintf(line,"-cdx %s\n", + (xorriso->wdx[0] ? Text_shellsafe(xorriso->wdx,sfe,0) : "'/'")); + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->split_size==0); + strcpy(line,"-split_size "); + if(xorriso->split_size % (1024*1024) || xorriso->split_size==0) { + Sfile_off_t_text(line+strlen(line), xorriso->split_size, 0); + } else { + Sfile_off_t_text(line+strlen(line), xorriso->split_size / (1024*1024), 0); + strcat(line, "m"); + } + strcat(line, "\n"); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->add_plainly==0); + sprintf(line,"-add_plainly %s\n", + (xorriso->add_plainly == 1 ? "unknown" : + xorriso->add_plainly == 2 ? "dashed" : + xorriso->add_plainly == 3 ? "any" : "none")); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + ret= Exclusions_get_descrs(xorriso->disk_exclusions, &paths, &leafs, 0); + if(ret>0) { + for(; paths!=NULL; paths= paths->next) { + sprintf(line, "-not_paths %s %s\n", + Text_shellsafe(paths->text, sfe, 0), xorriso->list_delimiter); + Xorriso_status_result(xorriso,filter,fp,flag&2); + } + for(; leafs!=NULL; leafs= leafs->next) { + sprintf(line,"-not_leaf %s\n", Text_shellsafe(leafs->text, sfe, 0)); + Xorriso_status_result(xorriso,filter,fp,flag&2); + } + } + + is_default= (xorriso->file_size_limit == + Xorriso_default_file_size_limiT); + if(xorriso->file_size_limit <= 0) + sprintf(line, "-file_size_limit off %s\n", xorriso->list_delimiter); + else + sprintf(line, "-file_size_limit %.f %s\n", + (double) xorriso->file_size_limit, xorriso->list_delimiter); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->disk_excl_mode==1); + sprintf(line, "-not_mgt %s:%s:%s:%s\n", + (xorriso->disk_excl_mode&1 ? "on" : "off"), + (xorriso->disk_excl_mode&2 ? "param_on" : "param_off"), + (xorriso->disk_excl_mode&4 ? "subtree_on" : "subtree_off"), + (xorriso->disk_excl_mode&8 ? "ignore_on" : "ignore_off")); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->do_iso_rr_pattern==1); + sprintf(line,"-iso_rr_pattern %s\n", + (xorriso->do_iso_rr_pattern == 1 ? "on" : + (xorriso->do_iso_rr_pattern == 2 ? "ls" : "off"))); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->do_disk_pattern==2); + sprintf(line,"-disk_pattern %s\n", + (xorriso->do_disk_pattern == 1 ? "on" : + (xorriso->do_disk_pattern == 2 ? "ls" : "off"))); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= xorriso->volid_default; + sprintf(line,"-volid %s\n",Text_shellsafe(xorriso->volid,sfe,0)); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + if(is_default && xorriso->loaded_volid[0] && + strcmp(xorriso->loaded_volid, xorriso->volid)!=0 && !no_defaults) { + sprintf(line,"# loaded image effective -volid %s\n", + Text_shellsafe(xorriso->loaded_volid,sfe,0)); + Xorriso_status_result(xorriso,filter,fp,flag&2); + } + + is_default= (xorriso->publisher[0]==0); + sprintf(line,"-publisher %s\n",Text_shellsafe(xorriso->publisher,sfe,0)); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->application_id[0]==0); + sprintf(line,"-application_id %s\n", + Text_shellsafe(xorriso->application_id,sfe,0)); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->do_joliet==0); + sprintf(line,"-joliet %s\n", (xorriso->do_joliet == 1 ? "on" : "off")); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (Xorriso_get_relax_text(xorriso, sfe, 0) == 2); + sprintf(line,"-compliance %s\n", sfe); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + if(xorriso->do_global_uid) { + sprintf(line,"-uid %lu\n", (unsigned long) xorriso->global_uid); + Xorriso_status_result(xorriso,filter,fp,flag&2); + } + + if(xorriso->do_global_gid) { + sprintf(line,"-gid %lu\n", (unsigned long) xorriso->global_gid); + Xorriso_status_result(xorriso,filter,fp,flag&2); + } + + is_default= !xorriso->allow_graft_points; + sprintf(line,"-pathspecs %s\n", xorriso->allow_graft_points ? "on" : "off"); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->do_follow_pattern && (!xorriso->do_follow_param) + && xorriso->do_follow_mount && (!xorriso->do_follow_links) + && xorriso->follow_link_limit==100); + mode[0]= 0; + if(xorriso->do_follow_pattern && + !(xorriso->do_follow_links && xorriso->do_follow_mount)) + strcat(mode,":pattern"); + if(xorriso->do_follow_param && !(xorriso->do_follow_links)) + strcat(mode,":param"); + if(xorriso->do_follow_links) + strcat(mode,":link"); + if(xorriso->do_follow_mount) + strcat(mode,":mount"); + if(mode[0]==0) + strcpy(mode, ":off"); + sprintf(mode+strlen(mode), ":limit=%d", xorriso->follow_link_limit); + sprintf(line,"-follow %s\n", mode+1); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->do_overwrite==2); + sprintf(line,"-overwrite %s\n",(xorriso->do_overwrite == 1 ? "on" : + (xorriso->do_overwrite == 2 ? "nondir" : "off"))); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= !xorriso->do_reassure; + sprintf(line,"-reassure %s\n",(xorriso->do_reassure == 1 ? "on" : + (xorriso->do_reassure == 2 ? "tree" : "off"))); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= !xorriso->do_close; + sprintf(line,"-close %s\n",(xorriso->do_close ? "on" : "off")); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= !xorriso->do_dummy; + sprintf(line,"-dummy %s\n",(xorriso->do_dummy ? "on" : "off")); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->speed==0); + sprintf(line,"-speed %dkB/s\n", xorriso->speed); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->do_stream_recording==0); + sprintf(line,"-stream_recording %s\n", + xorriso->do_stream_recording ? "on" : "off"); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->fs==4*512); + if((xorriso->fs/512)*512==xorriso->fs) + sprintf(line,"-fs %dm\n", xorriso->fs/512); + else + sprintf(line,"-fs %dk\n", xorriso->fs*2); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->padding==300*1024); + sprintf(line,"-padding %dk\n", xorriso->padding/1024); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (strcmp(xorriso->report_about_text,"UPDATE")==0); + sprintf(line,"-report_about %s\n",xorriso->report_about_text); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->session_logfile[0]==0); + sprintf(line,"-session_log %s\n", + Text_shellsafe(xorriso->session_logfile,sfe,0)); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (xorriso->pacifier_style==0); + sprintf(line,"-pacifier '%s'\n", + xorriso->pacifier_style==1 ? "mkisofs" : + xorriso->pacifier_style==2 ? "cdrecord" : "xorriso"); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (strcmp(xorriso->return_with_text,"SORRY")==0 && + xorriso->return_with_value==32); + sprintf(line,"-return_with %s %d\n", + xorriso->return_with_text, xorriso->return_with_value); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= (strcmp(xorriso->abort_on_text,"FATAL")==0); + sprintf(line,"-abort_on %s\n",xorriso->abort_on_text); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + if(xorriso->status_history_max!=Xorriso_status_history_maX || !no_defaults) { + sprintf(line,"-status_history_max %d\n",xorriso->status_history_max); + Xorriso_status_result(xorriso,filter,fp,flag&2); + } + +#ifdef Xorriso_with_readlinE + + if((flag&8) && xorriso->status_history_max>0) { + HIST_ENTRY **hl; + int hc,i; + + hl= history_list(); + if(hl!=NULL) { + for(hc= 0;hl[hc]!=NULL;hc++); + if(hc>0) + if(strcmp(hl[hc-1]->line,"-end")==0) + hc--; + if(hc>=xorriso->status_history_max) + i= hc-xorriso->status_history_max; + else + i= 0; + for(;i<hc;i++) { + sprintf(line,"-history %s\n",Text_shellsafe(hl[i]->line,sfe,0)); + Xorriso_status_result(xorriso,filter,fp,flag&2); + } + } + } + +#endif /* Xorriso_with_readlinE */ + + is_default= (xorriso->toc_emulation_flag == 0); + sprintf(line,"-rom_toc_scan %s%s\n", + xorriso->toc_emulation_flag & 1 ? "on" : "off", + xorriso->toc_emulation_flag & 2 ? ":emul_off" : ""); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso, filter, fp, flag & 2); + + adr_mode= xorriso->image_start_mode & 0xffff; + if(adr_mode>=0 && adr_mode<=max_load_mode) { + is_default= (adr_mode==0); + sprintf(line,"-load %s ", load_names[adr_mode]); + if(adr_mode==0) + sprintf(line+strlen(line),"''\n"); + else if(adr_mode>=1 && adr_mode<=3) + sprintf(line+strlen(line),"%s\n", xorriso->image_start_value); + else + sprintf(line+strlen(line),"%s\n", + Text_shellsafe(xorriso->image_start_value, sfe, 0)); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + } + + is_default= (xorriso->grow_blindly_msc2<0); + sprintf(sfe, "%d", xorriso->grow_blindly_msc2); + sprintf(line,"-grow_blindly %s\n", + xorriso->grow_blindly_msc2 < 0 ? "off" : sfe); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + Xorriso_get_local_charset(xorriso, &local_charset, 0); + nl_charset= nl_langinfo(CODESET); + is_default= (strcmp(local_charset, nl_charset) == 0); + sprintf(line, "-local_charset %s\n", Text_shellsafe(local_charset, sfe, 0)); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso, filter, fp, flag & 2); + + is_default= (xorriso->out_charset == NULL && xorriso->in_charset == NULL); + in_pt= ""; + if(xorriso->in_charset != NULL) + in_pt= xorriso->in_charset; + out_pt= ""; + if(xorriso->out_charset != NULL) + out_pt= xorriso->out_charset; + do_single= 0; + if(filter != NULL) + if(strncmp(filter, "-in_charset", 11) == 0 || + strncmp(filter, "-out_charset", 12) == 0) + do_single= 1; + if(strcmp(in_pt, out_pt) == 0 && !do_single) { + sprintf(line, "-charset %s\n", Text_shellsafe(in_pt, sfe, 0)); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso, filter, fp, flag & 2); + } else { + sprintf(line, "-in_charset %s\n", Text_shellsafe(in_pt, sfe, 0)); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso, filter, fp, flag & 2); + sprintf(line, "-out_charset %s\n", Text_shellsafe(out_pt, sfe, 0)); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso, filter, fp, flag & 2); + } + + is_default= (xorriso->assert_volid[0] == 0); + sprintf(line, "-assert_volid "); + Text_shellsafe(xorriso->assert_volid, line, 1); + strcat(line, " "); + Text_shellsafe(xorriso->assert_volid_sev, line, 1); + strcat(line, "\n"); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default= 1; + if(xorriso->drive_blacklist != NULL || xorriso->drive_whitelist != NULL || + xorriso->drive_greylist == NULL) + is_default= 0; + if(xorriso->drive_greylist != NULL) { + if(strcmp(Xorriso_get_pattern(xorriso, xorriso->drive_greylist, 0, 0), + "/dev") != 0) + is_default= 0; + if(Xorriso_get_pattern(xorriso, xorriso->drive_greylist, 1, 0) != NULL) + is_default= 0; + } + if(!(is_default && no_defaults)) { + for(s= xorriso->drive_blacklist; s != NULL; s= Xorriso_lst_get_next(s, 0)) { + sprintf(line, "-drive_class 'banned' %s\n", + Text_shellsafe(Xorriso_lst_get_text(s, 0), sfe, 0)); + Xorriso_status_result(xorriso,filter,fp,flag&2); + } + for(s= xorriso->drive_greylist; s != NULL; s= Xorriso_lst_get_next(s, 0)) { + sprintf(line, "-drive_class 'risky' %s\n", + Text_shellsafe(Xorriso_lst_get_text(s, 0), sfe, 0)); + Xorriso_status_result(xorriso,filter,fp,flag&2); + } + for(s= xorriso->drive_whitelist; s != NULL; s= Xorriso_lst_get_next(s, 0)) { + sprintf(line, "-drive_class 'harmless' %s\n", + Text_shellsafe(Xorriso_lst_get_text(s, 0), sfe, 0)); + Xorriso_status_result(xorriso,filter,fp,flag&2); + } + } + + do_single= 0; + if(filter != NULL) + if(strncmp(filter, "-indev", 6) == 0 || + strncmp(filter, "-outdev", 7) == 0) + do_single= 1; + if(strcmp(xorriso->indev, xorriso->outdev) == 0 && !do_single) { + sprintf(line,"-dev %s\n", Text_shellsafe(xorriso->indev,sfe,0)); + Xorriso_status_result(xorriso,filter,fp,flag&2); + } else { + sprintf(line,"-indev %s\n", Text_shellsafe(xorriso->indev,sfe,0)); + Xorriso_status_result(xorriso,filter,fp,flag&2); + sprintf(line,"-outdev %s\n", Text_shellsafe(xorriso->outdev,sfe,0)); + Xorriso_status_result(xorriso,filter,fp,flag&2); + } + + return(1); +} + + +/* @param flag bit2= this is a disk_pattern + @return <=0 failure , 1 pattern ok , 2 pattern needed prepended wd */ +int Xorriso_prepare_expansion_pattern(struct XorrisO *xorriso, char *pattern, + int flag) +{ + int ret, prepwd= 0; + + ret= Xorriso_prepare_regex(xorriso, pattern, 1|2|(flag&4)); + if(ret==2) { + ret= Xorriso_prepare_regex(xorriso, pattern, flag&4); + prepwd= 1; + } + if(ret<=0) { + sprintf(xorriso->info_text, + "Cannot compile pattern to regular expression: %s", pattern); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + return(1+prepwd); +} + + +/* @param flag bit0= count results rather than storing them + bit1= unexpected change of number is a FATAL event + @return <=0 error , 1 is root (end processing) , + 2 is not root (go on processing) +*/ +int Xorriso_check_for_root_pattern(struct XorrisO *xorriso, + int *filec, char **filev, int count_limit, off_t *mem, int flag) +{ + if(xorriso->re_fill!=0) + return(2); + /* This is the empty pattern representing root */ + if(flag&1) { + (*filec)++; + (*mem)+= 8; + } else { + if(*filec >= count_limit) { + sprintf(xorriso->info_text, + "Number of matching files changed unexpectedly (> %d)", + count_limit); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, + (flag&2 ? "FATAL" : "WARNING"), 0); + return(flag&2 ? -1 : 0); + } + filev[*filec]= strdup("/"); + if(filev[*filec]==NULL) { + Xorriso_no_pattern_memory(xorriso, (off_t) 2, 0); + return(-1); + } + (*filec)++; + } + return(1); +} + + +/* @param flag bit0= prepend wd only if name does not begin by '/' + bit1= normalize image path + bit2= prepend wd (automatically done if wd[0]!=0) + bit3= (with bit1) this is an address in the disk world +*/ +int Xorriso_make_abs_adr(struct XorrisO *xorriso, char *wd, char *name, + char adr[], int flag) +{ + char norm_adr[SfileadrL]; + int ret; + + if((wd[0]!=0 || (flag&4)) && !((flag&1) && name[0]=='/')) { + if(strlen(wd)+1>=SfileadrL) + goto much_too_long; + strcpy(adr, wd); + if(name[0]) + if(Sfile_add_to_path(adr, name, 0)<=0) { +much_too_long:; + Xorriso_much_too_long(xorriso, (int) (strlen(adr)+strlen(name)+1), 2); + return(0); + } + } else { + if(strlen(name)+1>=SfileadrL) + goto much_too_long; + strcpy(adr, name); + } + if(flag&2) { + ret= Xorriso_normalize_img_path(xorriso, "", adr, norm_adr, + 1|2|((flag&8)>>1)); + if(ret<=0) + return(ret); + if(norm_adr[0]==0) + strcpy(norm_adr, "/"); + strcpy(adr, norm_adr); + } + return(1); +} + + +/* + @param result Bitfield indicationg type of mismatch + bit11= cannot open regular disk file + bit12= cannot open iso file + bit13= early eof of disk file + bit14= early eof of iso file + bit15= content bytes differ + @param flag bit0= mtimes of both file objects are equal + bit29= do not issue pacifier messages + bit31= do not issue result messages + @return >0 ok , <=0 error +*/ +int Xorriso_compare_2_contents(struct XorrisO *xorriso, char *common_adr, + char *disk_adr, off_t disk_size, + off_t offset, off_t bytes, + char *iso_adr, off_t iso_size, + int *result, int flag) +{ + int fd1= -1, ret, r1, r2, done, wanted, i, was_error= 0; + void *stream2= NULL; + off_t r1count= 0, r2count= 0, diffcount= 0, first_diff= -1; + char *respt, buf1[32*1024], buf2[32*1024], offset_text[80]; + + respt= xorriso->result_line; + + fd1= open(disk_adr, O_RDONLY); + if(fd1==-1) { + sprintf(respt, "- %s (DISK) : cannot open() : %s\n", + disk_adr, strerror(errno)); +cannot_address:; + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + (*result)|= 2048; + return(0); + } + if(offset>0) + if(lseek(fd1, offset, SEEK_SET)==-1) { + sprintf(respt, "- %s (DISK) : cannot lseek(%.f) : %s\n", + disk_adr, (double) offset, strerror(errno)); + close(fd1); + goto cannot_address; + } + + ret= Xorriso_iso_file_open(xorriso, iso_adr, NULL, &stream2, 0); + if(ret<=0) { + sprintf(respt, "- %s (ISO) : cannot open() file in ISO image\n", iso_adr); + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + close(fd1); + (*result)|= 4096; + return(0); + } + + done= 0; + while(!done) { + + wanted= sizeof(buf1); + if(r1count+offset+wanted>disk_size) + wanted= disk_size-r1count-offset; + if(r1count+wanted>bytes) + wanted= bytes-r1count; + r1= 0; + while(wanted>0) { + ret= read(fd1, buf1, wanted); + if(ret<=0) + break; + wanted-= ret; + r1+= ret; + } + + wanted= sizeof(buf2); + if(r2count+wanted>iso_size) + wanted= iso_size-r2count; +/* + if(r2count+wanted>bytes) + wanted= bytes-r2count; +*/ + if(wanted>0) + r2= Xorriso_iso_file_read(xorriso, stream2, buf2, wanted, 0); + else + r2= 0; + + if(r1<0 || r2<0) + was_error= 1; + + if(r1<=0 && r2<=0) + break; + if(r1<=0) { + if(r1<0) + r1= 0; + if(disk_size > r1count + r1 + offset) { + sprintf(respt, "- %s (DISK) : early EOF after %.f bytes\n", + disk_adr, (double) r1count); + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + (*result)|= 8196; + } + (*result)|= (1<<15); + } + r1count+= r1; + if(r2<=0 || r2<r1) { + if(r2<0) + r2= 0; + if(iso_size > r2count + r2) { + sprintf(respt, "- %s (ISO) : early EOF after %.f bytes\n", + iso_adr, (double) r2count); + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + (*result)|= (1<<14); + } + (*result)|= (1<<15); + done= 1; + } + if(r2>r1) { + if(disk_size > r1count + r1 + offset) { + sprintf(respt, "- %s (DISK) : early EOF after %.f bytes\n", + disk_adr, (double) r1count); + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + (*result)|= 8196; + } + (*result)|= (1<<15); + done= 1; + } + r2count+= r2; + if(r1>r2) + r1= r2; + for(i= 0; i<r1; i++) { + if(buf1[i]!=buf2[i]) { + if(first_diff<0) + first_diff= i; + diffcount++; + } + } + if(!(flag&(1<<29))) { + xorriso->pacifier_count+= r1; + xorriso->pacifier_byte_count+= r1; + if(flag&(1<<31)) + Xorriso_pacifier_callback(xorriso, "content bytes read", + xorriso->pacifier_count, 0, "", 0); + else + Xorriso_pacifier_callback(xorriso, "bytes", xorriso->pacifier_count, 0, + "", 1<<6); + } + } + if(diffcount>0 || r1count!=r2count) { + if(first_diff<0) + first_diff= (r1count>r2count ? r2count : r1count); + offset_text[0]= 0; + if(offset>0) + sprintf(offset_text, "%.f+", (double) offset); + sprintf(respt, "%s %s : differs by at least %.f bytes. First at %s%.f\n", + common_adr, (flag&1 ? "CONTENT": "content"), + (double) (diffcount + abs(r1count-r2count)), + offset_text, (double) first_diff); + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + (*result)|= (1<<15); + } + if(fd1!=-1) + close(fd1); + Xorriso_iso_file_close(xorriso, &stream2, 0); + if(was_error) + return(-1); + return(1); +} + + +/* + @param result Bitfield indicationg type of mismatch + bit0= disk_adr not existing + bit1= iso_adr not existing + bit2= access permissions + bit3= file type + bit4= user id + bit5= group id + bit6= minor, major with device file + bit7= size + bit8= mtime + bit9= atime + bit10= ctime + bit11= cannot open regular disk file + bit12= cannot open iso file + bit13= early eof of disk file + bit14= early eof of iso file + bit15= content bytes differ + bit16= symbolic link on disk pointing to dir, dir in iso + bit17= file chunks detected and compared + bit18= incomplete chunk collection encountered + @param flag bit0= compare atime + bit1= compare ctime + bit2= check only existence of both file objects + count one or both missing as "difference" + bit27= for Xorriso_path_is_excluded(): bit0 + bit28= examine eventual disk_path link target rather than link + bit29= do not issue pacifier messages + bit30= omit adr_common_tail in report messages + bit31= do not issue result messages + @return 1=files match properly , 0=difference detected , -1=error +*/ +int Xorriso_compare_2_files(struct XorrisO *xorriso, char *disk_adr, + char *iso_adr, char *adr_common_tail, + int *result, int flag) +{ + struct stat s1, s2, stbuf; + int ret, missing= 0, is_split= 0, i, was_error= 0; + char *respt; + char a[5*SfileadrL], sfe[5*SfileadrL]; + char ttx1[40], ttx2[40]; + struct SplitparT *split_parts= NULL; + int split_count= 0; + + char part_path[SfileadrL], *part_name; + int partno, total_parts= 0; + off_t offset, bytes, total_bytes; + + *result= 0; + respt= xorriso->result_line; + + if(!(xorriso->disk_excl_mode&8)) { + ret= Xorriso_path_is_excluded(xorriso, disk_adr, 2 | !!(flag&(1<<27))); + if(ret>0) { + sprintf(respt , "? %s (DISK) : exluded by %s\n", + Text_shellsafe(disk_adr, sfe, 0), + (ret==1 ? "-not_paths" : "-not_leaf")); + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + missing= 1; + (*result)|= 1; + } + } + if(!missing) { + if(flag&(1<<28)) + ret= stat(disk_adr, &s1); + else + ret= lstat(disk_adr, &s1); + if(ret==-1) { + sprintf(respt , "? %s (DISK) : cannot lstat() : %s\n", + Text_shellsafe(disk_adr, sfe, 0), strerror(errno)); + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + missing= 1; + (*result)|= 1; + } + } + if(missing) + strcpy(a, "?"); + else + strcpy(a, Ftypetxt(s1.st_mode, 1)); + strcat(a, " "); + if(adr_common_tail[0]) + strcat(a, Text_shellsafe(adr_common_tail, sfe, 0)); + else { + Text_shellsafe(disk_adr, a+strlen(a), 0); + strcat(a, " (DISK)"); +/* + strcat(a, "'.'"); +*/ + } + strcat(a, " :"); + if(flag&(1<<30)) + a[0]= 0; + + ret= Xorriso_iso_lstat(xorriso, iso_adr, &s2, 0); + if(ret<0) { + sprintf(respt, "? %s (ISO) : cannot find this file in ISO image\n", + Text_shellsafe(iso_adr, sfe, 0)); + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + missing= 1; + (*result)|= 2; + } + + if((flag&4)||missing) + {ret= !missing; goto ex;} + + + /* Splitfile parts */ + if((S_ISREG(s1.st_mode) || S_ISBLK(s1.st_mode)) && S_ISDIR(s2.st_mode)) { + is_split= Xorriso_identify_split(xorriso, iso_adr, NULL, &split_parts, + &split_count, &s2, 0); + if(is_split>0) + (*result)|= (1<<17); + else + is_split= 0; + } + + /* Attributes */ + if(s1.st_mode != s2.st_mode) { + if((s1.st_mode&~S_IFMT)!=(s2.st_mode&~S_IFMT)) { + sprintf(respt, "%s st_mode : %7.7o <> %7.7o\n", + a, s1.st_mode, s2.st_mode); + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + (*result)|= 4; + } + if((s1.st_mode&S_IFMT)!=(s2.st_mode&S_IFMT)) { + sprintf(respt, "%s type : %s <> %s\n", + a, Ftypetxt(s1.st_mode, 0), Ftypetxt(s2.st_mode, 0)); + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + (*result)|= 8; + if((s1.st_mode&S_IFMT) == S_IFLNK) { + /* check whether link target type matches */ + ret= stat(disk_adr, &stbuf); + if(ret!=-1) + if(S_ISDIR(stbuf.st_mode) && S_ISDIR(s2.st_mode)) + (*result)|= (1<<16); + } + } + } + if(s1.st_uid != s2.st_uid) { + sprintf(respt, "%s st_uid : %d <> %d\n", a, s1.st_uid, s2.st_uid); + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + (*result)|= 16; + } + if(s1.st_gid != s2.st_gid) { + sprintf(respt, "%s st_gid : %d <> %d\n", a, s1.st_gid, s2.st_gid); + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + (*result)|= 32; + } + if((S_ISCHR(s1.st_mode) && S_ISCHR(s2.st_mode)) || + (S_ISBLK(s1.st_mode) && S_ISBLK(s2.st_mode))) { + if(s1.st_rdev != s2.st_rdev) { + sprintf(respt, "%s %s st_rdev : %lu <> %lu\n", a, + (S_ISCHR(s1.st_mode) ? "S_IFCHR" : "S_IFBLK"), + (unsigned long) s1.st_rdev, (unsigned long) s1.st_rdev); + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + (*result)|= 64; + } + } + if(S_ISREG(s2.st_mode) && s1.st_size != s2.st_size) { + sprintf(respt, "%s st_size : %.f <> %.f diff= %.f\n", + a, (double) s1.st_size, (double) s2.st_size, + ((double) s1.st_size) - (double) s2.st_size); + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + (*result)|= 128; + } + if(s1.st_mtime != s2.st_mtime) { + sprintf(respt, "%s st_mtime : %s <> %s diff= %.f s\n", + a, Ftimetxt(s1.st_mtime, ttx1, 0), + Ftimetxt(s2.st_mtime, ttx2, 0), + ((double) s1.st_mtime) - (double) s2.st_mtime); + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + (*result)|= 256; + } + if(flag&1) { + if(s1.st_atime != s2.st_atime) { + sprintf(respt, "%s st_atime : %s <> %s diff= %.f s\n", + a, Ftimetxt(s1.st_atime, ttx1, 0), + Ftimetxt(s2.st_atime, ttx2, 0), + ((double) s1.st_atime) - (double) s2.st_atime); + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + (*result)|= 512; + } + } + if(flag&2) { + if(s1.st_ctime != s2.st_ctime) { + sprintf(respt, "%s st_ctime : %s <> %s diff= %.f s\n", + a, Ftimetxt(s1.st_ctime, ttx1, 0), + Ftimetxt(s2.st_ctime, ttx2, 0), + ((double) s1.st_ctime) - (double) s2.st_ctime); + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + (*result)|= 1024; + } + } + if(S_ISREG(s1.st_mode) && S_ISREG(s2.st_mode)) { + /* Content */ + if(is_split) { + for(i= 0; i<split_count; i++) { + Splitparts_get(split_parts, i, &part_name, &partno, &total_parts, + &offset, &bytes, &total_bytes, 0); + strcpy(part_path, iso_adr); + if(Sfile_add_to_path(part_path, part_name, 0)<=0) { + Xorriso_much_too_long(xorriso, strlen(iso_adr)+strlen(part_name)+1, + 2); + {ret= -1; goto ex;} + } + ret= Xorriso_iso_lstat(xorriso, part_path, &stbuf, 0); + if(ret<0) + continue; + ret= Xorriso_compare_2_contents(xorriso, a, disk_adr, s1.st_size, + offset, bytes, + part_path, stbuf.st_size, result, + (s1.st_mtime==s2.st_mtime) | (flag&((1<<29)|(1<<31)))); + if(ret<0) + was_error= 1; + } + if(total_parts>0 && split_count!=total_parts) { + sprintf(xorriso->info_text, + "- %s/* (ISO) : Not all split parts present (%d of %d)\n", + iso_adr, split_count, total_parts); + if(!(flag&(1<<31))) + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 1); + (*result)|= 1<<18; + } + } else { + ret= Xorriso_compare_2_contents(xorriso, a, disk_adr, s1.st_size, + (off_t) 0, s1.st_size, + iso_adr, s2.st_size, result, + (s1.st_mtime==s2.st_mtime) | (flag&((1<<29)|(1<<31)))); + if(ret<0) + was_error= 1; + } + + } + if(was_error) + ret= -1; + else + ret= (((*result)&~((1<<17)|(1<<18)))==0); +ex:; + if(split_parts!=NULL) + Splitparts_destroy(&split_parts, split_count, 0); + return(ret); +} + + +/* @param boss_iter Opaque handle to be forwarded to actions in ISO image + Set to NULL if calling this function from outside ISO world + @param flag bit0= update rather than compare + bit1= find[ix] is in recursion + @return <=0 error, 1= ok , 2= iso_path was deleted + 3=ok, do not dive into directory (e.g. because it is a split file) +*/ +int Xorriso_find_compare(struct XorrisO *xorriso, void *boss_iter, + char *iso_path, char *iso_prefix, char *disk_prefix, + int flag) +{ + int ret, result, uret, follow_links, deleted= 0; + char disk_path[SfileadrL], adrc[SfileadrL]; + + if(strncmp(iso_path, iso_prefix, strlen(iso_prefix))!=0) + return(-1); + if(strlen(disk_prefix)+strlen(iso_path)-strlen(iso_prefix)>=SfileadrL) + return(-1); + if(iso_path[strlen(iso_prefix)]=='/') + strcpy(adrc, iso_path+strlen(iso_prefix)+1); + else + strcpy(adrc, iso_path+strlen(iso_prefix)); + + ret= Xorriso_make_abs_adr(xorriso, disk_prefix, adrc, disk_path, 4|8); + if(ret<=0) + return(ret); + + /* compare exclusions against disk_path resp. leaf name */ + if(xorriso->disk_excl_mode&8) + ret= Xorriso_path_is_excluded(xorriso, disk_path, !(flag&2)); + else + ret= 0; + if(ret<0) + return(ret); + if(ret>0) + return(3); + + follow_links= (xorriso->do_follow_links || + (xorriso->do_follow_param && !(flag&2))) <<28; + ret= Xorriso_compare_2_files(xorriso, disk_path, iso_path, adrc, &result, + 2 | follow_links | ((!(flag&2))<<27) | ((flag&1)<<31)); + /* was once: | ((!(flag&1))<<29) */ + if(ret<xorriso->find_compare_result) + xorriso->find_compare_result= ret; + if(flag&1) { + if(ret<=0) { + if(ret<0) + if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0) + return(ret); + uret= Xorriso_update_interpreter(xorriso, boss_iter, result, + disk_path, iso_path, (flag&2)<<1); + if(uret<=0) + ret= 0; + if(uret==2) + deleted= 1; + } + } + if(ret<0) + return(ret); + if(deleted) + return(2); + if(result&(1<<17)) + return(3); + return(ret); +} + + +/* @param flag bit0= count result rather than storing it + bit1= unexpected change of number is a FATAL event +*/ +int Xorriso_register_matched_adr(struct XorrisO *xorriso, + char *adr, int count_limit, + int *filec, char **filev, off_t *mem, int flag) +{ + int l; + + if(flag&1) { + (*filec)++; + l= strlen(adr)+1; + (*mem)+= sizeof(char *)+l; + if(l % sizeof(char *)) + (*mem)+= sizeof(char *)-(l % sizeof(char *)); + } else { + if(*filec >= count_limit) { + sprintf(xorriso->info_text, + "Number of matching files changed unexpectedly (> %d)", + count_limit); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, + (flag&2 ? "FATAL" : "WARNING"), 0); + return(flag&2 ? -1 : 0); + } + filev[*filec]= strdup(adr); + if(filev[*filec]==NULL) { + Xorriso_no_pattern_memory(xorriso, (off_t) (strlen(adr)+1), 0); + return(-1); + } + (*filec)++; + } + return(1); +} + + +/* @param flag bit0= count results rather than storing them + bit1= this is a recursion + bit2= prepend wd (automatically done if wd[0]!=0) + @return <=0 error , 1 ok , 2 could not open directory +*/ +int Xorriso_obtain_pattern_files_x( + struct XorrisO *xorriso, char *wd, char *dir_adr, + int *filec, char **filev, int count_limit, off_t *mem, + int *dive_count, int flag) +{ + int ret, failed_at, follow_mount, follow_links; + struct DirseQ *dirseq= NULL; + struct stat stbuf; + dev_t dir_dev; + char *path; + char *adr= NULL, *name= NULL, *path_data= NULL; + + adr= malloc(SfileadrL); + name= malloc(SfileadrL); + path_data= malloc(SfileadrL); + if(adr==NULL || name==NULL || path_data==NULL) { + Xorriso_no_malloc_memory(xorriso, &adr, 0); + {ret= -1; goto ex;} + } + follow_mount= (xorriso->do_follow_mount || xorriso->do_follow_pattern); + follow_links= (xorriso->do_follow_links || xorriso->do_follow_pattern); + if(!(flag&2)) + *dive_count= 0; + else + (*dive_count)++; + + ret= Xorriso_check_for_root_pattern(xorriso, filec, filev, count_limit, + mem, flag&1); + if(ret!=2) + goto ex; + + if(lstat(dir_adr, &stbuf)==-1) + {ret= 2; goto ex;} + dir_dev= stbuf.st_dev; + if(S_ISLNK(stbuf.st_mode)) { + if(stat(dir_adr, &stbuf)==-1) + {ret= 2; goto ex;} + if(dir_dev != stbuf.st_dev && !follow_mount) + {ret= 2; goto ex;} + } + ret= Dirseq_new(&dirseq, dir_adr, 1); + if(ret<0) { + sprintf(xorriso->info_text, "Cannot obtain disk directory iterator"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + {ret= -1; goto ex;} + } + if(ret==0) + {ret= 2; goto ex;} + + while(1) { + ret= Dirseq_next_adr(dirseq,name,0); + if(ret==0) + break; + if(ret<0) { + sprintf(xorriso->info_text,"Failed to obtain next directory entry"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + {ret= -1; goto ex;} + } + + ret= Xorriso_make_abs_adr(xorriso, wd, name, adr, flag&4); + if(ret<=0) + goto ex; + + ret= Xorriso_regexec(xorriso, adr, &failed_at, 1); + if(ret>0) { /* no match */ + if(failed_at <= *dive_count) /* no hope for a match */ + continue; + path= adr; + if(adr[0]!='/') { + path= path_data; + ret= Xorriso_make_abs_adr(xorriso, xorriso->wdx, adr, path, 1|4); + if(ret<=0) + goto ex; + } + + if(follow_links) + ret= stat(path,&stbuf); + else + ret= lstat(path,&stbuf); + if(ret==-1) + continue; + if(!S_ISDIR(stbuf.st_mode)) + continue; + if(dir_dev != stbuf.st_dev && !follow_mount) + continue; + + /* dive deeper */ + ret= Xorriso_obtain_pattern_files_x(xorriso, adr, path, + filec, filev, count_limit, mem, dive_count, flag|2); + if(ret<=0) + goto ex; + } else { + ret= Xorriso_register_matched_adr(xorriso, adr, count_limit, + filec, filev, mem, flag&1); + if(ret<0) + goto ex; + if(ret==0) + break; + } + } + ret= 1; +ex:; + if(adr!=NULL) + free(adr); + if(name!=NULL) + free(name); + if(path_data!=NULL) + free(path_data); + Dirseq_destroy(&dirseq,0); + if(flag&2) + (*dive_count)--; + return(ret); +} + + +int Xorriso_eval_nonmatch(struct XorrisO *xorriso, char *pattern, + int *nonconst_mismatches, off_t *mem, int flag) +{ + int k,l; + + /* Is this a constant pattern ? */ + for(k= 0; k<xorriso->re_fill; k++) { + if(xorriso->re_constants[k]==NULL) + break; + if(xorriso->re_constants[k][0]==0) + break; + } + if(k<xorriso->re_fill) + (*nonconst_mismatches)++; /* it is not */ + + l= strlen(pattern)+1; + (*mem)+= sizeof(char *)+l; + if(l % sizeof(char *)) + (*mem)+= sizeof(char *)-(l % sizeof(char *)); + return(1); +} + + +/* @param flag bit0= a match count !=1 is a SORRY event + bit1= a match count !=1 is a FAILURE event +*/ +int Xorriso_check_matchcount(struct XorrisO *xorriso, + int count, int nonconst_mismatches, int num_patterns, + char **patterns, int flag) +{ + char sfe[5*SfileadrL]; + + if((flag&1) && (count!=1 || nonconst_mismatches)){ + if(count-nonconst_mismatches>0) + sprintf(xorriso->info_text, + "Pattern match with more than one file object"); + else + sprintf(xorriso->info_text, "No pattern match with any file object"); + if(num_patterns==1) + sprintf(xorriso->info_text+strlen(xorriso->info_text), ": %s", + Text_shellsafe(patterns[0], sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, + (flag&2 ? "FAILURE" : "SORRY"), 0); + return(0); + } + return(1); +} + + +int Xorriso_no_pattern_memory(struct XorrisO *xorriso, off_t mem, int flag) +{ + char mem_text[80]; + + Sfile_scale((double) mem, mem_text,5,1e4,1); + sprintf(xorriso->info_text, + "Cannot allocate enough memory (%s) for pattern expansion", + mem_text); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(1); +} + + +int Xorriso_no_malloc_memory(struct XorrisO *xorriso, char **to_free, int flag) +{ + if(to_free!=NULL) + if(*to_free!=NULL) { + /* Eventual memory sacrifice to get on going */ + free(*to_free); + *to_free= NULL; + } + sprintf(xorriso->info_text, "Out of virtual memory"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "ABORT", 0); + return(1); +} + + +int Xorriso_alloc_pattern_mem(struct XorrisO *xorriso, off_t mem, + int count, char ***filev, int flag) +{ + char mem_text[80], limit_text[80]; + + Sfile_scale((double) mem, mem_text,5,1e4,0); + sprintf(xorriso->info_text, + "Temporary memory needed for pattern expansion : %s", mem_text); + if(!(flag&1)) + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + if(mem > xorriso->temp_mem_limit) { + Sfile_scale((double) xorriso->temp_mem_limit, limit_text,5,1e4,1); + sprintf(xorriso->info_text, + "List of matching file addresses exceeds -temp_mem_limit (%s > %s)", + mem_text, limit_text); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + + (*filev)= (char **) calloc(count, sizeof(char *)); + if(*filev==NULL) { + Xorriso_no_pattern_memory(xorriso, mem, 0); + return(-1); + } + return(1); +} + + +/* @param flag bit0= a match count !=1 is a FAILURE event + bit1= with bit0 tolerate 0 matches if pattern is a constant +*/ +int Xorriso_expand_disk_pattern(struct XorrisO *xorriso, + int num_patterns, char **patterns, int extra_filec, + int *filec, char ***filev, off_t *mem, int flag) +{ + int ret, count= 0, abs_adr= 0, i, was_count, was_filec; + int nonconst_mismatches= 0, dive_count= 0; + char sfe[5*SfileadrL], dir_adr[SfileadrL]; + + *filec= 0; + *filev= NULL; + + xorriso->search_mode= 3; + xorriso->structured_search= 1; + + for(i= 0; i<num_patterns; i++) { + + ret= Xorriso_prepare_expansion_pattern(xorriso, patterns[i], 4); + if(ret<=0) + return(ret); + if(ret==2) + abs_adr= 4; + + if(patterns[i][0]=='/' || abs_adr) { + strcpy(dir_adr, "/"); + abs_adr= 4; + } else { + strcpy(dir_adr, xorriso->wdx); + if(dir_adr[0]==0) + strcpy(dir_adr, "/"); + ret= Sfile_type(dir_adr, 1|4); + if(ret!=2) { + Xorriso_msgs_submit(xorriso, 0, dir_adr, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, + "Address set by -cdx is not a directory: %s", + Text_shellsafe(dir_adr, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + } + + /* count the matches */ + was_count= count; + ret= Xorriso_obtain_pattern_files_x(xorriso, "", dir_adr, &count, NULL, 0, + mem, &dive_count, 1 | abs_adr); + if(ret<=0) + goto ex; + if(was_count==count && strcmp(patterns[i],"*")!=0 && (flag&3)!=1) { + count++; + ret= Xorriso_eval_nonmatch(xorriso, patterns[i], + &nonconst_mismatches, mem, 0); + if(ret<=0) + goto ex; + } + } + + ret= Xorriso_check_matchcount(xorriso, count, nonconst_mismatches, + num_patterns, patterns, (flag&1)|2); + if(ret<=0) + goto ex; + + count+= extra_filec; + mem+= extra_filec*sizeof(char *); + + if(count<=0) + {ret= 0; goto ex;} + + ret= Xorriso_alloc_pattern_mem(xorriso, *mem, count, filev, 0); + if(ret<=0) + goto ex; + + /* now store addresses */ + for(i= 0; i<num_patterns; i++) { + + ret= Xorriso_prepare_expansion_pattern(xorriso, patterns[i], 4); + if(ret<=0) + return(ret); + + if(patterns[i][0]=='/' || abs_adr) { + strcpy(dir_adr, "/"); + abs_adr= 4; + } else { + strcpy(dir_adr, xorriso->wdx); + if(dir_adr[0]==0) + strcpy(dir_adr, "/"); + } + + was_filec= *filec; + ret= Xorriso_obtain_pattern_files_x(xorriso, "", dir_adr, filec, *filev, + count, mem, &dive_count, abs_adr); + if(ret<=0) + goto ex; + + if(was_filec == *filec && strcmp(patterns[i],"*")!=0) { + (*filev)[*filec]= strdup(patterns[i]); + if((*filev)[*filec]==NULL) { + (*mem)= strlen(patterns[i])+1; + Xorriso_no_pattern_memory(xorriso, *mem, 0); + ret= -1; goto ex; + } + (*filec)++; + } + } + + ret= 1; +ex:; + if(ret<=0) { + if(filev!=NULL) + Sfile_destroy_argv(&count, filev, 0); + *filec= 0; + } + return(ret); +} + + +/* @param flag bit0= command without pattern capability + bit1= disk_pattern rather than iso_rr_pattern +*/ +int Xorriso_warn_of_wildcards(struct XorrisO *xorriso, char *path, int flag) +{ + if(strchr(path,'*')!=NULL || strchr(path,'?')!=NULL || + strchr(path,'[')!=NULL) { + if(flag&1) { + sprintf(xorriso->info_text, + "Pattern expansion of wildcards \"*?[\" does not apply to this command"); + } else { + sprintf(xorriso->info_text, + "Pattern expansion of wildcards \"*?[\" is disabled by command %s", + (flag&2) ? "-disk_pattern or -pathspecs" : "-iso_rr_pattern"); + } + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); + sprintf(xorriso->info_text,"Pattern seen: %s\n", path); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); + return(1); + } + return(0); +} + + +/* @param flag bit0= do not warn of wildcards + bit1= these are disk_paths +*/ +int Xorriso_end_idx(struct XorrisO *xorriso, + int argc, char **argv, int idx, int flag) +{ + int i, warned= 0; + + for(i= idx; i<argc; i++) { + if(strcmp(argv[i], xorriso->list_delimiter)==0) + break; + if(!((flag&1) || warned)) + warned= Xorriso_warn_of_wildcards(xorriso, argv[i], flag&2); + } + return(i); +} + + +/* Returns a vector of strings which belong to an open ended arg list. + If expansion is enabled, the vector might be allocated, else it is + a pointer into the argv input vector. + Thus the release of that memory is an expert task to be done by this + function only. Use bit8 for that. With bit8 parameter argc MUST be the + same value as with the call which might have allocated memory. + @param xorriso The environment object + @param argc Length of argv + @param argv The vector with arguments, eventual list_delimiter ("--") + and then eventual unrelated words + @param idx Start index in argv of the argument list + @param optc Length of the effective possibly expanded option vector + @param optv The option vector. Maybe a pointer into argv or maybe + an own allocated vector. + @param flag bit0= do not warn of wildcards + bit1= these are disk_paths + bit2= never expand wildcards + bit3= do not expand last argument + bit4= ignore last argument + bit5= demand exactly one match + bit6= with bit5 allow 0 matches if pattern is a constant + bit8= free the eventually allocated sub_vector +*/ +int Xorriso_opt_args(struct XorrisO *xorriso, char *cmd, + int argc, char **argv, int idx, + int *end_idx, int *optc, char ***optv, int flag) +{ + int i, do_expand, nump, was_empty= 0, filec= 0, ret; + char **filev= NULL, **patterns= NULL; + off_t mem= 0; + + if(flag&2) + do_expand= xorriso->do_disk_pattern==1 && !(flag&4); + else + do_expand= xorriso->do_iso_rr_pattern==1 && !(flag&4); + if(flag&256) { + if(*optv<argv || *optv>=argv+argc) + Sfile_destroy_argv(optc, optv, 0); + return(1); + } + if(idx>=argc) { + *end_idx= argc; + *optc= 0; + *optv= NULL; + sprintf(xorriso->info_text, "%s : Not enough arguments given", cmd); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + *end_idx= Xorriso_end_idx(xorriso, argc, argv, idx, + ((flag&1) || do_expand) | (flag&2)); + if(*end_idx<0) + return(*end_idx); + if((flag&16) && (*end_idx)>idx) + (*end_idx)--; + *optc= *end_idx - idx; + *optv= argv+idx; + if(*optc<=0 || !do_expand) + return(1); + patterns= calloc(*optc, sizeof(char *)); + if(patterns==NULL) { +no_memory:; + sprintf(xorriso->info_text, + "%s : Cannot allocate enough memory for pattern expansion", cmd); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + {ret= -1; goto ex;} + } + nump= 0; + if(flag&8) { + was_empty= 1; + mem+= strlen(argv[idx + *optc - 1])+1+sizeof(char *); + } + for(i= 0; i<*optc-!!(flag&8); i++) { + if(argv[i + idx][0]==0) { + was_empty++; + mem+= sizeof(char *); /* as upper limit for size of an empty string */ + continue; + } + patterns[nump++]= argv[i + idx]; + } + if(nump<=0) { /* Only empty texts. May the caller get happy with them. */ + free(patterns); + return(1); + } + if(flag&2) + ret= Xorriso_expand_disk_pattern(xorriso, nump, patterns, was_empty, + &filec, &filev, &mem, (flag>>5)&3); + else + ret= Xorriso_expand_pattern(xorriso, nump, patterns, was_empty, + &filec, &filev, &mem, (flag>>5)&3); + if(ret<=0) + {ret= 0; goto ex;} + for(i= 0; i<was_empty; i++) { + if(i==was_empty-1 && (flag&8)) + filev[filec++]= strdup(argv[idx + *optc - 1]); + else + filev[filec++]= strdup(""); + if(filev[filec-1]==NULL) + goto no_memory; + } + +#ifdef Xorriso_verbous_pattern_expansioN +{ int l; + sprintf(xorriso->info_text, "Pattern expansion yields %d items:", filec); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + l= 0; + xorriso->info_text[0]= 0; + for(i= 0; i<filec; i++) { + l= strlen(xorriso->info_text); + if(l>0 && l+1+strlen(filev[i])>60) { + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + xorriso->info_text[0]= 0; + l= 0; + } + sprintf(xorriso->info_text+l, " %s", filev[i]); + } + l= strlen(xorriso->info_text); + if(l>0) + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); +} +#endif /* Xorriso_verbous_pattern_expansioN */ + + ret= 1; +ex:; + if(ret<=0) { + if(patterns!=NULL) + free((char *) patterns); + Sfile_destroy_argv(&filec, &filev, 0); + } else { + *optc= filec; + *optv= filev; + } + return(ret); +} + + +int Xorriso_get_problem_status(struct XorrisO *xorriso, char severity[80], + int flag) +{ + strcpy(severity, xorriso->problem_status_text); + return(xorriso->problem_status); +} + + +int Xorriso_set_problem_status(struct XorrisO *xorriso, char *severity, + int flag) +{ + char *sev_text= "ALL"; + int sev, ret; + + if(severity[0]) + sev_text= severity; + ret= Xorriso__text_to_sev(sev_text, &sev, 0); + if(ret<=0) + return(0); + xorriso->problem_status= sev; + strcpy(xorriso->problem_status_text, sev_text); + if(sev > xorriso->eternal_problem_status) { + xorriso->eternal_problem_status= sev; + strcpy(xorriso->eternal_problem_status_text, sev_text); + } + return(1); +} + + +/* @param flag bit0-7= purpose + 0= ERRFILE + 1= mark line (only to be put out if enabled) +*/ +int Xorriso_process_errfile(struct XorrisO *xorriso, + int error_code, char msg_text[], int os_errno, + int flag) +{ + char ttx[41]; + int purpose; + + if(strlen(msg_text)>SfileadrL) + return(-1); + + purpose= flag&255; + if(purpose==1 && !(xorriso->errfile_mode&1)) + return(2); + if(xorriso->errfile_fp!=NULL) { + if(purpose==1) + fprintf(xorriso->errfile_fp, "----------------- %s %s\n", + msg_text, Ftimetxt(time(0), ttx, 1)); + else + fprintf(xorriso->errfile_fp, "%s\n", msg_text); + fflush(xorriso->errfile_fp); + return(1); + } + if(xorriso->errfile_log[0]==0) + return(1); + if(strcmp(xorriso->errfile_log, "-")==0 || + strcmp(xorriso->errfile_log, "-R")==0) { + if(purpose==1) + sprintf(xorriso->result_line, "----------------- %s %s\n", + msg_text, Ftimetxt(time(0), ttx, 1)); + else + sprintf(xorriso->result_line, "%s\n", msg_text); + Xorriso_result(xorriso, 1); + return(1); + } + if(strcmp(xorriso->errfile_log, "-I")==0) { + if(purpose==1) + sprintf(xorriso->info_text, "ERRFILE_MARK=%s %s\n", + msg_text, Ftimetxt(time(0), ttx, 1)); + else + sprintf(xorriso->info_text, "ERRFILE=%s", msg_text); + Xorriso_info(xorriso, 0); + return(1); + } + return(2); +} + + +/* Note: It is ok to submit xorriso->info_text as msg_text here. */ +/* flag: + bit0= for Xorriso_info() : use pager (as with result) + bit1= for Xorriso_info() : permission to suppress output + bit2..5= name prefix + 0="xorriso" + 1="libisofs" + 2="libburn" + 3="libisoburn" + else: "" + bit6= append carriage return rather than line feed (if not os_errno) + bit7= perform Xorriso_process_msg_queues() first +*/ +int Xorriso_msgs_submit(struct XorrisO *xorriso, + int error_code, char msg_text[], int os_errno, + char severity[], int flag) +{ + int ret, lt, li, sev, i; + char *sev_text= "FATAL", prefix[80]; + static char pfx_list[20][16]= { + "xorriso : ", "libisofs: ", "libburn : ", "libisoburn: ", + "", "", "", "", "", "", "", "", "", "", "", "" }; + + if(flag&128) + Xorriso_process_msg_queues(xorriso, 0); + + if(strcmp(severity, "ERRFILE")==0) + Xorriso_process_errfile(xorriso, error_code, msg_text, os_errno, 0); + + /* Set problem status */ + ret= Xorriso__text_to_sev(severity, &sev, 0); + if(ret<=0) + Xorriso__text_to_sev(sev_text, &sev, 0); + else + sev_text= severity; + if(xorriso->problem_status<sev) { + xorriso->problem_status= sev; + strcpy(xorriso->problem_status_text, sev_text); + } + if(xorriso->eternal_problem_status<sev) { + xorriso->eternal_problem_status= sev; + strcpy(xorriso->eternal_problem_status_text, sev_text); + } + + /* Report problem event */ + if(sev<xorriso->report_about_severity && sev<xorriso->abort_on_severity) + return(2); + sprintf(prefix,"%s%s : ", pfx_list[(flag>>2)&15], sev_text); + li= strlen(prefix); + lt= strlen(msg_text); + if(lt>sizeof(xorriso->info_text)-li-2) + lt= sizeof(xorriso->info_text)-li-2; + if(msg_text==xorriso->info_text) { + for(i= lt; i>=0; i--) + msg_text[i+li]= msg_text[i]; + for(i=0; i<li; i++) + msg_text[i]= prefix[i]; + } else { + strcpy(xorriso->info_text, prefix); + strncpy(xorriso->info_text+li, msg_text, lt); + } + if((flag&64) && os_errno<=0) + xorriso->info_text[li+lt]= '\r'; + else + xorriso->info_text[li+lt]= '\n'; + xorriso->info_text[li+lt+1]= 0; + Xorriso_info(xorriso,4|(flag&3)); + if(os_errno>0) { + sprintf(xorriso->info_text, "%ssys : %s\n", + pfx_list[(flag>>2)&15], strerror(os_errno)); + Xorriso_info(xorriso,4|(flag&3)); + } + return(1); +} + + +/* To be used with isoburn_set_msgs_submit() +*/ +int Xorriso_msgs_submit_void(void *xorriso, + int error_code, char msg_text[], int os_errno, + char severity[], int flag) +{ + int ret; + + ret= Xorriso_msgs_submit((struct XorrisO *) xorriso, error_code, msg_text, + os_errno, severity, flag); + return(ret); +} + + +/** + @param flag bit0= do not issue own event messages + bit1= take xorriso->request_to_abort as reason for abort + @return Gives the advice: + 2= pardon was given, go on + 1= no problem, go on + 0= function failed but xorriso would not abort, go on + <0= do abort + -1 = due to problem_status + -2 = due to xorriso->request_to_abort +*/ +int Xorriso_eval_problem_status(struct XorrisO *xorriso, int ret, int flag) +{ + static int sev= 0; + if(sev==0) + Xorriso__text_to_sev("SORRY", &sev, 0); + + if((flag&2) && xorriso->request_to_abort) + return(-2); + + Xorriso_process_msg_queues(xorriso, 0); + if(ret>0 && xorriso->problem_status <= 0) + return(1); + + if(xorriso->problem_status < xorriso->abort_on_severity && + xorriso->problem_status > 0) { + if(xorriso->problem_status >= sev && !(flag&1)) { + sprintf(xorriso->info_text, + "xorriso : NOTE : Tolerated problem event of severity '%s'\n", + xorriso->problem_status_text); + Xorriso_info(xorriso, 0);/* submit not as problem event */ + } + ret= 2; + } else if(xorriso->problem_status > 0) { + sprintf(xorriso->info_text, + "xorriso : aborting : -abort_on '%s' encountered '%s'\n", + xorriso->abort_on_text, xorriso->problem_status_text); + if(!(flag&1)) + Xorriso_info(xorriso, 0);/* submit not as problem event */ + ret= -1; + } else if(ret>0) + ret= 1; + else + ret= 2; + return(ret); +} + + +int Xorriso_convert_uidstring(struct XorrisO *xorriso, char *uid_string, + uid_t *uid, int flag) +{ + double num; + char text[80]; + struct passwd *pwd; + + sscanf(uid_string, "%lf", &num); + sprintf(text,"%.f",num); + if(strcmp(text,uid_string)==0) { + *uid= num; + return(1); + } + pwd= getpwnam(uid_string); + if(pwd==NULL) { + sprintf(xorriso->info_text, "-uid: Not a known user: '%s'", uid_string); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + *uid= pwd->pw_uid; + return(1); +} + + +int Xorriso_convert_gidstring(struct XorrisO *xorriso, char *gid_string, + gid_t *gid, int flag) +{ + double num; + char text[80]; + struct group *grp; + + sscanf(gid_string, "%lf", &num); + sprintf(text,"%.f",num); + if(strcmp(text,gid_string)==0) { + *gid= num; + return(1); + } + grp= getgrnam(gid_string); + if(grp==NULL) { + sprintf(xorriso->info_text, "-gid: Not a known group: '%s'", gid_string); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + *gid= grp->gr_gid; + return(1); +} + + +int Xorriso_convert_modstring(struct XorrisO *xorriso, char *cmd, char *mode, + mode_t *mode_and, mode_t *mode_or, int flag) +{ + int who_val= 0; + char sfe[5*SfileadrL], *mpt, *vpt, *opt; + unsigned int num= 0; + mode_t mode_val,mask; + + *mode_and= ~0; + *mode_or= 0; + if(mode[0]=='0') { + *mode_and= 0; + sscanf(mode,"%o",&num); + *mode_or= num; + } else if(strchr(mode,'+')!=NULL || strchr(mode,'-')!=NULL + || strchr(mode,'=')!=NULL) { + /* [ugoa][+-][rwxst] */; + for(mpt= mode; mpt!=NULL; mpt= strchr(mpt, ',')) { + if(*mpt==',') + mpt++; + if(strlen(mpt)<2) + goto unrecognizable; + who_val= 0; + for(vpt= mpt; *vpt!='+' && *vpt!='-' && *vpt!='='; vpt++) { + if(*vpt=='u') + who_val|= 4; + else if(*vpt=='g') + who_val|= 2; + else if(*vpt=='o') + who_val|= 1; + else if(*vpt=='a') + who_val|= 7; + else + goto unrecognizable; + } + opt= vpt; + mode_val= 0; + for(vpt= opt+1; *vpt!=0 && *vpt!=','; vpt++) { + if(*vpt=='r') { + if(who_val&4) + mode_val|= S_IRUSR; + if(who_val&2) + mode_val|= S_IRGRP; + if(who_val&1) + mode_val|= S_IROTH; + } else if(*vpt=='w') { + if(who_val&4) + mode_val|= S_IWUSR; + if(who_val&2) + mode_val|= S_IWGRP; + if(who_val&1) + mode_val|= S_IWOTH; + } else if(*vpt=='x') { + if(who_val&4) + mode_val|= S_IXUSR; + if(who_val&2) + mode_val|= S_IXGRP; + if(who_val&1) + mode_val|= S_IXOTH; + } else if(*vpt=='s') { + if(who_val&4) + mode_val|= S_ISUID; + if(who_val&2) + mode_val|= S_ISGID; + } else if(*vpt=='t') { + if(who_val&1) + mode_val|= S_ISVTX; + } else + goto unrecognizable; + } + if(*opt=='+') { + (*mode_or)|= mode_val; + } else if(*opt=='=') { + mask= 0; + if(who_val&1) + mask|= S_IRWXO|S_ISVTX; + if(who_val&2) + mask|= S_IRWXG|S_ISGID; + if(who_val&4) + mask|= S_IRWXU|S_ISUID; + (*mode_and)&= ~(mask); + (*mode_or)= ((*mode_or) & ~mask) | mode_val; + } else if(*opt=='-') { + (*mode_or)&= ~mode_val; + (*mode_and)&= ~mode_val; + } + } + } else { +unrecognizable:; + sprintf(xorriso->info_text, + "%s: Unrecognizable or faulty permission mode %s\n", cmd, + Text_shellsafe(mode, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + return(1); +} + + +int Xorriso_convert_datestring(struct XorrisO *xorriso, char *cmd, + char *time_type, char *timestring, + int *t_type, time_t *t, int flag) +{ + int ret; + + if(strcmp(time_type, "a")==0) + (*t_type)|= 1; + else if(strcmp(time_type, "m")==0) + (*t_type)|= 4; + else if(strcmp(time_type, "b")==0) + (*t_type)|= 5; + else { + sprintf(xorriso->info_text, "%s: Unrecognized type '%s'", cmd, time_type); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + ret= Decode_timestring(timestring, t, 0); + if(ret<=0) { + sprintf(xorriso->info_text, "%s: Cannot decode timestring '%s'", cmd, + timestring); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + sprintf(xorriso->info_text, "Understanding timestring '%s' as: %s", + timestring, ctime(t)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + return(1); +} + + +/* @param flag bit0=path is in source filesystem , bit1= unconditionally */ +int Xorriso_much_too_long(struct XorrisO *xorriso, int len, int flag) +{ + if(len>=SfileadrL || (flag&2)) { + sprintf(xorriso->info_text, + "Path given for %s is much too long (%d)", + ((flag&1) ? "local filesystem" : "ISO image"), len); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + return(1); +} + + +int Xorriso_no_findjob(struct XorrisO *xorriso, char *cmd, int flag) +{ + sprintf(xorriso->info_text, "%s: cannot create find job object", cmd); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(1); +} + + +/* @param flag bit1= do not report memory usage as DEBUG +*/ +int Xorriso_check_temp_mem_limit(struct XorrisO *xorriso, off_t mem, int flag) +{ + char mem_text[80], limit_text[80]; + + Sfile_scale((double) mem, mem_text,5,1e4,0); + if(!(flag&2)) { + sprintf(xorriso->info_text, + "Temporary memory needed for result sorting : %s", mem_text); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + } + if(mem > xorriso->temp_mem_limit) { + Sfile_scale((double) xorriso->temp_mem_limit,limit_text,5,1e4,1); + sprintf(xorriso->info_text, + "Cannot sort. List of matching files exceeds -temp_mem_limit (%s > %s)", + mem_text, limit_text); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); + return(0); + } + return(1); +} + + +/* @param flag bit0= for Xorriso_msgs_submit: use pager + bit1= do not issue warnings +*/ +int Xorriso_hop_link(struct XorrisO *xorriso, char *link_path, + struct LinkiteM **link_stack, struct stat *stbuf, int flag) +{ + int ret; + struct LinkiteM *litm; + char sfe[5*SfileadrL]; + + if(*link_stack != NULL) { + if((*link_stack)->link_count>=xorriso->follow_link_limit) { + sprintf(xorriso->info_text, + "Too many symbolic links in single tree branch at : %s", + Text_shellsafe(link_path, sfe, 0)); + if(!(flag&2)) + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,"WARNING",flag&1); + return(0); + } + } + ret= stat(link_path, stbuf); + if(ret==-1) + return(0); + ret= Linkitem_find(*link_stack, stbuf->st_dev, stbuf->st_ino, &litm, 0); + if(ret>0) { + sprintf(xorriso->info_text, + "Detected symbolic link loop around : %s", + Text_shellsafe(link_path, sfe, 0)); + if(!(flag&2)) + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", flag&1); + return(0); + } + ret= Linkitem_new(&litm, link_path, stbuf->st_dev, stbuf->st_ino, + *link_stack, 0); + if(ret<=0) { + sprintf(xorriso->info_text, + "Cannot add new item to link loop prevention stack"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", flag&1); + return(-1); + } + *link_stack= litm; + return(1); +} + + +/* @param flag bit0= do not only sum up sizes but also print subdirs + bit1= this is a recursion + @return <=0 error , 1 ok , 2 could not open directory +*/ +int Xorriso_show_dux_subs(struct XorrisO *xorriso, + char *abs_path, char *rel_path, off_t *size, + off_t boss_mem, + struct LinkiteM *link_stack, + int flag) +{ + int i, ret, no_sort= 0, filec= 0, l, j, fc, no_dive, is_link; + char **filev= NULL, *namept; + off_t sub_size, report_size, mem= 0; + struct DirseQ *dirseq= NULL; + struct stat stbuf; + dev_t dir_dev; + struct LinkiteM *own_link_stack; + char *path= NULL, *show_path= NULL, *name= NULL, *sfe= NULL; + + sfe= malloc(5*SfileadrL); + path= malloc(SfileadrL); + show_path= malloc(SfileadrL); + name= malloc(SfileadrL); + if(path==NULL || show_path==NULL || name==NULL || sfe==NULL) { + Xorriso_no_malloc_memory(xorriso, &sfe, 0); + {ret= -1; goto ex;} + } + own_link_stack= link_stack; + namept= name; + *size= 0; + + if(lstat(abs_path, &stbuf)==-1) + {ret= 2; goto ex;} + dir_dev= stbuf.st_dev; + if(S_ISLNK(stbuf.st_mode)) { + if(!(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&2)))) + {ret= 2; goto ex;} + if(stat(abs_path, &stbuf)==-1) + {ret= 2; goto ex;} + if(dir_dev != stbuf.st_dev && + !(xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&2)))) + {ret= 2; goto ex;} + } + ret= Dirseq_new(&dirseq, abs_path, 1); + if(ret<0) { + sprintf(xorriso->info_text, "Cannot obtain disk directory iterator"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + {ret= -1; goto ex;} + } + if(ret==0) + {ret= 2; goto ex;} + + while(1) { + Linkitem_reset_stack(&own_link_stack, link_stack, 0); + ret= Dirseq_next_adr(dirseq,name,0); + if(ret<0) + goto ex; + if(ret==0) + break; + + sub_size= 0; + strcpy(show_path, rel_path); + if(Sfile_add_to_path(show_path, name, 0)<=0) + goto much_too_long; + + strcpy(path, abs_path); + if(Sfile_add_to_path(path, name, 0)<=0) { +much_too_long:; + Xorriso_much_too_long(xorriso, strlen(path)+strlen(name)+1, 2); + {ret= -1; goto ex;} + } + no_dive= 0; + + ret= lstat(path, &stbuf); + if(ret==-1) + continue; + is_link= S_ISLNK(stbuf.st_mode); + if(is_link && xorriso->do_follow_links) { + ret= Xorriso_hop_link(xorriso, path, &own_link_stack, &stbuf, 1); + if(ret<0) + {ret= -1; goto ex;} + if(ret!=1) + no_dive= 1; + } + if(!S_ISDIR(stbuf.st_mode)) + no_dive= 1; + if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount) + no_dive= 1; + if(!no_dive) { + filec++; + l= strlen(rel_path)+1; + mem+= l; + if(l % sizeof(char *)) + mem+= sizeof(char *)-(l % sizeof(char *)); + if(flag&1) /* diving and counting is done further below */ + continue; + ret= Xorriso_show_dux_subs(xorriso, path, show_path, &sub_size, boss_mem, + own_link_stack,2); + if(ret<0) + goto ex; + if(ret==0) + continue; + } + +/* + sub_size+= stbuf.st_size+strlen(name)+1; +*/ + sub_size+= stbuf.st_size+2048; + if(sub_size>0) + (*size)+= sub_size; + } + + if(filec<=0 || !(flag&1)) + {ret= 1; goto ex;} + + /* Try to get a sorted list of directory names */ + mem+= (filec+1)*sizeof(char *); + ret= Xorriso_check_temp_mem_limit(xorriso, mem+boss_mem, 2); + if(ret<0) + goto ex; + Dirseq_rewind(dirseq, 0); + if(ret==0) { +no_sort_possible:; + no_sort= 1; + } else { + filev= (char **) calloc(filec+1, sizeof(char *)); + if(filev==NULL) + goto no_sort_possible; + else { + for(i= 0; i<filec; i++) + filev[i]= NULL; + fc= 0; + while(1) { + ret= Dirseq_next_adr(dirseq,name,0); + if(ret<0) + goto ex; + if(ret==0) + break; + strcpy(path, abs_path); + if(Sfile_add_to_path(path, name, 0)<=0) + goto much_too_long; + + ret= lstat(path,&stbuf); + if(ret==-1) + continue; + is_link= S_ISLNK(stbuf.st_mode); + if(is_link && xorriso->do_follow_links) { + ret= stat(path,&stbuf); + if(ret==-1) + continue; + } + if(!S_ISDIR(stbuf.st_mode)) + continue; + if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount) + continue; + + if(fc>=filec) { /* Number of files changed (or programming error) */ +revoke_sorting:; + for(j=0; j<fc; j++) + free((char *) filev[j]); + free((char *) filev); + filev= NULL; + goto no_sort_possible; + } + + filev[fc]= strdup(name); + if(filev[fc]==NULL) + goto revoke_sorting; + fc++; + } + filec= fc; + if(filec>1) + Sort_argv(filec, filev, 0); + } + } + + for(i= 0; (no_sort || i<filec) && !(xorriso->request_to_abort); i++) { + Linkitem_reset_stack(&own_link_stack, link_stack, 0); + if(no_sort) { + ret= Dirseq_next_adr(dirseq,name,0); + if(ret<0) + goto ex; + if(ret==0) + break; + } else + namept= filev[i]; + + sub_size= 0; + strcpy(show_path, rel_path); + if(Sfile_add_to_path(show_path, namept, 0)<=0) + goto much_too_long; + strcpy(path, abs_path); + if(Sfile_add_to_path(path, namept, 0)<=0) + goto much_too_long; + no_dive= 0; + + ret= lstat(path,&stbuf); + if(ret==-1) + continue; + is_link= S_ISLNK(stbuf.st_mode); + if(is_link && xorriso->do_follow_links) { + ret= Xorriso_hop_link(xorriso, path, &own_link_stack, &stbuf, 1); + if(ret<0) + {ret= -1; goto ex;} + if(ret!=1) + continue; + } + if(!S_ISDIR(stbuf.st_mode)) + continue; + if(dir_dev == stbuf.st_dev || xorriso->do_follow_mount) { + ret= Xorriso_show_dux_subs(xorriso, path, show_path, &sub_size, + boss_mem+mem, own_link_stack, 2|(flag&1)); + if(ret<0) + goto ex; + } + +/* + sub_size+= stbuf.st_size+strlen(namept)+1; +*/ + sub_size+= stbuf.st_size+2048; + if(sub_size>0) + (*size)+= sub_size; + report_size= sub_size/1024; + if(report_size*1024<sub_size) + report_size++; + sprintf(xorriso->result_line, "%7.f ",(double) (report_size)); + sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s\n", + Text_shellsafe(show_path, sfe, 0)); + Xorriso_result(xorriso, 0); + } + + ret= 1; +ex:; + if(sfe!=NULL) + free(sfe); + if(path!=NULL) + free(path); + if(show_path!=NULL) + free(show_path); + if(name!=NULL) + free(name); + Linkitem_reset_stack(&own_link_stack, link_stack, 0); + Dirseq_destroy(&dirseq, 0); + if(filev!=NULL) { + for(i=0; i<filec; i++) + if(filev[i]!=NULL) + free((char *) filev[i]); + free((char *) filev); + } + return(ret); +} + + +int Xorriso__mode_to_perms(mode_t st_mode, char perms[10], int flag) +{ + strcpy(perms,"---------"); + if(st_mode&S_IRUSR) perms[0]= 'r'; + if(st_mode&S_IWUSR) perms[1]= 'w'; + if(st_mode&S_IXUSR) perms[2]= 'x'; + if(st_mode&S_ISUID) { + if(st_mode&S_IXUSR) + perms[2]= 's'; + else + perms[2]= 'S'; + } + if(st_mode&S_IRGRP) perms[3]= 'r'; + if(st_mode&S_IWGRP) perms[4]= 'w'; + if(st_mode&S_IXGRP) perms[5]= 'x'; + if(st_mode&S_ISGID) { + if(st_mode&S_IXGRP) + perms[5]= 's'; + else + perms[5]= 'S'; + } + if(st_mode&S_IROTH) perms[6]= 'r'; + if(st_mode&S_IWOTH) perms[7]= 'w'; + if(st_mode&S_IXOTH) perms[8]= 'x'; + if(st_mode&S_ISVTX) { + if(st_mode&S_IXOTH) + perms[8]= 't'; + else + perms[8]= 'T'; + } + return(1); +} + + +/* @param flag bit0= recognize Xorriso_IFBOOT as file type +*/ +int Xorriso_format_ls_l(struct XorrisO *xorriso, struct stat *stbuf, int flag) +{ + int show_major_minor= 0, high_shift= 0, high_mask= 0; + char *rpt, perms[10], mm_text[80]; + mode_t st_mode; + dev_t dev, major, minor; + + rpt= xorriso->result_line; + rpt[0]= 0; + st_mode= stbuf->st_mode; + + if(S_ISDIR(st_mode)) + strcat(rpt, "d"); + else if(S_ISREG(st_mode)) + strcat(rpt, "-"); + else if(S_ISLNK(st_mode)) + strcat(rpt, "l"); + else if(S_ISBLK(st_mode)) { + strcat(rpt, "b"); + show_major_minor= 1; + } else if(S_ISCHR(st_mode)) { + strcat(rpt, "c"); + show_major_minor= 1; + } else if(S_ISFIFO(st_mode)) + strcat(rpt, "p"); + else if(S_ISSOCK(st_mode)) + strcat(rpt, "s"); + else if((flag & 1) && (st_mode & S_IFMT) == Xorriso_IFBOOT) + strcat(rpt, "e"); + else + strcat(rpt, "?"); + + Xorriso__mode_to_perms(st_mode, perms, 0); + strcat(rpt, perms); + + sprintf(rpt+strlen(rpt),"%4u ",(unsigned int) stbuf->st_nlink); + + sprintf(rpt+strlen(rpt), "%-8lu ", (unsigned long) stbuf->st_uid); + sprintf(rpt+strlen(rpt), "%-8lu ", (unsigned long) stbuf->st_gid); + if(show_major_minor) { + dev= stbuf->st_rdev; + + /* according to /usr/include/sys/sysmacros.h : gnu_dev_major(),_minor() + >>> but this looks as if it should go to some system dependency + >>> in FreeBSD dev_t is 32 bit + */ + if(sizeof(dev_t) > 4) { + high_shift= 32; + high_mask= ~0xfff; + } + major= (((dev >> 8) & 0xfff) | + ((unsigned int) (dev >> high_shift) & high_mask)) + & 0xffffffff; + minor= (((dev & 0xff) | ((unsigned int) (dev >> 12) & ~0xff))) & 0xffffffff; + + sprintf(mm_text, "%u,%u", (unsigned int) major, (unsigned int) minor); + sprintf(rpt+strlen(rpt), "%8s ", mm_text); + } else + sprintf(rpt+strlen(rpt), "%8.f ", (double) stbuf->st_size); + + Ftimetxt(stbuf->st_mtime, rpt+strlen(rpt), 0); + strcat(rpt, " "); + + return(1); +} + + +struct DirentrY { + char *adr; + struct DirentrY *next; +}; + + +int Xorriso_sorted_dir_x(struct XorrisO *xorriso, char *dir_path, + int *filec, char ***filev, off_t boss_mem, int flag) +{ + int count= 0, ret; + char name[SfileadrL]; + struct DirseQ *dirseq= NULL; + off_t mem; + struct DirentrY *last= NULL, *current= NULL; + + *filec= 0; + *filev= NULL; + mem= boss_mem; + ret= Dirseq_new(&dirseq, dir_path, 1); + if(ret<=0) + goto ex; + while(1) { /* loop over directory content */ + ret= Dirseq_next_adr(dirseq,name,0); + if(ret==0) + break; + if(ret<0) + goto ex; + mem+= strlen(name)+8+sizeof(struct DirentrY)+sizeof(char *); + if(mem>xorriso->temp_mem_limit) + {ret= 0; goto ex;} + + current= (struct DirentrY *) calloc(1, sizeof(struct DirentrY)); + if(current==NULL) + {ret= -1; goto ex;} + current->adr= NULL; + current->next= last; + last= current; + last->adr= strdup(name); + if(last->adr==NULL) + {ret= -1; goto ex;} + count++; + } + *filec= count; + if(count==0) + {ret= 1; goto ex;} + (*filev)= (char **) calloc(count, sizeof(char *)); + if(*filev==NULL) + {ret= -1; goto ex; } + count= 0; + for(current= last; current!=NULL; current= last) { + last= current->next; + (*filev)[count++]= current->adr; + free((char *) current); + } + Sort_argv(*filec, *filev, 0); + ret= 1; +ex:; + for(current= last; current!=NULL; current= last) { + last= current->next; + free(current->adr); + free((char *) current); + } + return(ret); +} + + +/* @param flag bit0= long format + bit1= do not print count of nodes + bit2= du format + bit3= print directories as themselves (ls -d) +*/ +int Xorriso_lsx_filev(struct XorrisO *xorriso, char *wd, + int filec, char **filev, off_t boss_mem, int flag) +{ + int i, ret, was_error= 0, dfilec= 0, pass, passes; + char sfe[5*SfileadrL], sfe2[5*SfileadrL], path[SfileadrL]; + char *rpt, link_target[SfileadrL], **dfilev= NULL; + off_t size; + struct stat stbuf; + + rpt= xorriso->result_line; + + Sort_argv(filec, filev, 0); + + /* Count valid nodes, warn of invalid ones */ + for(i= 0; i<filec; i++) { + ret= Xorriso_make_abs_adr(xorriso, wd, filev[i], path, 1|2|4); + if(ret<=0) { + was_error++; + continue; + } + ret= lstat(path, &stbuf); + if(ret==-1) { + sprintf(xorriso->info_text, "Not found in local filesystem: %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 1); + was_error++; + continue; + } + } + + if((flag&8) && !(flag&(2|4))) { + sprintf(xorriso->info_text,"Valid local files found: %d\n",filec-was_error); + Xorriso_info(xorriso,1); + if(filec-was_error<=0) + return(!was_error); + } + + passes= 1+!(flag&(4|8)); + for(pass= 0; pass<passes; pass++) + for(i= 0; i<filec && !(xorriso->request_to_abort); i++) { + ret= Xorriso_make_abs_adr(xorriso, wd, filev[i], path, 1|2|4); + if(ret<=0) + continue; + ret= lstat(path, &stbuf); + if(ret==-1) + continue; + if(S_ISLNK(stbuf.st_mode) && + (xorriso->do_follow_links || xorriso->do_follow_param)) { + ret= stat(path, &stbuf); + if(ret==-1) + ret= lstat(path, &stbuf); + if(ret==-1) + continue; + } + if(S_ISDIR(stbuf.st_mode) && !(flag&(4|8))) { + if(pass==0) + continue; + if(filec>1) { + strcpy(xorriso->result_line, "\n"); + Xorriso_result(xorriso,0); + sprintf(xorriso->result_line, "%s:\n", Text_shellsafe(filev[i], sfe,0)); + Xorriso_result(xorriso,0); + } + ret= Xorriso_sorted_dir_x(xorriso, path, &dfilec, &dfilev, boss_mem, 0); + if(ret<=0) { + + /* >>> DirseQ loop and single item Xorriso_lsx_filev() */; + + } else { + if(flag&1) { + sprintf(xorriso->result_line, "total %d\n", dfilec); + Xorriso_result(xorriso,0); + } + Xorriso_lsx_filev(xorriso, path, + dfilec, dfilev, boss_mem, (flag&1)|2|8); + } + if(dfilec>0) + Sfile_destroy_argv(&dfilec, &dfilev, 0); + continue; + } else + if(pass>0) + continue; + link_target[0]= 0; + rpt[0]= 0; + if((flag&5)==1) { + ret= Xorriso_format_ls_l(xorriso, &stbuf, 0); + if(ret<=0) + continue; + if(S_ISLNK(stbuf.st_mode)) { + ret= Xorriso_resolve_link(xorriso, path, link_target, 1); + if(ret<=0) + link_target[0]= 0; + } + } else if(flag&4) { /* -du or -dus */ + size= stbuf.st_size; + if(S_ISDIR(stbuf.st_mode)) { + ret= Xorriso_show_dux_subs(xorriso, path, filev[i], &size, boss_mem, + NULL, flag&1); + if(ret<0) + return(-1); + if(ret==0) + continue; + } + sprintf(rpt, "%7.f ",(double) (size/1024)); + } + if(link_target[0]) + sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s -> %s\n", + Text_shellsafe(filev[i], sfe, 0), + Text_shellsafe(link_target, sfe2, 0)); + else + sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s\n", + Text_shellsafe(filev[i], sfe, 0)); + Xorriso_result(xorriso, 0); + } + return(!was_error); +} + + +/* @param flag bit0= path is a directory + bit2= recursion: do not reassure in mode 2 "tree" + bit3= this is for overwriting and not for plain removal +*/ +int Xorriso_reassure_restore(struct XorrisO *xorriso, char *path, int flag) +{ + int ret; + char sfe[5*SfileadrL]; + + while((xorriso->do_reassure==1 || (xorriso->do_reassure==2 && !(flag&4))) + && !xorriso->request_not_to_ask) { + /* ls -ld */ + Xorriso_lsx_filev(xorriso, xorriso->wdx, 1, &path, (off_t) 0, 1|2|8); + if(flag&1) /* du -s */ + Xorriso_lsx_filev(xorriso, xorriso->wdx, 1, &path, (off_t) 0, 2|4); + if(flag&8) + sprintf(xorriso->info_text, + "File exists. Remove ? n= keep old, y= remove, x= abort, @= stop asking\n"); + else + sprintf(xorriso->info_text, + "Remove above file ? n= keep it, y= remove it, x= abort, @= stop asking\n"); + Xorriso_info(xorriso, 4); + ret= Xorriso_request_confirmation(xorriso, 1|2|4|16); + if(ret<=0) + goto ex; + if(xorriso->request_to_abort) { + sprintf(xorriso->info_text, + "Removal operation aborted by user before file: %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + ret= 3; goto ex; + } + if(ret==3) + continue; + if(ret==6) /* yes */ + break; + if(ret==4) { /* yes, do not ask again */ + xorriso->request_not_to_ask= 1; + break; + } + if(ret==1) { /* no */ + sprintf(xorriso->info_text, "Kept in existing state: %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + ret= 3; goto ex; + } + } + ret= 1; +ex: + return(ret); +} + + +/* + @param flag >>> bit0= remove whole sub tree: rm -r + bit1= remove empty directory: rmdir + bit2= recursion: do not reassure in mode 2 "tree" + bit3= this is for overwriting and not for plain removal + bit4= count deleted files in xorriso->pacifier_count + bit5= with bit0 only remove directory content, not the directory + @return <=0 = error + 1 = removed leaf file object + 2 = removed directory or tree + 3 = did not remove on user revocation +*/ +int Xorriso_rmx(struct XorrisO *xorriso, off_t boss_mem, char *path, int flag) +{ + int ret, is_dir= 0; + struct stat victim_stbuf, *victim_node= NULL; + struct DirseQ *dirseq= NULL; + char *sfe= NULL, *sub_path= NULL; + + /* Avoiding large local memory objects in order to save stack space */ + sfe= malloc(5*SfileadrL); + sub_path= malloc(2*SfileadrL); + if(sfe==NULL || sub_path==NULL) { + Xorriso_no_malloc_memory(xorriso, &sfe, 0); + {ret= -1; goto ex;} + } + + if(Xorriso_much_too_long(xorriso, strlen(path), 0)<=0) + {ret= 0; goto ex;} + + ret= lstat(path, &victim_stbuf); + if(ret==-1) { + sprintf(xorriso->info_text, "Cannot lstat(%s)", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + {ret= 0; goto ex;} + } + if(strcmp(path, "/")==0) { + sprintf(xorriso->info_text, "May not delete root directory"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + victim_node= &victim_stbuf; + if(S_ISDIR(victim_stbuf.st_mode)) + is_dir= 1; + if(!is_dir) { + if(flag&2) { /* rmdir */ + sprintf(xorriso->info_text, "%s in disk filesystem is not a directory", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + } else { + if(flag&1) { /* rm -r */ + +#ifdef Osirrox_not_yeT + /* >>> */ + + if((xorriso->do_reassure==1 && !xorriso->request_not_to_ask) || + (flag&32)) { + /* Iterate over subordinates and delete them */ + mem= boss_mem; + + ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem, + &iter, &node_array, &node_count, &node_idx, + &node, 1|2); + if(ret<=0) { +cannot_create_iter:; + Xorriso_cannot_create_iter(xorriso, ret, 0); + ret= -1; goto ex; + } + pl= strlen(path); + strcpy(sub_path, path); + if(pl==0 || sub_path[pl-1]!='/') { + sub_path[pl++]= '/'; + sub_path[pl]= 0; + } + sub_name= sub_path+pl; + while(1) { + ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem, &iter, + &node_array, &node_count, &node_idx, &node, 0); + if(ret<0) + goto ex; + if(ret==0 || xorriso->request_to_abort) + break; + name= (char *) iso_node_get_name(node); + if(Xorriso_much_too_long(xorriso, pl+1+strlen(name), 0)<=0) + {ret= 0; goto rm_r_problem_handler;} + strcpy(sub_name, name); + ret= Xorriso_rmi(xorriso, iter, mem, sub_path, (flag&(1|2|8|16))|4); + if(ret==3 || ret<=0 || xorriso->request_to_abort) { +rm_r_problem_handler:; + not_removed= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); + if(fret<0) + goto dir_not_removed; + } + } + if(flag&32) + {ret= 2; goto ex;} + + if(not_removed) { +dir_not_removed:; + sprintf(xorriso->info_text, "Directory not removed: %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + if(ret>0) + ret= 3; + goto ex; + } + } + +#else /* Osirrox_not_yeT */ + + sprintf(xorriso->info_text, "-rm_rx is not implemented yet"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + +#endif /* !Osirrox_not_yeT */ + + } else { + if(!(flag&2)) { /* not rmdir */ + sprintf(xorriso->info_text, "%s in disk filesystem is a directory", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + ret= Dirseq_new(&dirseq, path, 1); + if(ret>0) { + ret= Dirseq_next_adr(dirseq, sfe, 0); + if(ret>0) { + sprintf(xorriso->info_text, + "Directory not empty on attempt to delete: %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + } + } + } + if(xorriso->request_to_abort) + {ret= 3; goto ex;} + ret= Xorriso_reassure_restore(xorriso, path, (flag&(4|8)) | !!is_dir); + if(ret<=0 || ret==3) + goto ex; + if(is_dir) + ret= rmdir(path); + else + ret= unlink(path); + if(ret==-1) { + sprintf(xorriso->info_text, "Cannot delete from disk filesystem %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + ret= -1; goto ex; + } + if(flag&16) + xorriso->pacifier_count++; + ret= 1+!!is_dir; +ex:; + if(sfe!=NULL) + free(sfe); + if(sub_path!=NULL) + free(sub_path); + Dirseq_destroy(&dirseq, 0); + return(ret); +} + + +/* @param flag bit0= recursion +*/ +int Xorriso_findx_action(struct XorrisO *xorriso, struct FindjoB *job, + char *abs_path, char *show_path, int depth, int flag) +{ + int ret= 0, type, action= 0, dpl= 0, compare_result, uret; + uid_t user= 0; + gid_t group= 0; + time_t date= 0; + mode_t mode_or= 0, mode_and= ~1; + char *target, sfe[5*SfileadrL], *disk_prefix, iso_path[SfileadrL]; + struct FindjoB *subjob; + struct stat stbuf; + + action= Findjob_get_action_parms(job, &target, &user, &group, + &mode_and, &mode_or, &type, &date, &subjob, 0); + if(action<0) + action= 0; + if(action<0) + action= 0; + if(action==15 || action==16 || action==18 || action==19 || action==20) { + /* in_iso , not_in_iso, add_missing , empty_iso_dir , is_full_in_iso */ + Findjob_get_start_path(job, &disk_prefix, 0); + if(strncmp(abs_path, disk_prefix, strlen(disk_prefix))!=0) + {ret= -1; goto ex;} + dpl= strlen(disk_prefix); + if(strlen(target)+strlen(abs_path)-dpl >= SfileadrL) + {ret= -1; goto ex;} + if(abs_path[dpl]=='/') + dpl++; + ret= Xorriso_make_abs_adr(xorriso, target, abs_path+dpl, iso_path, 4); + if(ret<=0) + {goto ex;} + + } + if(action==15) { /* in_iso */ + ret= Xorriso_iso_lstat(xorriso, iso_path, &stbuf, 0); + if(ret<0) + {ret= 1; goto ex;} + sprintf(xorriso->result_line, "%s\n", Text_shellsafe(show_path, sfe, 0)); + Xorriso_result(xorriso, 0); + ret= 1; + } else if(action==16) { /* not_in_iso */ + ret= Xorriso_compare_2_files(xorriso, abs_path, iso_path, abs_path+dpl, + &compare_result, 4); + if(ret<xorriso->find_compare_result) + xorriso->find_compare_result= ret; + if(ret>=0) + ret= 1; + } else if(action==18) { /* add_missing */ + ret= Xorriso_compare_2_files(xorriso, abs_path, iso_path, abs_path+dpl, + &compare_result, 4|(1<<31)); + if(ret<xorriso->find_compare_result) + xorriso->find_compare_result= ret; + if(ret==0) { + uret= Xorriso_update_interpreter(xorriso, NULL, compare_result, + abs_path, iso_path, (flag&1)<<2); + if(uret<=0) + ret= 0; + } + if(ret>=0) + ret= 1; + } else if(action==19) { /* empty_iso_dir */ + ret= Xorriso_iso_lstat(xorriso, iso_path, &stbuf, 0); + if(ret<0) + {ret= 1; goto ex;} + if(!S_ISDIR(stbuf.st_mode)) + {ret= 1; goto ex;} + ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, iso_path, 1|32); + if(ret>0) { + sprintf(xorriso->info_text, "Emptied directory %s", + Text_shellsafe(iso_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0); + } + } else if(action==20) { /* is_full_in_iso */ + ret= Xorriso_iso_lstat(xorriso, iso_path, &stbuf, 0); + if(ret<0) + {ret= 1; goto ex;} + if(!S_ISDIR(stbuf.st_mode)) + {ret= 1; goto ex;} + strcpy(sfe, xorriso->wdi); + strcpy(xorriso->wdi, iso_path); + ret= Xorriso_ls(xorriso, 4|8); + strcpy(xorriso->wdi, sfe); + if(ret>0) { + sprintf(xorriso->result_line, + "d %s (ISO) : non-empty directory (would not match mount point)\n", + Text_shellsafe(iso_path, sfe, 0)); + Xorriso_result(xorriso,0); + } + {ret= 1; goto ex;} + } else { + sprintf(xorriso->result_line, "%s\n", Text_shellsafe(show_path, sfe, 0)); + Xorriso_result(xorriso, 0); + ret= 1; + } +ex:; + if(action==15 || action==16 || action==18 || action==19 || action==20) + if(xorriso->no_volset_present) + xorriso->request_to_abort= 1; /* Need an image. No use to try again. */ + return(ret); +} + + +/* @param flag bit0=recursion +*/ +int Xorriso_findx(struct XorrisO *xorriso, struct FindjoB *job, + char *abs_dir_parm, char *dir_path, + struct stat *dir_stbuf, int depth, + struct LinkiteM *link_stack, int flag) +{ + int ret,is_link, no_dive; + struct DirseQ *dirseq= NULL; + struct stat stbuf; + struct LinkiteM *own_link_stack; + char *abs_dir_path, *namept; + char *name= NULL, *path= NULL, *sfe= NULL; + char *abs_dir_path_data= NULL, *abs_path= NULL; + + sfe= malloc(5*SfileadrL); + name= malloc(SfileadrL); + path= malloc(SfileadrL); + abs_dir_path_data= malloc(SfileadrL); + abs_path= malloc(SfileadrL); + if(name==NULL || sfe==NULL || path==NULL || + abs_dir_path_data==NULL || abs_path==NULL) { + Xorriso_no_malloc_memory(xorriso, &sfe, 0); + {ret= -1; goto ex;} + } + own_link_stack= link_stack; + abs_dir_path= abs_dir_parm; + if(abs_dir_path[0]==0) { + ret= Xorriso_make_abs_adr(xorriso, xorriso->wdx, dir_path, + abs_dir_path_data, 1|2|8); + if(ret<=0) + goto ex; + abs_dir_path= abs_dir_path_data; + ret= Xorriso_path_is_excluded(xorriso, abs_dir_path, !(flag&1)); + if(ret<0) + goto ex; + if(ret>0) + {ret= 0; goto ex;} + ret= lstat(abs_dir_path, dir_stbuf); + if(ret==-1) + {ret= 0; goto ex;} + if(S_ISLNK(dir_stbuf->st_mode) && + (xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&1)))) + if(stat(abs_dir_path, &stbuf)!=-1) + if(dir_stbuf->st_dev == stbuf.st_dev || + (xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&1)))) + memcpy(dir_stbuf, &stbuf, sizeof(struct stat)); + + namept= strrchr(dir_path, '/'); + if(namept==NULL) + namept= dir_path; + else + namept++; + ret= Findjob_test(job, namept, NULL, dir_stbuf, depth, 0); + if(ret<0) + goto ex; + if(ret>0) { + ret= Xorriso_findx_action(xorriso, job, abs_dir_path, dir_path, depth, + flag&1); + if(ret<=0) { + if(xorriso->request_to_abort) + goto ex; + if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0) + goto ex; + } + } + } + if(xorriso->request_to_abort) + {ret= 1; goto ex;} + if(!S_ISDIR(dir_stbuf->st_mode)) + {ret= 2; goto ex;} + + ret= Dirseq_new(&dirseq, abs_dir_path, 1); + if(ret<0) { + sprintf(xorriso->info_text, "Cannot obtain disk directory iterator"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + {ret= -1; goto ex;} + } + if(ret==0) + {ret= 2; goto ex;} + + while(!xorriso->request_to_abort) { + Linkitem_reset_stack(&own_link_stack, link_stack, 0); + ret= Dirseq_next_adr(dirseq,name,0); + if(ret==0) + break; + if(ret<0) { + sprintf(xorriso->info_text,"Failed to obtain next directory entry"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + {ret= -1; goto ex;} + } + ret= Xorriso_make_abs_adr(xorriso, abs_dir_path, name, abs_path, 1); + if(ret<=0) + goto ex; + ret= Xorriso_make_abs_adr(xorriso, dir_path, name, path, 4); + if(ret<=0) + goto ex; + ret= Xorriso_path_is_excluded(xorriso, abs_path, 0); /* (is never param) */ + if(ret<0) + goto ex; + if(ret>0) + continue; + ret= lstat(abs_path, &stbuf); + if(ret==-1) + continue; + no_dive= 0; + + is_link= S_ISLNK(stbuf.st_mode); + if(is_link && xorriso->do_follow_links) { + ret= Xorriso_hop_link(xorriso, abs_path, &own_link_stack, &stbuf, 2); + if(ret<0) + {ret= -1; goto ex;} + if(ret!=1) + no_dive= 1; + } + ret= Findjob_test(job, name, dir_stbuf, &stbuf, depth, 0); + if(ret<0) + goto ex; + if(ret>0) { + ret= Xorriso_findx_action(xorriso, job, abs_path, path, depth, flag&1); + if(ret<=0) { + if(xorriso->request_to_abort) + goto ex; + if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0) + goto ex; + } + } + if(!S_ISDIR(stbuf.st_mode)) + no_dive= 1; + if(dir_stbuf->st_dev != stbuf.st_dev && !xorriso->do_follow_mount) + no_dive= 1; + if(!no_dive) { + ret= Xorriso_findx(xorriso, job, abs_path, path, &stbuf, depth+1, + own_link_stack, flag|1); + if(ret<0) + goto ex; + } + } + + ret= 1; +ex:; + if(sfe!=NULL) + free(sfe); + if(name!=NULL) + free(name); + if(path!=NULL) + free(path); + if(abs_dir_path_data!=NULL) + free(abs_dir_path_data); + if(abs_path!=NULL) + free(abs_path); + Dirseq_destroy(&dirseq, 0); + return(ret); +} + + +/* @param flag bit0= a non-existing target of multiple sources is a directory + bit1= all paths except the last one are disk_paths + bit2= the last path is a disk_path + @return <=0 is error, 1= leaf file object, 2= directory +*/ +int Xorriso_cpmv_args(struct XorrisO *xorriso, char *cmd, + int argc, char **argv, int *idx, + int *optc, char ***optv, char eff_dest[SfileadrL], + int flag) +{ + int destc= 0, is_dir=0, end_idx, ret, i; + char **destv= NULL; + char sfe[5*SfileadrL]; + + end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, + (xorriso->do_iso_rr_pattern==1)|(flag&2)); + if(end_idx - *idx < 2) { + sprintf(xorriso->info_text, "%s: not enough arguments", cmd); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + {ret= 0; goto ex;} + } + + ret= Xorriso_opt_args(xorriso, cmd, argc, argv, *idx, &end_idx, optc, optv, + (flag&2)|16); /* ignore last argument */ + if(ret<=0) + goto ex; + /* demand one match, or 0 with a constant */ + ret= Xorriso_opt_args(xorriso, cmd, argc, argv, end_idx, &end_idx, &destc, + &destv, ((flag&4)>>1) | 32 | 64); + if(ret<=0) + goto ex; + + /* Evaluate target address */ + if(flag&4) + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, destv[0], eff_dest, + 2|4|16); + else + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, destv[0], eff_dest, + 1); + if(ret<0) + {ret= 0; goto ex;} + if(ret==2 || ((flag&1) && *optc > 1 && ret==0)) { + is_dir= 1; + } else if(*optc > 1) { + for(i= 0; i<*optc; i++) + Xorriso_msgs_submit(xorriso, 0, (*optv)[i], 0, "ERRFILE", 0); + sprintf(xorriso->info_text, + "%s: more than one origin given, destination is a non-directory: %s", + cmd, Text_shellsafe(destv[0], sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + if(ret==0) { /* compute complete eff_dest */ + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, destv[0], eff_dest, + 2 | (flag&4)); + if(ret<0) + {ret= 0; goto ex;} + } + + ret= 1+is_dir; +ex:; + Xorriso_opt_args(xorriso, cmd, argc, argv, *idx, &end_idx, &destc, &destv, + 256); + (*idx)= end_idx; + return(ret); +} + + +/** @return -1= abort , 0= no , 1= yes +*/ +int Xorriso_reassure(struct XorrisO *xorriso, char *cmd, char *which_will, + int flag) +{ + int ret; + + if(!xorriso->do_reassure) + return(1); + sprintf(xorriso->info_text, "Really perform %s which will %s ? (y/n)\n", + cmd, which_will); + Xorriso_info(xorriso, 4); + do { + ret= Xorriso_request_confirmation(xorriso, 2|4|16); + } while(ret==3); + if(ret==6 || ret==4) { + sprintf(xorriso->info_text, "%s confirmed", cmd); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(1); + } + if(ret==2) { + sprintf(xorriso->info_text, "%s aborted", cmd); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(-1); + } + sprintf(xorriso->info_text, "%s revoked", cmd); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(0); +} + + +/* @param flag bit0+1= what to aquire after giving up outdev + 0=none, 1=indev, 2=outdev, 3=both +*/ +int Xorriso_reaquire_outdev(struct XorrisO *xorriso, int flag) +{ + int ret, aq_flag; + char drive_name[SfileadrL], sfe[5*SfileadrL]; + + aq_flag= flag&3; + strcpy(drive_name, xorriso->outdev); + Xorriso_give_up_drive(xorriso, aq_flag); + if(aq_flag==0) { + sprintf(xorriso->info_text,"Gave up -outdev %s", + Text_shellsafe(xorriso->outdev, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(1); + } + sprintf(xorriso->info_text,"Re-aquiring -outdev %s", + Text_shellsafe(drive_name, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + ret= Xorriso_aquire_drive(xorriso, drive_name, aq_flag); + if(ret<=0) { + sprintf(xorriso->info_text,"Could not re-aquire -outdev %s", + Text_shellsafe(xorriso->outdev, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(ret); + } + return(1); +} + + +/* micro version of cdrskin */ +int Xorriso_cdrskin(struct XorrisO *xorriso, char *whom, int argc, char **argv, + int flag) +{ + int ret, i, k, mem_do_close, aq_ret, eject_ret, msc1, msc2, hflag; + int do_atip= 0, do_checkdrive= 0, do_eject= 0, do_scanbus= 0; + int do_toc= 0, do_verbous= 0, do_version= 0, do_help= 0, do_waiti= 0; + int do_multi= 0, do_msinfo= 0, do_grow= 0, do_isosize= 0; + double write_start_address= -1.0, tsize= -1.0; + char track_source[SfileadrL], sfe[5*SfileadrL], dev_adr[SfileadrL], *cpt; + char mem_report_about_text[80], *report_about= "SORRY", blank_mode[80]; + char speed[80]; + + /* cdrecord 2.01 options which are not scheduled for implementation, yet */ + static char ignored_partial_options[][41]= { + "timeout=", "debug=", "kdebug=", "kd=", "driver=", "ts=", + "pregap=", "defpregap=", "mcn=", "isrc=", "index=", "textfile=", + "pktsize=", "cuefile=", + "gracetime=", "minbuf=", + + "assert_write_lba=", "fifo_start_at=", "dev_translation=", + "drive_scsi_dev_family=", "fallback_program=", "modesty_on_drive=", + "tao_to_sao_tsize=", + + "direct_write_amount=", "msifile=", + + "" + }; + static char ignored_full_options[][41]= { + "-d", "-Verbose", "-V", "-silent", "-s", "-setdropts", "-prcap", + "-reset", "-abort", "-overburn", "-ignsize", "-useinfo", + "-fix", "-nofix", + "-raw", "-raw96p", "-raw16", + "-clone", "-text", "-mode2", "-xa", "-xa1", "-xa2", "-xamix", + "-cdi", "-preemp", "-nopreemp", "-copy", "-nocopy", + "-scms", "-shorttrack", "-noshorttrack", "-packet", "-noclose", + "-media-info", "-minfo", + "-load", "-lock", "-raw96r", "-sao", "-dao", "-swab", + "-tao", "-force", "-format", + + "--adjust_speed_to_drive", "--allow_emulated_drives", "--allow_setuid", + "--allow_untested_media", "--any_track", "--demand_a_drive", + "--fifo_disable", "--fifo_start_empty", "--fill_up_media", + "--list_ignored_options", "--no_rc", "--no_convert_fs_adr", + "--prodvd_cli_compatible", "--single_track", + + "--tell_media_space", + + "" + }; + + static char helptext[][80]= { +"Usage: xorriso -as cdrecord [options|source_addresses]", +"Note: This is not cdrecord. See xorriso -help, xorriso -version, man xorriso", +"Options:", +"\t-version\tprint version information and exit emulation", +"\t--devices\tprint list of available MMC drives and exit emulation", +"\tdev=target\tpseudo-SCSI target to use as CD-Recorder", +"\t-v\t\tincrement verbose level by one", +"\t-checkdrive\tcheck if a driver for the drive is present", +"\t-inq\t\tdo an inquiry for the drive and exit emulation", +"\tspeed=#\t\tset speed of drive", +"\tblank=type\tblank a CD-RW disc (see blank=help)", +"\tfs=#\t\tSet fifo size to # (0 to disable, default is 4 MB)", +"\t-eject\t\teject the disk after doing the work", +"\t-dummy\t\tdo everything with laser turned off", +"\t-msinfo\t\tretrieve multi-session info for mkisofs >= 1.10", +"\t-toc\t\tretrieve and print TOC/PMA data", +"\t-atip\t\tretrieve media state, print \"Is *erasable\"", +"\t-multi\t\tgenerate a TOC that allows multi session", +"\t-waiti\t\twait until input is available before opening SCSI", +"\ttsize=#\t\tannounces exact size of source data", +"\tpadsize=#\tAmount of padding", +"\t-data\t\tSubsequent tracks are CD-ROM data mode 1 (default)", +"\t-isosize\tUse iso9660 file system size for next data track", +"\t-pad\t\tpadsize=30k", +"\t-nopad\t\tDo not pad", +"\t--grow_overwriteable_iso\temulate multi-session on DVD+RW", +"\twrite_start_address=#\t\twrite to given byte address on DVD+RW", +"\tstream_recording=on\t\ttry to get full speed DVD-RAM and BD-RE", +"\t-help\t\tprint this text to stderr and exit emulation", +"Actually this is the integrated ISO RockRidge filesystem manipulator xorriso", +"lending its libburn capabilities to a very limited cdrecord emulation. Only", +"a single data track can be burnt to blank, appendable or overwriteable media.", +"A much more elaborate cdrecord emulator is cdrskin from the same project.", +"@End_of_helptexT@" +}; +/* "\t-scanbus\tscan the SCSI bus and exit emulation", */ + +static char blank_help[][80]= { +"Blanking options:", +"\tall\t\tblank the entire disk", +"\tdisc\t\tblank the entire disk", +"\tdisk\t\tblank the entire disk", +"\tfast\t\tminimally blank the entire disk", +"\tminimal\t\tminimally blank the entire disk", +"\tas_needed\tblank or format media to make it ready for (re-)use", +"\tdeformat\t\tblank a formatted DVD-RW", +"\tdeformat_quickest\tminimally blank a formatted DVD-RW to DAO only", +"\tformat_overwrite\tformat a DVD-RW to \"Restricted Overwrite\"", +"@End_of_helptexT@" +}; + + strcpy(mem_report_about_text, xorriso->report_about_text); + mem_do_close= xorriso->do_close; + + track_source[0]= 0; + dev_adr[0]= 0; + blank_mode[0]= 0; + speed[0]= 0; + + if(xorriso->in_drive_handle != NULL) { + ret= Xorriso_option_dev(xorriso, "", 1|32); /* give up indev */ + if(ret!=1) + return(ret); + } + + + /* Assess plan, make settings */ + for(i= 0; i<argc; i++) { + sprintf(xorriso->info_text, "-as %s: %s", + whom, Text_shellsafe(argv[i], sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + + for(k=0;ignored_partial_options[k][0]!=0;k++) { + if(argv[i][0]=='-') + if(strncmp(argv[i]+1,ignored_partial_options[k], + strlen(ignored_partial_options[k]))==0) + goto no_volunteer; + if(strncmp(argv[i],ignored_partial_options[k], + strlen(ignored_partial_options[k]))==0) + goto no_volunteer; + } + for(k=0;ignored_full_options[k][0]!=0;k++) + if(strcmp(argv[i],ignored_full_options[k])==0) + goto no_volunteer; + if(0) { +no_volunteer:; + sprintf(xorriso->info_text, "-as %s: Ignored option %s", + whom, Text_shellsafe(argv[i], sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + continue; + } + + if(strcmp(argv[i], "-atip")==0) { + do_atip= 1; + } else if(strcmp(argv[i], "-audio")==0) { + sprintf(xorriso->info_text, "-as %s: Option -audio not supported.", whom); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } else if(strncmp(argv[i], "-blank=", 7)==0 || + strncmp(argv[i], "blank=", 6)==0) { + cpt= strchr(argv[i], '=')+1; + if(strcmp(cpt,"all")==0 || strcmp(cpt,"disc")==0 + || strcmp(cpt,"disk")==0) { + strcpy(blank_mode, "all"); + } else if(strcmp(cpt,"fast")==0 || strcmp(cpt,"minimal")==0) { + strcpy(blank_mode, "fast"); + } else if(strcmp(cpt,"help")==0) { + strcpy(blank_mode, "help"); + } else if(strcmp(cpt,"deformat")==0 || + strcmp(cpt,"deformat_sequential")==0 || + strcmp(cpt,"deformat_quickest")==0 || + strcmp(cpt,"deformat_sequential_quickest")==0) { + strcpy(blank_mode, cpt); + } else if(strcmp(cpt,"format_overwrite")==0) { + strcpy(blank_mode, "format_overwrite"); + } else if(strcmp(cpt,"as_needed")==0) { + strcpy(blank_mode, "as_needed"); + } else { + sprintf(xorriso->info_text, + "-as %s: blank=%s not supported. See blank=help .", + whom, Text_shellsafe(argv[i], sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + } else if(strcmp(argv[i], "-checkdrive")==0) { + do_checkdrive= 1; + } else if(strcmp(argv[i], "-data")==0) { + /* ok */; + } else if(strncmp(argv[i], "-dev=", 5)==0 || + strncmp(argv[i], "dev=", 4)==0) { + cpt= strchr(argv[i], '=')+1; + strcpy(dev_adr, cpt); + } else if(strcmp(argv[i], "--devices")==0) { + do_scanbus= 2; + } else if(strncmp(argv[i],"driveropts=", 11)==0 || + strncmp(argv[i],"-driveropts=", 12)==0) { + if(strcmp(argv[i]+11, "help")==0) { + fprintf(stderr,"Driver options:\n"); + fprintf(stderr, + "burnfree\tPrepare writer to use BURN-Free technology\n"); + } + } else if(strcmp(argv[i], "-dummy")==0) { + xorriso->do_dummy= 1; + } else if(strcmp(argv[i], "-eject")==0) { + do_eject= 1; + } else if(strncmp(argv[i], "-fs=", 4)==0 || strncmp(argv[i], "fs=", 3)==0) { + cpt= strchr(argv[i], '=')+1; + ret= Xorriso_option_fs(xorriso, cpt, 0); + if(ret<=0) + goto ex; + } else if(strcmp(argv[i], "--grow_overwriteable_iso")==0) { + do_grow= 1; + } else if(strcmp(argv[i], "-help")==0) { + do_help= 1; + } else if(strcmp(argv[i], "-isosize")==0) { + do_isosize= 1; + } else if(strcmp(argv[i], "-inq")==0) { + do_checkdrive= 2; + } else if(strcmp(argv[i], "-msinfo")==0) { + do_msinfo= 1; + } else if(strcmp(argv[i], "-multi")==0) { + do_multi= 1; + } else if(strcmp(argv[i], "-nopad")==0) { + xorriso->padding= 0; + } else if(strcmp(argv[i], "-pad")==0) { + xorriso->padding= 15*2048; + } else if(strncmp(argv[i], "-padsize=", 9)==0 || + strncmp(argv[i], "padsize=", 8)==0) { + cpt= strchr(argv[i], '=')+1; + ret= Xorriso_option_padding(xorriso, cpt, 0); + if(ret<=0) + goto ex; + } else if(strcmp(argv[i], "-scanbus")==0) { + sprintf(xorriso->info_text, "-as %s: Option -scanbus not supported.", + whom); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + +/* do_scanbus= 1; */ + } else if(strncmp(argv[i], "-speed=", 7)==0 || + strncmp(argv[i], "speed=", 6)==0) { + cpt= strchr(argv[i], '=')+1; + strncpy(speed, cpt, 79); + speed[79]= 0; + + } else if(strncmp(argv[i], "-stream_recording=", 18)==0 || + strncmp(argv[i], "stream_recording=", 17)==0) { + cpt= strchr(argv[i], '=')+1; + Xorriso_option_stream_recording(xorriso, cpt, 0); + + } else if(strcmp(argv[i], "-toc")==0) { + do_toc= 1; + } else if(strncmp(argv[i], "-tsize=", 7)==0 || + strncmp(argv[i], "tsize=", 6)==0) { + cpt= strchr(argv[i], '=')+1; + tsize= Scanf_io_size(cpt, 1); + if(tsize > 1024.0*1024.0*1024.0*1024.0*1024.0) { + sprintf(xorriso->info_text, "-as %s: much too large: %s",whom, argv[i]); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + } else if(strcmp(argv[i], "-v")==0 || strcmp(argv[i],"-verbose")==0) { + do_verbous++; + } else if(strcmp(argv[i], "-vv")==0) { + do_verbous+= 2; + } else if(strcmp(argv[i], "-vvv")==0) { + do_verbous+= 3; + } else if(strcmp(argv[i], "-version")==0) { + do_version= 1; + } else if(strcmp(argv[i], "-waiti")==0) { + do_waiti= 1; + } else if(strncmp(argv[i], "write_start_address=", 20)==0) { + write_start_address= Scanf_io_size(argv[i]+20,0); + } else if(argv[i][0]=='-' && argv[i][1]!=0) { + sprintf(xorriso->info_text, "-as %s: Unknown option %s", + whom, Text_shellsafe(argv[i], sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } else { + if(track_source[0]) { + sprintf(xorriso->info_text, "-as %s: Surplus track source %s", + whom, Text_shellsafe(argv[i], sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + sprintf(xorriso->info_text, "First and only track source is %s", + Text_shellsafe(track_source, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + ret= 0; goto ex; + } + if(Sfile_str(track_source, argv[i], 0)<=0) + {ret= -1; goto ex;} + } + } + + /* Perform actions */ + Xorriso_option_report_about(xorriso, "NOTE", 0); + if(do_version) { + sprintf(xorriso->result_line, "Cdrecord 2.01-Emulation Copyright (C) 2008 see libburnia-project.org xorriso\n"); + Xorriso_result(xorriso, 1); + Xorriso_option_version(xorriso, 0); + ret= 1; goto ex; + } + if(do_waiti) { + sprintf(xorriso->info_text, + "xorriso: Option -waiti pauses program until input appears at stdin\n"); + Xorriso_info(xorriso,0); + sprintf(xorriso->result_line, "Waiting for data on stdin...\n"); + Xorriso_result(xorriso, 1); + for(ret= 0; ret==0; ) + ret= Wait_for_input(0,1000000,0); + if(ret<0 || feof(stdin)) { + Xorriso_msgs_submit(xorriso, 0, + "stdin produces exception rather than data", 0, "NOTE", 0); + } + sprintf(xorriso->info_text, "xorriso: Option -waiti pausing is done.\n"); + } + if(dev_adr[0]) { + hflag= 2|32; + if(!do_grow) + hflag|= 8; /* consider overwriteables as blank */ + ret= Xorriso_option_dev(xorriso, dev_adr, hflag); + if(ret<=0) + goto ex; + } + + if(do_help) { + for(i= 0; strcmp(helptext[i], "@End_of_helptexT@")!=0; i++) { + sprintf(xorriso->info_text, "%s\n", helptext[i]); + Xorriso_info(xorriso,0); + } + ret= 1; goto ex; + } + if(do_scanbus) { + if(do_scanbus==1) + /* >>> would need -scanbus compatible output and input format */; + else + Xorriso_option_devices(xorriso, 0); + ret= 1; goto ex; + } + if(strcmp(blank_mode, "help")==0) { + for(i= 0; strcmp(blank_help[i], "@End_of_helptexT@")!=0; i++) { + sprintf(xorriso->info_text, "%s\n", blank_help[i]); + Xorriso_info(xorriso,0); + } + ret= 1; goto ex; + } + + if(!(do_checkdrive || do_atip || do_toc || blank_mode[0] || track_source[0] || + do_eject || do_msinfo)) + {ret= 1; goto ex;} + + if(xorriso->out_drive_handle==NULL) { + sprintf(xorriso->info_text, "-as %s: No output drive selected", whom); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + + if(do_msinfo) { + ret= Xorriso_msinfo(xorriso, &msc1, &msc2, 2 | !!do_grow); + if(ret<=0) + goto ex; + sprintf(xorriso->result_line, "%d,%d\n", msc1, msc2); + Xorriso_result(xorriso, 1); + } + + if(speed[0]) { + ret= Xorriso_option_speed(xorriso, speed, 0); + if(ret<=0) + goto ex; + } + + if(do_verbous<=0) + report_about= "SORRY"; + else if(do_verbous<=2) + report_about= "UPDATE"; + else if(do_verbous==3) + report_about= "DEBUG"; + else + report_about= "ALL"; + Xorriso_option_report_about(xorriso, report_about, 0); + + if(do_checkdrive) { + ret= Xorriso_atip(xorriso, 2-(do_checkdrive==2)); + if(ret<=0) + goto ex; + } + if(do_atip) { + ret= Xorriso_atip(xorriso, 0); + if(ret<=0) + goto ex; + } + if(do_toc) { + ret= Xorriso_option_toc(xorriso, 0); + if(ret<=0) + goto ex; + } + if(strcmp(blank_mode, "format_overwrite")==0) { + ret= Xorriso_option_blank(xorriso, "fast", 1); + if(ret<=0) + goto ex; + } else if(blank_mode[0]) { + ret= Xorriso_option_blank(xorriso, blank_mode, 0); + if(ret<=0) + goto ex; + } + if(track_source[0]) { + xorriso->do_close= !do_multi; + ret= Xorriso_burn_track(xorriso, (off_t) write_start_address, + track_source, (off_t) tsize, + (!!do_grow)|((!!do_isosize)<<1)); + aq_ret= Xorriso_reaquire_outdev(xorriso, 2*(ret>0)); + if(ret<=0 && ret<aq_ret) + goto ex; + if(aq_ret<=0) + {ret= aq_ret; goto ex;} + } + + ret= 1; +ex:; + if(do_eject && ret>=0) { + eject_ret= Xorriso_option_eject(xorriso, "out", 0); + if(eject_ret<ret) + ret= eject_ret; + } + if(ret<=0) { + sprintf(xorriso->info_text, "-as %s: Job could not be performed properly.", + whom); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + } + Xorriso_option_report_about(xorriso, mem_report_about_text, 0); + xorriso->do_close= mem_do_close; + return(ret); +} + + +/* @param flag bit0= do not report eventual ignore decision +*/ +int Xorriso_genisofs_ignore(struct XorrisO *xorriso, char *whom, + char **argv, int *i, int flag) +{ + /* mkisofs 2.01 options which are not scheduled for implementation, yet */ + static char ignored_arg0_options[][41]= { + "-allow-leading-dots", "-ldots", "-allow-lowercase", "-allow-multidot", + "-cache-inodes", "-no-cache-inodes", "-check-oldnames", "-d", "-D", + "-joliet-long", "-l", "-L", "-max-iso9660-filenames", "-N", "-nobak", + "-no-bak", "-force-rr", "-r", "-relaxed-filenames", "-T", "-U", + "-no-iso-translate", + "" + }; + static char ignored_arg1_options[][41]= { + "-A", "-biblio", "-check-session", "-p", "-root", + "-old-root", "-sysid", "-table-name", + "" + }; + int k, idx_offset= 0; + char sfe[5*SfileadrL]; + + for(k=0;ignored_arg0_options[k][0]!=0;k++) + if(strcmp(argv[*i],ignored_arg0_options[k])==0) + goto no_volunteer; + for(k=0;ignored_arg1_options[k][0]!=0;k++) + if(strcmp(argv[*i],ignored_arg1_options[k])==0) { + (*i)++; + idx_offset= -1; + goto no_volunteer; + } + return(0); +no_volunteer:; + sprintf(xorriso->info_text, "-as %s: Ignored option %s", + whom, Text_shellsafe(argv[(*i)+idx_offset], sfe, 0)); + if(!(flag & 1)) + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(1); +} + + +/* micro emulation of mkisofs */ +int Xorriso_genisofs(struct XorrisO *xorriso, char *whom, + int argc, char **argv, int flag) +{ + int ret, i, was_path= 0, was_other_option= 0, mem_graft_points, mem; + int do_print_size= 0, fd, idx, iso_level= 0, no_emul_boot= 0; + int option_b= 0, was_failure= 0, fret; + char sfe[5*SfileadrL], adr[SfileadrL+8], ra_text[80], pathspec[2*SfileadrL]; + char *ept, *add_pt, eff_path[SfileadrL], indev[SfileadrL+8], msc[80], *cpt; + + static char helptext[][80]= { +"Usage: xorriso -as mkisofs [options] file...", +"Note: This is not mkisofs. See xorriso -help, xorriso -version, man xorriso", +"Options:", +" -f, -follow-links Follow symbolic links", +" -graft-points Allow to use graft points for filenames", +" -help Print option help", +" -input-charset CHARSET Local input charset for file name conversion", +" -output-charset CHARSET Output charset for file name conversion", +" -iso-level LEVEL Set ISO9660 conformance level (1..3)", +" -J, -joliet Generate Joliet directory information", +" -o FILE, -output FILE Set output file name", +" -m GLOBFILE, -exclude GLOBFILE", +" Exclude file name", +" -exclude-list FILE File with list of file names to exclude", +" -pad Pad output by 300k (default)", +" -no-pad Do not pad output", +" -M FILE, -prev-session FILE Set path to previous session to merge", +" -C PARAMS, -cdrecord-params PARAMS", +" Magic paramters from cdrecord", +" -path-list FILE File with list of pathnames to process", +" --quoted_path_list FILE File with list of quoted pathnames to process", +" -print-size Print estimated filesystem size and exit", +" -quiet Run quietly", +" -R, -rock Generate Rock Ridge directory information", +" -V ID, -volid ID Set Volume ID", +" -b FILE, -eltorito-boot FILE", +" Set El Torito boot image name", +" -c FILE, -eltorito-catalog FILE", +" Set El Torito boot catalog name", +" -boot-load-size # Set numbers of load sectors", +" -no-emul-boot Boot image is 'no emulation' image", +" -boot-info-table Patch boot image with info table", +" isolinux_mbr=on|auto|off Control eventual isohybrid MBR generation", +" -v, -verbose Verbose", +" -version Print the current version", +"@End_of_helptexT@" +}; + + strcpy(ra_text, xorriso->report_about_text); + + adr[0]= indev[0]= msc[0]= 0; + for(i= 0; i<argc; i++) { + ret= Xorriso_genisofs_ignore(xorriso, whom, argv, &i, 1); + if(ret == 1) + continue; + if(strcmp(argv[i], "-version")==0) { + sprintf(xorriso->result_line, +"mkisofs 2.01-Emulation Copyright (C) 2008 see libburnia-project.org xorriso\n" + ); + fd= xorriso->dev_fd_1; + if(fd<0) + fd= 1; + write(fd, xorriso->result_line, strlen(xorriso->result_line)); + fsync(fd); + Xorriso_option_version(xorriso, 0); + + } else if(strcmp(argv[i], "-o")==0 || strcmp(argv[i], "-output")==0) { + if(i+1>=argc) + goto not_enough_args; + i++; + adr[0]= 0; + if(strcmp(argv[i],"-")!=0 && strncmp(argv[i], "stdio:", 6)!=0) + strcpy(adr, "stdio:"); + if(Sfile_str(adr+strlen(adr), argv[i], 0)<=0) + {ret= -1; goto ex;} + } else if(strcmp(argv[i], "-M")==0 || strcmp(argv[i], "-dev")==0 || + strcmp(argv[i], "-prev-session")==0) { + if(i+1>=argc) + goto not_enough_args; + i++; + if(strncmp(argv[i], "stdio:", 6)!=0) + strcpy(indev, "stdio:"); + if(Sfile_str(indev+strlen(indev), argv[i], 0)<=0) + {ret= -1; goto ex;} + } else if(strcmp(argv[i], "-C")==0 || + strcmp(argv[i], "-cdrecord-params")==0) { + if(i+1>=argc) + goto not_enough_args; + i++; + strncpy(msc, argv[i], sizeof(msc)-1); + msc[sizeof(msc)-1]= 0; + } else if(strcmp(argv[i], "-help")==0) { + Xorriso_option_report_about(xorriso, "NOTE", 0); + for(i= 0; strcmp(helptext[i], "@End_of_helptexT@")!=0; i++) { + sprintf(xorriso->info_text, "%s\n", helptext[i]); + Xorriso_info(xorriso, 1); + } + Xorriso_option_report_about(xorriso, ra_text, 0); + } else if(strcmp(argv[i], "-v")==0 || strcmp(argv[i], "-verbose")==0) { + strcpy(ra_text, "UPDATE"); + } else if(strcmp(argv[i], "-quiet")==0) { + strcpy(ra_text, "SORRY"); + } else if(strcmp(argv[i], "-f")==0 || strcmp(argv[i], "-follow-links")==0) { + ret= Xorriso_option_follow(xorriso, "on", 0); + if(ret<=0) + goto problem_handler_1; + } else if(strcmp(argv[i], "-iso-level")==0) { + if(i+1>=argc) + goto not_enough_args; + i++; + sscanf(argv[i], "%d", &iso_level); + if(iso_level < 1 || iso_level > 3) { + sprintf(xorriso->info_text, + "-as %s: unsupported -iso-level '%s' (use one of: 1,2,3)", + whom, argv[i]); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto problem_handler_1; + } + if(iso_level < 3) + xorriso->file_size_limit= + ((off_t) 4) * ((off_t) 1024*1024*1024) - ((off_t) 1); + else + xorriso->file_size_limit= 0; + } else if(strcmp(argv[i], "-no-emul-boot")==0) { + no_emul_boot= 1; + } else if(strcmp(argv[i], "-boot-info-table")==0) { + ; + } else if(strcmp(argv[i], "-b") == 0 || + strcmp(argv[i], "-eltorito-boot") == 0) { + if(i+1>=argc) + goto not_enough_args; + i++; + xorriso->boot_image_bin_path[0]= 0; + if(argv[i][0] != '/') + strcat(xorriso->boot_image_bin_path, "/"); + ret= Sfile_str(xorriso->boot_image_bin_path + + strlen(xorriso->boot_image_bin_path), argv[i], 0); + if(ret <= 0) + goto ex; + option_b= 1; + xorriso->keep_boot_image= 0; + xorriso->patch_isolinux_image= 0; + } else if(strcmp(argv[i], "-c") == 0 || + strcmp(argv[i], "-eltorito-catalog") == 0) { + if(i+1>=argc) + goto not_enough_args; + i++; + xorriso->boot_image_cat_path[0]= 0; + if(argv[i][0] != '/') + strcat(xorriso->boot_image_cat_path, "/"); + ret= Sfile_str(xorriso->boot_image_cat_path + + strlen(xorriso->boot_image_cat_path), argv[i], 0); + if(ret <= 0) + goto ex; + } else if(strcmp(argv[i], "-boot-load-size") == 0) { + if(i+1>=argc) + goto not_enough_args; + i++; + sscanf(argv[i], "%d", &ret); + xorriso->boot_image_load_size= ret * 512; + } else if(strncmp(argv[i], "isolinux_mbr=", 13)==0) { + sprintf(sfe, "isohybrid=%s", argv[i] + 13); + ret= Xorriso_option_boot_image(xorriso, "isolinux", sfe, 0); + if(ret <= 0) + goto problem_handler_1; + } else if(strcmp(argv[i], "-input-charset")==0) { + if(i+1>=argc) + goto not_enough_args; + i++; + /* -local_charset */ + if(strcmp(argv[i], "default") == 0) + ret= Xorriso_option_charset(xorriso, "ISO-8859-1", 4); + else + ret= Xorriso_option_charset(xorriso, argv[i], 4); + if(ret <= 0) + goto problem_handler_1; + } else if(strcmp(argv[i], "-output-charset")==0) { + if(i+1>=argc) + goto not_enough_args; + i++; + /* -charset */ + if(strcmp(argv[i], "default") == 0) + ret= Xorriso_option_charset(xorriso, "ISO-8859-1", 3); + else + ret= Xorriso_option_charset(xorriso, argv[i], 3); + if(ret <= 0) + goto problem_handler_1; + } else + was_other_option= 1; + + continue; /* regular bottom of loop */ +problem_handler_1:; + was_failure= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); + if(fret>=0) + continue; + goto ex; + } + Xorriso_option_report_about(xorriso, ra_text, 0); + if(adr[0]) { + if(strncmp(adr, "stdio:", 6)==0 && strncmp(adr, "stdio:/dev/fd/", 14)!=0) { + ret= Sfile_type(adr+6, 1); + if(ret==-1) { + /* ok */; + } else if(ret==2 || ret==3) { + sprintf(xorriso->info_text, + "-as %s: Cannot accept %s as target: -o %s", + whom, (ret==3 ? "symbolic link" : "directory"), + Text_shellsafe(adr+6, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + } + /* Regard overwriteable as blank, truncate regular files on write start */ + ret= Xorriso_option_dev(xorriso, adr, 2|8|16); + if(ret<=0) + goto ex; + } + if(option_b && !no_emul_boot) { + xorriso->boot_image_bin_path[0]= 0; + sprintf(xorriso->info_text, + "-as %s: Option -b is supported only if option -no-emul-boot is given", + whom); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + if(was_other_option && xorriso->out_drive_handle==NULL) { + ret= Xorriso_option_dev(xorriso, "-", 2|4); /* set outdev to stdout */ + if(ret<=0) + return(ret); + } + + if(msc[0]) { + cpt= strchr(msc, ','); + if(cpt==NULL) { +illegal_c:; + sprintf(xorriso->info_text, + "-as %s: unusable parameter with option -C: %s", + whom, Text_shellsafe(msc, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } else if(cpt==msc || msc[1]==0) + goto illegal_c; + strncpy(sfe, msc, cpt-msc); + sfe[cpt-msc]= 0; + if(xorriso->in_drive_handle!=NULL && indev[0]) { + /* give up indev before setting the load address */ + ret= Xorriso_option_dev(xorriso, "", 1); + if(ret<=0) + return(ret); + } + /* growisofs submits msc1+16 to avoid a theoretical bug in mkisofs. + Therefore this bug has to be emulated here. Sigh. + */ + ret= Xorriso_option_load(xorriso, "sbsector", sfe, 1); + if(ret<=0) + return(ret); + ret= Xorriso_option_grow_blindly(xorriso, cpt+1, 0); + if(ret<=0) + return(ret); + } + if(indev[0]) { + ret= Xorriso_option_dev(xorriso, indev, 1); + if(ret<=0) + goto ex; + } + + if(!was_other_option) + {ret= 1; goto ex;} + + xorriso->padding= 300*1024; + + for(i= 0; i<argc; i++) { + sprintf(xorriso->info_text, "-as %s: %s", + whom, Text_shellsafe(argv[i], sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + ret= Xorriso_genisofs_ignore(xorriso, whom, argv, &i, 0); + if(ret == 1) + continue; + if(strcmp(argv[i], "-version")==0) { + /* was already handled in first argument scan */; + + } else if(strcmp(argv[i], "-R")==0 || strcmp(argv[i], "-rock")==0) { + /* ok */; + } else if(strcmp(argv[i], "-J")==0 || strcmp(argv[i], "-joliet")==0) { + xorriso->do_joliet= 1; + } else if(strcmp(argv[i], "-graft-points")==0) { + xorriso->allow_graft_points= 1; + } else if(strcmp(argv[i], "-path-list")==0 || + strcmp(argv[i], "--quoted_path_list")==0) { + if(i+1>=argc) { +not_enough_args:; + sprintf(xorriso->info_text, "-as %s: Not enough arguments to option %s", + whom, argv[i]); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + i++; + was_path= 1; + xorriso->pacifier_style= 1; + ret= Xorriso_option_path_list(xorriso, argv[i], + (strcmp(argv[i-1], "--quoted_path_list")==0)); + if(ret<=0) + goto problem_handler_2; + } else if(strcmp(argv[i], "-f")==0 || strcmp(argv[i], "-follow-links")==0) { + /* was already handled in first argument scan */; + } else if(strcmp(argv[i], "-pad")==0) { + xorriso->padding= 300*1024; + } else if(strcmp(argv[i], "-no-pad")==0) { + xorriso->padding= 0; + } else if(strcmp(argv[i], "-print-size")==0) { + do_print_size= 1; + } else if(strcmp(argv[i], "-o")==0) { + i++; + /* was already handled in first argument scan */; + } else if(strcmp(argv[i], "-M")==0 || strcmp(argv[i], "-dev")==0) { + i++; + /* was already handled in first argument scan */; + } else if(strcmp(argv[i], "-C")==0) { + i++; + /* was already handled in first argument scan */; + } else if(strcmp(argv[i], "-help")==0) { + /* was already handled in first argument scan */; + } else if(strcmp(argv[i], "-V")==0 || strcmp(argv[i], "-volid")==0) { + if(i+1>=argc) + goto not_enough_args; + i++; + ret= Xorriso_option_volid(xorriso, argv[i], 0); + if(ret<=0) + goto problem_handler_2; + } else if(strcmp(argv[i], "-P")==0 || strcmp(argv[i], "-publisher")==0) { + if(i+1>=argc) + goto not_enough_args; + i++; + ret= Xorriso_option_publisher(xorriso, argv[i], 0); + if(ret<=0) + goto problem_handler_2; + } else if(strcmp(argv[i], "-m")==0 || strcmp(argv[i], "-exclude")==0 || + strcmp(argv[i], "-x")==0 || strcmp(argv[i], "-old-exclude")==0) { + if(i+1>=argc) + goto not_enough_args; + i++; + mem= xorriso->do_disk_pattern; + xorriso->do_disk_pattern= 1; + if(strchr(argv[i], '/')!=NULL) { + idx= i; + ret= Xorriso_option_not_paths(xorriso, i+1, argv, &idx, 0); + } else + ret= Xorriso_option_not_leaf(xorriso, argv[i], 0); + xorriso->do_disk_pattern= mem; + if(ret<=0) + goto problem_handler_2; + } else if(strcmp(argv[i], "-exclude-list")==0) { + if(i+1>=argc) + goto not_enough_args; + i++; + mem= xorriso->do_disk_pattern; + xorriso->do_disk_pattern= 1; + ret= Xorriso_option_not_list(xorriso, argv[i], 0); + xorriso->do_disk_pattern= mem; + if(ret<=0) + goto problem_handler_2; + } else if(strcmp(argv[i], "-v")==0 || strcmp(argv[i], "-quiet")==0) { + /* was already handled in first argument scan */; + + } else if(strcmp(argv[i], "-iso-level")==0) { + i++; + /* was already handled in first argument scan */; + } else if(strcmp(argv[i], "-no-emul-boot")==0) { + /* was already handled in first argument scan */; + } else if(strcmp(argv[i], "-b") == 0 || + strcmp(argv[i], "-eltorito-boot") == 0) { + i++; + /* was already handled in first argument scan */; + } else if(strcmp(argv[i], "-c") == 0 || + strcmp(argv[i], "-eltorito-catalog") == 0) { + i++; + /* was already handled in first argument scan */; + } else if(strncmp(argv[i], "isolinux_mbr=", 13)==0) { + /* was already handled in first argument scan */; + } else if(strcmp(argv[i], "-boot-load-size") == 0) { + i++; + /* was already handled in first argument scan */; + } else if(strcmp(argv[i], "-boot-info-table")==0) { + ; + } else if(strcmp(argv[i], "-input-charset")==0) { + i++; + /* was already handled in first argument scan */; + } else if(strcmp(argv[i], "-output-charset")==0) { + i++; + /* was already handled in first argument scan */; + } else if(argv[i][0]=='-' && argv[i][1]!=0) { + sprintf(xorriso->info_text, "-as %s: Unknown option %s", + whom, Text_shellsafe(argv[i], sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + } else { + int zero= 0; + + /* implementing mkisofs tendency to map single-path pathspecs to / */ + if((!xorriso->allow_graft_points) || + Fileliste__target_source_limit(argv[i], '=', &ept, 0)<=0) { + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, argv[i], + eff_path, 2|4); + if(ret<=0) + goto problem_handler_2; + ret= Sfile_type(eff_path, + 1|((xorriso->do_follow_param||xorriso->do_follow_links)<<2)); + if(ret==2) { + strcpy(pathspec, "/="); + } else { + pathspec[0]= '/'; + pathspec[1]= 0; + ret= Sfile_leafname(eff_path, pathspec+1, 0); + if(ret>0) + strcat(pathspec, "="); + else + pathspec[0]= 0; + } + strcat(pathspec, eff_path); + add_pt= pathspec; + } else + add_pt= argv[i]; + mem_graft_points= xorriso->allow_graft_points; + xorriso->allow_graft_points= 1; + ret= Xorriso_option_add(xorriso, 1, &add_pt, &zero, was_path<<1); + xorriso->allow_graft_points= mem_graft_points; + if(ret<=0) + goto problem_handler_2; + was_path= 1; + xorriso->pacifier_style= 1; + } + continue; /* regular bottom of loop */ +problem_handler_2:; + was_failure= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); + if(fret>=0) + continue; + goto ex; + } + if(do_print_size) { + ret= Xorriso_option_print_size(xorriso, 1); + if(ret<=0) + goto ex; + } + + ret= !was_failure; +ex:; + if(was_path && !do_print_size) + Xorriso_pacifier_callback(xorriso, "files added", xorriso->pacifier_count, + xorriso->pacifier_total, "", 1); + if(do_print_size && xorriso->volset_change_pending) + Xorriso_option_rollback(xorriso, 0); + return(ret); +} + + +int Xorriso_as_genisofs(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag) +{ + int end_idx, ret, idx_count, old_idx; + + old_idx= *idx; + end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1); + (*idx)= end_idx; + idx_count= end_idx-old_idx; + if(end_idx<=0 || old_idx>=argc) + return(1); + ret= Xorriso_genisofs(xorriso, "genisofs", end_idx-old_idx, argv+old_idx, 0); + return(ret); +} + + +int Xorriso_as_cdrskin(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag) +{ + int end_idx, ret, idx_count, old_idx; + + old_idx= *idx; + end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1); + (*idx)= end_idx; + idx_count= end_idx-old_idx; + if(end_idx<=0 || old_idx>=argc) + return(1); + ret= Xorriso_cdrskin(xorriso, "cdrskin", end_idx-old_idx, argv+old_idx, 0); + return(ret); +} + + +/* @param boss_iter Opaque handle to be forwarded to actions in ISO image + Set to NULL if calling this function from outside ISO world + @param flag bit2= -follow: this is not a command parameter + @return <=0 error, 1= ok , 2= iso_rr_path node object has been deleted , + 3= no action taken +*/ +int Xorriso_update_interpreter(struct XorrisO *xorriso, void *boss_iter, + int compare_result, char *disk_path, + char *iso_rr_path, int flag) +{ + int ret, deleted= 0, is_split= 0, i, loop_count; + char sfe[5*SfileadrL]; + struct stat stbuf; + struct SplitparT *split_parts= NULL; + int split_count= 0; + char part_path[SfileadrL], *part_name; + int partno, total_parts, new_total_parts; + off_t offset, bytes, total_bytes, disk_size, first_bytes; + + if((compare_result&3)==3) { + sprintf(xorriso->info_text, "Missing on disk and in ISO: disk_path %s", + Text_shellsafe(disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 1); + xorriso->find_compare_result= -1; + ret= 3; goto ex; + } + + if(compare_result&((1<<11)|(1<<13))) { + /* cannot open regular disk file, early eof of disk file */ + sprintf(xorriso->info_text, "Problems with reading disk file %s", + Text_shellsafe(disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 1); + xorriso->find_compare_result= -1; + ret= 1; goto ex; + } + xorriso->info_text[0]= 0; + is_split= !!(compare_result & (1<<17)); + + if(compare_result&(8|64)) { + /* file type, minor+major with device file */ + ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, iso_rr_path, 1); /* rm_r */ + if(ret>0) { + deleted= 1; + ret= Xorriso_graft_in(xorriso, boss_iter, disk_path, iso_rr_path, + (off_t) 0, (off_t) 0, 2|(flag&4)); + } + sprintf(xorriso->info_text, "Deleted and re-added "); + + } else if(compare_result&(1)) { +delete:; + /* disk_adr not existing */ + ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, iso_rr_path, 1); + deleted= 1; + sprintf(xorriso->info_text, "Deleted "); + + } else if(compare_result&(2|128|(1<<12)|(1<<14)|(1<<15))) { + /* iso_adr not existing, size, cannot open iso file, early eof of iso file + content bytes differ */ + + if(is_split) { + ret= Xorriso_identify_split(xorriso, iso_rr_path, NULL, + &split_parts, &split_count, &stbuf, 0); + if(ret<=0) + {ret= -1; goto ex;} /* (should not happen) */ + ret= lstat(disk_path, &stbuf); + if(ret==-1) + goto delete; + disk_size= stbuf.st_size; + Splitparts_get(split_parts, 0, &part_name, &partno, &total_parts, + &offset, &first_bytes, &total_bytes, 0); + new_total_parts= disk_size/first_bytes; + if(disk_size % first_bytes) + new_total_parts++; + + loop_count= split_count; + /* If disk file grew over part limit and all parts are present: + add new parts */ + if(new_total_parts > total_parts && split_count == total_parts) + loop_count= new_total_parts; + + for(i= 0; i<loop_count; i++) { + if(i<split_count) { + /* Delete old part */ + Splitparts_get(split_parts, i, &part_name, &partno, &total_parts, + &offset, &bytes, &total_bytes, 0); + strcpy(part_path, iso_rr_path); + if(Sfile_add_to_path(part_path, part_name, 0)<=0) { + Xorriso_much_too_long(xorriso, + strlen(iso_rr_path)+strlen(part_path)+1, 2); + {ret= -1; goto ex;} + } + ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, part_path, 1); + if(ret<=0) + goto ex; + deleted= 1; + } else { + partno= i+1; + offset= i*first_bytes; + } + if(disk_size<=offset) + continue; + /* Insert new part */ + if(strlen(part_path)+160>SfileadrL) { + Xorriso_much_too_long(xorriso, strlen(part_path)+160, 2); + ret= 0; goto ex; + } + Splitpart__compose(part_path+strlen(iso_rr_path)+1, partno, + new_total_parts, offset, first_bytes, disk_size, 0); + ret= Xorriso_graft_in(xorriso, boss_iter, disk_path, part_path, + offset, bytes, 2|(flag&4)|8|128); + if(ret<=0) + goto ex; + } + /* Copy file attributes to iso_rr_path, augment r-perms by x-perms */ + ret= Xorriso_copy_properties(xorriso, disk_path, iso_rr_path, 2); + if(ret<=0) + goto ex; + } else { + ret= Xorriso_graft_in(xorriso, boss_iter, disk_path, iso_rr_path, + (off_t) 0, (off_t) 0, 2|(flag&4)); + if(ret>0 && !(compare_result&2)) + deleted= 1; + } + sprintf(xorriso->info_text, "Added/overwrote "); + + } else if(compare_result&(4|16|32|256|512|1024)) { + /* access permissions, user id, group id, mtime, atime, ctime */ + + if(is_split) { + ret= Xorriso_identify_split(xorriso, iso_rr_path, NULL, + &split_parts, &split_count, &stbuf, 0); + if(ret<=0) + {ret= -1; goto ex;} /* (should not happen) */ + for(i= 0; i<split_count; i++) { + Splitparts_get(split_parts, i, &part_name, &partno, &total_parts, + &offset, &bytes, &total_bytes, 0); + strcpy(part_path, iso_rr_path); + if(Sfile_add_to_path(part_path, part_name, 0)<=0) { + Xorriso_much_too_long(xorriso, + strlen(iso_rr_path)+strlen(part_path)+1, 2); + {ret= -1; goto ex;} + } + ret= Xorriso_copy_properties(xorriso, disk_path, part_path, 0); + if(ret<=0) + goto ex; + } + /* Copy file attributes to iso_rr_path, augment r-perms by x-perms */ + ret= Xorriso_copy_properties(xorriso, disk_path, iso_rr_path, 2); + if(ret<=0) + goto ex; + } else + ret= Xorriso_copy_properties(xorriso, disk_path, iso_rr_path, 0); + sprintf(xorriso->info_text, "Adjusted attributes of "); + + } else + ret= 1; + if(ret>0 && xorriso->info_text[0]) { + strcat(xorriso->info_text, Text_shellsafe(iso_rr_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0); + } + ret= 1; +ex:; + if(split_parts!=NULL) + Splitparts_destroy(&split_parts, split_count, 0); + if(ret<=0) + return(ret); + if(deleted) + return(2); + return(ret); +} + + +int Xorriso_write_session_log(struct XorrisO *xorriso, int flag) +{ + FILE *fp= NULL; + char sfe[5*SfileadrL], timetext[40], *rpt, *wpt; + + if(xorriso->session_logfile[0]==0) + return(2); + fp= fopen(xorriso->session_logfile, "a"); + if(fp==0) { + sprintf(xorriso->info_text, "-session_log: Cannot open file %s", + Text_shellsafe(xorriso->session_logfile, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + wpt= sfe; + for(rpt= xorriso->volid; *rpt!=0; rpt++) { + if(*rpt=='\n') { + *(wpt++)= '\\'; + *(wpt++)= 'n'; + } else + *(wpt++)= *rpt; + } + *wpt= 0; + fprintf(fp, "%s %d %d %s\n", + Ftimetxt(time(0), timetext, 2), xorriso->session_lba, + xorriso->session_blocks, sfe); + fclose(fp); + return(1); +} + + +/* @param flag bit0= path is a command parameter +*/ +int Xorriso_path_is_excluded(struct XorrisO *xorriso, char *path, int flag) +{ + int ret; + char sfe[5*SfileadrL]; + + if(!(xorriso->disk_excl_mode&1)) /* exclusion is off */ + return(0); + if((flag&1) && !(xorriso->disk_excl_mode&2)) /* params are exempted */ + return(0); + ret= Exclusions_match(xorriso->disk_exclusions, path, + !!(xorriso->disk_excl_mode&4)); + if(ret<0) { + sprintf(xorriso->info_text, + "Error during disk file exclusion decision"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + } + if(ret>0 && (flag&1)) { + sprintf(xorriso->info_text, "Disk path parameter excluded by %s : %s", + (ret==1 ? "-not_paths" : "-not_leaf"), Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + } + return(ret); +} + + +int Xorriso_make_tmp_path(struct XorrisO *xorriso, char *orig_path, + char *tmp_path, int *fd, int flag) +{ + char *cpt; + + cpt= strrchr(orig_path, '/'); + if(cpt==NULL) + tmp_path[0]= 0; + else { + strncpy(tmp_path, orig_path, cpt+1-orig_path); + tmp_path[cpt+1-orig_path]= 0; + } + strcat(tmp_path, "_tmp_xorriso_restore_XXXXXX"); + *fd= mkstemp(tmp_path); + if(*fd==-1) { + strcpy(xorriso->info_text, "Cannot create temporary file : "); + Text_shellsafe(tmp_path, xorriso->info_text, 1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + return(0); + } + fchmod(*fd, S_IRUSR|S_IWUSR); + return(1); +} + + +int Xorriso_auto_chmod(struct XorrisO *xorriso, char *disk_path, int flag) +{ + int ret, is_link= 0; + char *path_pt, sfe[5*SfileadrL], link_target[SfileadrL]; + mode_t mode, desired= S_IRUSR | S_IWUSR | S_IXUSR; + struct stat stbuf; + + if(!xorriso->do_auto_chmod) + return(0); + + path_pt= disk_path; + ret= lstat(path_pt, &stbuf); + if(ret==-1) + return(0); + if(S_ISLNK(stbuf.st_mode)) { + is_link= 1; + ret= stat(path_pt, &stbuf); + if(ret==-1) + return(0); + } + if(!S_ISDIR(stbuf.st_mode)) + return(0); + if(is_link) { + ret= Xorriso_resolve_link(xorriso, path_pt, link_target, 0); + if(ret<=0) + return(ret); + path_pt= link_target; + } + if(stbuf.st_uid!=geteuid()) + return(0); + if((stbuf.st_mode & desired) == desired) + return(0); + + mode= (stbuf.st_mode | desired) & 07777; + ret= chmod(path_pt, mode); + if(ret==-1) { + sprintf(xorriso->info_text, + "Cannot change access permissions of disk directory: chmod %o %s", + mode & 07777, Text_shellsafe(path_pt, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "SORRY", 0); + } + ret= Permstack_push(&(xorriso->perm_stack), path_pt, &stbuf, 0); + if(ret<=0) + return(ret); + return(1); +} + + +/* @param flag bit0= mark untested areas as valid +*/ +int Xorriso_spotlist_to_sectormap(struct XorrisO *xorriso, + struct SpotlisT *spotlist, + int read_chunk, + struct SectorbitmaP **map, + int flag) +{ + struct SectorbitmaP *m; + int map_sectors= -1, map_sector_size= -1; + int list_sectors, list_blocks, sector_size, sector_blocks; + int replace_map= 0, count, i, lba, blocks, quality, ret; + + sector_size= Spotlist_sector_size(spotlist, read_chunk, 0); + sector_blocks= sector_size / 2048; + if(*map != NULL) + Sectorbitmap_get_layout(*map, &map_sectors, &map_sector_size, 0); + + count= Spotlist_count(spotlist, 0); + list_blocks= Spotlist_block_count(spotlist, 0); + + /* >>> ??? insist in list_blocks % sector_blocks == 0 */ + + list_sectors= list_blocks / sector_blocks; + if(list_sectors * sector_blocks < list_blocks) + list_sectors++; + if(*map != NULL && map_sectors * (map_sector_size / 2048) >= list_blocks && + map_sector_size == sector_size) + m= *map; + else { + if(*map != NULL) { + if(((off_t) (*map)->sectors) * ((off_t) (*map)->sector_size) > + ((off_t) list_sectors) * ((off_t) sector_size)) + list_sectors= (((off_t) (*map)->sectors) * + ((off_t) (*map)->sector_size)) / ((off_t) sector_size) + + 1; + } + ret= Sectorbitmap_new(&m, list_sectors, sector_size, 0); + if(ret <= 0) + return(-1); + replace_map= 1; + if(*map != NULL) { + ret= Sectorbitmap_copy(*map, m, 0); + if(ret <= 0) { + Sectorbitmap_destroy(&m, 0); + return(0); + } + } + } + + count= Spotlist_count(spotlist, 0); + for(i= 0; i < count; i++) { + ret= Spotlist_get_item(spotlist, i, &lba, &blocks, &quality, 0); + if(ret <= 0) + continue; + if(quality == Xorriso_read_quality_untesteD && !(flag & 1)) + continue; + Sectorbitmap_set_range(m, lba / sector_blocks, blocks / sector_blocks, + quality >= Xorriso_read_quality_untesteD); + } + if(replace_map) { + Sectorbitmap_destroy(map, 0); + *map= m; + } + return(1); +} + + +int Xorriso_sectormap_to_spotlist(struct XorrisO *xorriso, + struct CheckmediajoB *job, + struct SpotlisT **spotlist, + int flag) +{ + struct SectorbitmaP *map; + int ret, i, sectors, sector_size, value, old_value= -1, old_start= -1; + + map= job->sector_map; + if(map == NULL) + return(-1); + ret= Spotlist_new(spotlist, 0); + if(ret <= 0) + {ret= -1; goto ex;} + Sectorbitmap_get_layout(map, §ors, §or_size, 0); + sector_size/= 2048; + if(job->max_lba >= 0) + sectors= (job->max_lba + 1) / sector_size; + i= 0; + if(job->min_lba >= 0) + i= job->min_lba / sector_size; + for(; i < sectors; i++) { + value= Sectorbitmap_is_set(map, i, 0); + if(value == old_value) + continue; + if(old_value >= 0) { + ret= Spotlist_add_item(*spotlist, old_start, i * sector_size - old_start, + (old_value ? Xorriso_read_quality_valiD : + Xorriso_read_quality_invaliD), 0); + if(ret <= 0) + goto ex; + if(job->item_limit > 0 && + Spotlist_count(*spotlist, 0) + 1 >= job->item_limit) { + sprintf(xorriso->info_text, "-check_media: Reached item_limit=%d", + job->item_limit); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + if(sectors - i > 1) { + ret= Spotlist_add_item(*spotlist, i * sector_size, + (sectors - i - 1) * sector_size, + Xorriso_read_quality_untesteD, 0); + if(ret <= 0) + goto ex; + } + ret= 2; goto ex; + } + } + old_value= value; + old_start= i * sector_size; + } + if(old_value >= 0) { + ret= Spotlist_add_item(*spotlist, old_start, i * sector_size - old_start, + (old_value ? Xorriso_read_quality_valiD : + Xorriso_read_quality_invaliD), 0); + if(ret <= 0) + goto ex; + } + ret= 1; +ex:; + if(ret <= 0) + Spotlist_destroy(spotlist, 0); + return(ret); +} + + +int Xorriso_afile_fopen(struct XorrisO *xorriso, + char *filename, char *mode, FILE **ret_fp, int flag) +/* + bit0= do not print error message on failure +*/ +{ + FILE *fp= NULL; + + *ret_fp= NULL; + if(strcmp(filename,"-")==0) { + if(mode[0]=='a' || mode[0]=='w' || + (mode[0]=='r' && mode[1]=='+') || + (mode[0]=='r' && mode[1]=='b' && mode[2]=='+')) + fp= stdout; + else + fp= stdin; + } else if(strncmp(filename,"tcp:",4)==0){ + Xorriso_msgs_submit(xorriso, 0, "TCP/IP service isn't implemented yet.", 0, + "FAILURE", 0); + } else if(strncmp(filename,"file:",5)==0){ + fp= fopen(filename+5,mode); + } else { + fp= fopen(filename,mode); + } + if(fp==NULL){ + if(!(flag&1)) { + sprintf(xorriso->info_text, + "Failed to open file '%s' in %s mode\n", filename, mode); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + } + return(0); + } + *ret_fp= fp; + return(1); +} + + +/* @param flag bit2=do not try to read ISO heads +*/ +int Xorriso_toc_to_string(struct XorrisO *xorriso, char **toc_text, int flag) +{ + int ret, stack_handle, toc_ret, l; + struct Xorriso_lsT *results= NULL, *infos= NULL, *lpt; + + *toc_text= NULL; + ret= Xorriso_push_outlists(xorriso, &stack_handle, 1); + if(ret <= 0) + goto ex; + toc_ret= Xorriso_toc(xorriso, flag & 4); + ret= Xorriso_pull_outlists(xorriso, stack_handle, &results, &infos, 0); + if(ret <= 0) + goto ex; + if(toc_ret <= 0) + {ret= toc_ret; goto ex;} + l= 0; + for(lpt= results; lpt != NULL; lpt= Xorriso_lst_get_next(lpt, 0)) + l+= strlen(Xorriso_lst_get_text(lpt, 0)); + *toc_text= calloc(l + 1, 1); + l= 0; + for(lpt= results; lpt != NULL; lpt= Xorriso_lst_get_next(lpt, 0)) { + strcpy((*toc_text) + l, Xorriso_lst_get_text(lpt, 0)); + l+= strlen(Xorriso_lst_get_text(lpt, 0)); + } +ex:; + Xorriso_lst_destroy_all(&results, 0); + Xorriso_lst_destroy_all(&infos, 0); + return(ret); +} + + +int Xorriso_open_job_data_to(struct XorrisO *xorriso, + struct CheckmediajoB *job, int flag) +{ + char sfe[5*SfileadrL]; + + if(job->data_to_path[0] == 0) + return(2); + job->data_to_fd= open(job->data_to_path, O_RDWR | O_CREAT, + S_IRUSR | S_IWUSR); + if(job->data_to_fd == -1) { + sprintf(xorriso->info_text, "Cannot open path %s", + Text_shellsafe(job->data_to_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + return(0); + } + return(1); +} + +/* + @param flag bit0= make absolute command paths with known systems + bit1= do not allow prefixes with cmd + bit2= interpret unprefixed cmd as shell: +*/ +int Xorriso_make_mount_cmd(struct XorrisO *xorriso, char *cmd, + int lba, int track, int session, char *volid, + char *devadr, char result[SfileadrL], int flag) +{ + int ret, reg_file= 0, is_safe= 0, sys_code= 0; + char form[6*SfileadrL], session_text[12], track_text[12], lba_text[12]; + char *vars[5][2], sfe[5*SfileadrL], volid_sfe[5*80+1], *cpt, *sysname; + struct stat stbuf; + + if(strlen(cmd) > SfileadrL) { +/* +too_long:; +*/ + Xorriso_msgs_submit(xorriso, 0, "Argument much too long", 0, "FAILURE", 0); + return(0); + } + ret= stat(devadr, &stbuf); + if(ret != -1) + if(S_ISREG(stbuf.st_mode)) + reg_file= 1; + if(strncmp(cmd, "linux:", 6) == 0 && !(flag & 2)) { + cpt= cmd + 6; + sys_code= 1; + } else if(strncmp(cmd, "freebsd:", 8) == 0 && !(flag & 2)) { + cpt= cmd + 8; + sys_code= 2; + } else if(strncmp(cmd, "string:", 7) == 0 && !(flag & 2)) { + cpt= cmd + 7; + strcpy(form, cpt); + } else if(flag & 4) { + cpt= cmd; + strcpy(form, cpt); + } else { + cpt= cmd; + ret= System_uname(&sysname, NULL, NULL, NULL, 0); + if(ret <= 0) { + Xorriso_msgs_submit(xorriso, 0, + "-mount*: Cannot determine current system type", + 0, "FAILURE", 0); + return(0); + } else if(strcmp(sysname, "FreeBSD") == 0) { + sys_code= 2; + } else if(strcmp(sysname, "Linux") == 0) { + sys_code= 1; + } else { + sprintf(xorriso->info_text, "-mount*: Unsupported system type %s", + Text_shellsafe(sysname, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + } + + if(sys_code == 1) { /* Linux */ + sprintf(form, + "%smount -t iso9660 -o %snodev,noexec,nosuid,ro,sbsector=%%sbsector%% %%device%% %s", + (flag & 1 ? "/bin/" : ""), (reg_file ? "loop," : ""), + Text_shellsafe(cpt, sfe, 0)); + is_safe= 1; + } else if(sys_code == 2) { /* FreeBSD */ + if(reg_file) { + +/* <<< Considered to create vnode as of + J.R. Oldroyd <fbsd@opal.com>, 20 Nov 2008 + but for now refraining from creating that persistent file object + + strcpy(form, "n=$(mdconfig -a -t vnode -f %device%)"); + sprintf(form + strlen(form), + " && mount -t cd9660 -o noexec,nosuid -s %%sbsector%% /dev/\"$n\" %s", + Text_shellsafe(cmd+8, sfe, 0)); +*/ + + Xorriso_msgs_submit(xorriso, 0, + "Detected regular file as mount device with FreeBSD style command.", + 0, "FAILURE", 0); + Xorriso_msgs_submit(xorriso, 0, +"Command mdconfig -a -t vnode -f can create a device node which uses the file", + 0, "HINT", 0); + return(0); + } else + sprintf(form, + "%smount -t cd9660 -o noexec,nosuid -s %%sbsector%% %%device%% %s", + (flag & 1 ? "/sbin/" : ""), Text_shellsafe(cmd+8, sfe, 0)); + is_safe= 1; + } + sprintf(session_text, "%d", session); + sprintf(track_text, "%d", track); + sprintf(lba_text, "%d", lba); + vars[0][0]= "sbsector"; + vars[0][1]= lba_text; + vars[1][0]= "track"; + vars[1][1]= track_text; + vars[2][0]= "session"; + vars[2][1]= session_text; + vars[3][0]= "volid"; + vars[3][1]= Text_shellsafe(volid, volid_sfe, 0); + vars[4][0]= "device"; + vars[4][1]= Text_shellsafe(devadr, sfe, 0); + ret= Sregex_resolve_var(form, vars, 5, "%", "%", "%", result, SfileadrL, 0); + if(ret <= 0) + return(ret); + return(1 + is_safe); +} + + +int Xorriso_decode_load_adr(struct XorrisO *xorriso, char *cmd, + char *adr_mode, char *adr_value, + int *entity_code, char entity_id[81], + int flag) +{ + double num; + int l; + + if(strcmp(adr_mode, "auto")==0) + *entity_code= 0; + else if(strcmp(adr_mode, "session")==0) + *entity_code= 1; + else if(strcmp(adr_mode, "track")==0) + *entity_code= 2; + else if(strcmp(adr_mode, "lba")==0 || strcmp(adr_mode, "sbsector")==0) + *entity_code= 3 | ((flag&1) << 16); + else if(strcmp(adr_mode, "volid")==0) + *entity_code= 4; + else { + sprintf(xorriso->info_text, "%s: unknown address mode '%s'", cmd, adr_mode); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + l= strlen(adr_value); + if(l==0) + *entity_code= 0; + + if(*entity_code>=1 && *entity_code<= 3) { + num= Scanf_io_size(adr_value, 0); + if(*entity_code==3 && + (adr_value[l-1]<'0' || adr_value[l-1]>'9')) + num/= 2048.0; + sprintf(entity_id, "%.f", num); + } else { + if(strlen(adr_value)>80) { + sprintf(xorriso->info_text, "%s: address value too long (80 < %d)", + cmd, (int) strlen(adr_value)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + strcpy(entity_id, adr_value); + } + return(1); +} + + +/* + @param flag bit0= use env_path to find the desired program +return: + <=0 : error + 1 : done +*/ +int Xorriso_execv(struct XorrisO *xorriso, char *cmd, char *env_path, + int *status, int flag) +{ + int ret, argc= 0; + char **argv= NULL, *pathlist= NULL, *cpt, *npt, prog[SfileadrL]; + char sfe[5*SfileadrL]; + pid_t child_pid; + struct stat stbuf; + + wait3(NULL,WNOHANG,NULL); /* just to remove any old dead child */ + + ret= Sfile_make_argv("", cmd, &argc, &argv, 1|4|128); + if(ret <= 0) + goto ex; + if(argc < 1) + {ret= 0; goto ex;} + + strcpy(prog, argv[0]); + if((flag & 1) && strchr(argv[0], '/') == NULL) { + if(env_path == NULL) + env_path= "/bin:/sbin"; + else if(env_path[0] == 0) + env_path= "/bin:/sbin"; + if(Sregex_string(&pathlist, env_path, 0) <= 0) + {ret= -1; goto ex;} + for(cpt= npt= pathlist; npt != NULL; cpt= npt + 1) { + npt= strchr(cpt, ':'); + if(npt != NULL) + *npt= 0; + if(strlen(cpt) + strlen(argv[0]) + 1 >= SfileadrL) + {ret= -1; goto ex;} + sprintf(prog, "%s/%s", cpt, argv[0]); + ret= stat(prog, &stbuf); + if(ret != -1) + break; + prog[0]= 0; + } + if(prog[0] == 0) { + sprintf(xorriso->info_text, "Cannot find external program %s", + Text_shellsafe(argv[0], sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + } + + child_pid= fork(); + if(child_pid==-1) + return(-1); + + if(child_pid==0) { + /* this is the child process */ + + sprintf(xorriso->info_text, "Executing external program %s", + Text_shellsafe(prog, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + + execv(prog, argv); /* should never come back */ + fprintf(stderr,"--- execution of shell command failed:\n"); + fprintf(stderr," %s\n",cmd); + exit(127); + } + + + /* this is the original process waiting for child to exit */ + do { + /* try to read and print the reply */; + ret= waitpid(child_pid,status,WNOHANG); + if(ret==-1) { + if(errno!=EINTR) + ret= 0; goto ex; + } else if(ret==0) { + +#ifdef NIX + + /* >>> An interrupt key would be nice. */ + + if((flag&4)) { + ret= Asqueue_event_is_pending(agent->queue,0,0); + if(ret>0) { + Asagent_stderr(agent,"--- shell command interrupted",1); + kill(child_pid,SIGTERM); + ret= 2; goto ex; + } + } +#endif /* NIX */ + + continue; + } else { + break; + } + } while(1); + ret= 1; +ex: + Sfile_make_argv("", "", &argc, &argv, 2); + Sregex_string(&pathlist, NULL, 0); + return(ret); +} + + +/* ---------------------------- Options API ------------------------ */ + + +/* Option -abort_on */ +int Xorriso_option_abort_on(struct XorrisO *xorriso, char *severity, int flag) +{ + int ret, sev; + char sfe[5*SfileadrL]; + + ret= Xorriso__text_to_sev(severity, &sev, 0); + if(ret<=0) { + sprintf(xorriso->info_text, + "-abort_on: Not a known severity name : %s", + Text_shellsafe(severity, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(ret); + } + if(Sfile_str(xorriso->abort_on_text,severity,0)<=0) + return(-1); + xorriso->abort_on_severity= sev; + Xorriso_set_abort_severity(xorriso, 0); + return(1); +} + + +/* Option -add */ +/* @param flag bit0=do not report the added item + bit1=do not reset pacifier, no final pacifier message +*/ +int Xorriso_option_add(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag) +{ + int i, end_idx, ret, was_failure= 0, fret, optc= 0, split; + char target[SfileadrL], source[SfileadrL], *ept, eff_path[SfileadrL]; + char **optv= NULL, *rpt, *wpt; + + ret= Xorriso_opt_args(xorriso, "-add", argc, argv, *idx, &end_idx, + &optc, &optv, ((!!xorriso->allow_graft_points)<<2)|2); + if(ret<=0) + goto ex; + + if(!(flag&2)) + Xorriso_pacifier_reset(xorriso, 0); + for(i= 0; i<optc; i++) { + if(Sfile_str(target,optv[i],0)<=0) + {ret= -1; goto ex;} + strcpy(source, optv[i]); + split= 0; + if(xorriso->allow_graft_points) { + ret= Fileliste__target_source_limit(target, '=', &ept, 0); + if(ret>0) { + *ept= 0; + strcpy(source, ept+1); + split= 1; + } + /* unescape \= */; + if(split) + rpt= wpt= target; + else + rpt= wpt= source; + for(; *rpt!=0; rpt++) { + if(*rpt=='\\') + if(*(rpt+1)=='=') + continue; + *(wpt++)= *rpt; + } + *wpt= 0; + } + if(split==0) { + strcpy(target, source); + } else if(target[0]!='/') { + ret= Sfile_prepend_path(xorriso->wdi, target, 0); + if(ret<=0) + goto problem_handler; + } + + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, target, eff_path, 2); + if(ret<=0) + goto problem_handler; + strcpy(target, eff_path); + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, source,eff_path,2|4); + if(ret<=0) + goto problem_handler; + strcpy(source, eff_path); + + ret= Xorriso_graft_in(xorriso, NULL, source, target, (off_t)0, (off_t)0, 0); + if(ret<=0 || xorriso->request_to_abort) + goto problem_handler; + sprintf(xorriso->info_text, "Added to ISO image: %s '%s'='%s'\n", + (ret>1 ? "directory" : "file"), (target[0] ? target : "/"), source); + if(!(flag&1)) + Xorriso_info(xorriso, 0); + + continue; /* regular bottom of loop */ +problem_handler:; + was_failure= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); + if(fret>=0) + continue; + goto ex; + } + if(!(flag&2)) + Xorriso_pacifier_callback(xorriso, "files added", xorriso->pacifier_count, + xorriso->pacifier_total, "", 1); + ret= 1; +ex:; + (*idx)= end_idx; + Xorriso_opt_args(xorriso, "-add", argc, argv, *idx, &end_idx, &optc, &optv, + 256); + if(ret<=0) + return(ret); + return(!was_failure); +} + + +/* Option -add_plainly "none"|"unknown" */ +int Xorriso_option_add_plainly(struct XorrisO *xorriso, char *mode,int flag) +{ + if(strcmp(mode, "none")==0) + xorriso->add_plainly= 0; + if(strcmp(mode, "unknown")==0) + xorriso->add_plainly= 1; + else if(strcmp(mode, "dashed")==0) + xorriso->add_plainly= 2; + else if(strcmp(mode, "any")==0) + xorriso->add_plainly= 3; + else { + sprintf(xorriso->info_text, "-add_plainly: unknown mode '%s'", mode); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + return(1); +} + + +/* Option -alter_date , -alter_date_r */ +/* @param flag bit0=recursive (-alter_date_r) +*/ +int Xorriso_option_alter_date(struct XorrisO *xorriso, + char *time_type, char *timestring, + int argc, char **argv, int *idx, int flag) +{ + int i, ret, was_failure= 0, t_type= 0, end_idx, fret; + time_t t; + int optc= 0; + char **optv= NULL; + struct FindjoB *job= NULL; + struct stat dir_stbuf; + + ret= Xorriso_opt_args(xorriso, "-alter_date", argc, argv, *idx, &end_idx, + &optc, &optv, 0); + if(ret<=0) + goto ex; + ret= Xorriso_convert_datestring(xorriso, "-alter_date", time_type, timestring, + &t_type, &t, 0); + if(ret<=0) + goto ex; + for(i= 0; i<optc; i++) { + if(flag&1) { + ret= Findjob_new(&job, optv[i], 0); + if(ret<=0) { + Xorriso_no_findjob(xorriso, "-chmod_r", 0); + {ret= -1; goto ex;} + } + Findjob_set_action_ad(job, t_type, t, 0); + ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0, + NULL, optv[i], &dir_stbuf, 0, 0); + Findjob_destroy(&job, 0); + } else + ret= Xorriso_set_time(xorriso, optv[i], t, t_type); + if(ret>0 && !xorriso->request_to_abort) + continue; /* regular bottom of loop */ + was_failure= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); + if(fret>=0) + continue; + goto ex; + } + ret= 1; +ex:; + (*idx)= end_idx; + Xorriso_opt_args(xorriso, "-alter_date", argc, argv, *idx, &end_idx, &optc, + &optv, 256); + Findjob_destroy(&job, 0); + if(ret<=0) + return(ret); + return(!was_failure); +} + + +/* Option -application_id */ +int Xorriso_option_application_id(struct XorrisO *xorriso, char *name, + int flag) +{ + if(strlen(name)>=sizeof(xorriso->application_id)) { + sprintf(xorriso->info_text, + "Name too long with option -application_id (%d > %d)", + (int) strlen(name), (int) sizeof(xorriso->application_id)-1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + if(Sfile_str(xorriso->application_id,name,0)<=0) + return(-1); + return(1); +} + + +/* Option -as */ +/* @param flag bit0=do not report the added item + bit1=do not reset pacifier, no final pacifier message +*/ +int Xorriso_option_as(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag) +{ + int end_idx, ret, idx_count; + + end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1); + idx_count= end_idx-(*idx); + if(end_idx<=0 || (*idx)>=argc) { + if(idx_count<1) + sprintf(xorriso->info_text, + "-as : Not enough arguments given. Needed: whom do_what %s", + xorriso->list_delimiter); + else + sprintf(xorriso->info_text, + "-as %s : Not enough arguments given. Needed: do_what %s", + argv[*idx], xorriso->list_delimiter); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + if(strcmp(argv[*idx], "cdrecord")==0 || strcmp(argv[*idx], "wodim")==0 || + strcmp(argv[*idx], "cdrskin")==0 || strcmp(argv[*idx], "xorrecord")==0) { + ret= Xorriso_cdrskin(xorriso, argv[*idx], end_idx-(*idx)-1, argv+(*idx)+1, + 0); + if(ret<=0) + goto ex; + } else if(strcmp(argv[*idx], "mkisofs")==0 || + strcmp(argv[*idx], "genisoimage")==0 || + strcmp(argv[*idx], "genisofs")==0 || + strcmp(argv[*idx], "xorrisofs")==0) { + ret= Xorriso_genisofs(xorriso, argv[*idx], end_idx-(*idx)-1, argv+(*idx)+1, + 0); + if(ret<=0) + goto ex; + } else { + sprintf(xorriso->info_text, + "-as : Not a known emulation personality: '%s'", argv[*idx]); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + + ret= 1; +ex:; + (*idx)= end_idx; + return(ret); +} + + +/* Option -assert_volid */ +int Xorriso_option_assert_volid(struct XorrisO *xorriso, char *pattern, + char *severity, int flag) +{ + int ret, sev; + char *sev_text= ""; + + if(strlen(pattern)>=sizeof(xorriso->assert_volid)) { + sprintf(xorriso->info_text, + "Name too long with option -application_id (%d > %d)", + (int) strlen(pattern), (int) sizeof(xorriso->assert_volid)-1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + if(pattern[0]) { + ret= Sregex_match(pattern, "", 1); + if(ret <= 0) { + sprintf(xorriso->info_text, "-assert_volid: Cannot use given pattern."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + } + if(severity[0] != 0 || pattern[0] != 0) { + if(severity[0] == 0) + sev_text= xorriso->abort_on_text; + else + sev_text= severity; + if(strcmp(sev_text, "NEVER") == 0) + sev_text= "ABORT"; + ret= Xorriso__text_to_sev(sev_text, &sev, 0); + if(ret<=0) { + sprintf(xorriso->info_text, "-assert_volid: Not a known severity name : "); + Text_shellsafe(severity, xorriso->info_text, 1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(ret); + } + } + if(Sfile_str(xorriso->assert_volid, pattern,0) <= 0) + return(-1); + strcpy(xorriso->assert_volid_sev, sev_text); + return(1); +} + + +/* Option -backslash_codes */ +int Xorriso_option_backslash_codes(struct XorrisO *xorriso, char *mode, + int flag) +{ + char *npt, *cpt; + int l, was; + + was= xorriso->bsl_interpretation; + xorriso->bsl_interpretation= 0; + npt= cpt= mode; + for(; npt!=NULL; cpt= npt+1) { + npt= strchr(cpt,':'); + if(npt==NULL) + l= strlen(cpt); + else + l= npt-cpt; + if(l == 0) + continue; + if(l == 3 && strncmp(cpt, "off", l)==0) { + xorriso->bsl_interpretation= 0; + } else if(l == 16 && strncmp(cpt, "in_double_quotes", l)==0) { + xorriso->bsl_interpretation= (xorriso->bsl_interpretation & ~3) | 1; + } else if(l == 9 && strncmp(cpt, "in_quotes", l)==0) { + xorriso->bsl_interpretation= (xorriso->bsl_interpretation & ~3) | 2; + } else if(l == 17 && strncmp(cpt, "with_quoted_input", l)==0) { + xorriso->bsl_interpretation= (xorriso->bsl_interpretation & ~3) | 3; + } else if(l == 22 && strncmp(cpt, "with_program_arguments", l)==0) { + xorriso->bsl_interpretation= xorriso->bsl_interpretation | 16; + } else if(l == 13 && strncmp(cpt, "encode_output", l)==0) { + xorriso->bsl_interpretation= xorriso->bsl_interpretation | 32 | 64; + } else if(l == 14 && strncmp(cpt, "encode_results", l)==0) { + xorriso->bsl_interpretation= xorriso->bsl_interpretation | 32; + } else if(l == 12 && strncmp(cpt, "encode_infos", l)==0) { + xorriso->bsl_interpretation= xorriso->bsl_interpretation | 64; + } else if(l == 2 && strncmp(cpt, "on", l)==0) { + xorriso->bsl_interpretation= 3 | 16 | 32 | 64; + } else { + if(l<SfileadrL) + sprintf(xorriso->info_text, "-backslash_codes: unknown mode '%s'", cpt); + else + sprintf(xorriso->info_text, + "-backslash_codes: oversized mode parameter (%d)", l); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + xorriso->bsl_interpretation= was; + return(0); + } + } + return(1); +} + + +/* Option -ban_stdio_write */ +int Xorriso_option_ban_stdio_write(struct XorrisO *xorriso, int flag) +{ + xorriso->ban_stdio_write= 1; + return(1); +} + + +/* Option -blank and -format */ +/* @param flag bit0= format rather than blank + @return <=0 error , 1 success, 2 revoked by -reassure +*/ +int Xorriso_option_blank(struct XorrisO *xorriso, char *mode, int flag) +{ + char drive_name[SfileadrL], *cmd= "-blank"; + int aq_ret, ret, aq_flag= 2, mode_flag= 0, as_needed= 0, idx; + off_t size= 0; + + if(flag&1) + cmd= "-format"; + if(xorriso->out_drive_handle == NULL) { + sprintf(xorriso->info_text, + "%s: No output drive set by -dev -or -outdev", cmd); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + if(xorriso->in_drive_handle == xorriso->out_drive_handle) { + if(xorriso->volset_change_pending) { + sprintf(xorriso->info_text, + "%s: Image changes pending. -commit or -rollback first.", cmd); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + aq_flag= 3; + } + ret= Xorriso_reassure(xorriso, cmd, + "possibly make unreadable data on outdev", 0); + if(ret<=0) + return(2); + + if(strcmp(mode, "as_needed")==0 || mode[0]==0) + as_needed= 1; + else if(strcmp(mode, "all")==0 || strcmp(mode, "full")==0) + mode_flag= 0; + else if((strcmp(mode, "deformat")==0 || + strcmp(mode, "deformat_sequential")==0) && !(flag&1)) + mode_flag= 2; + else if((strcmp(mode, "deformat_quickest")==0 || + strcmp(mode, "deformat_sequential_quickest")==0) && !(flag&1)) + mode_flag= 3; + else if(strcmp(mode, "fast")==0) + mode_flag= 1; + else if(strncmp(mode, "by_index_", 9)==0 && (flag&1)) { + mode_flag= 128; + idx= -1; + if(strlen(mode)>9) + sscanf(mode+9, "%d", &idx); + if(idx<0 || idx>255) { +unusable_index:; + sprintf(xorriso->info_text, + "-format: mode '%s' provides unusable index number", mode); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + mode_flag|= (idx<<8); + } else if(strncmp(mode, "fast_by_index_", 14)==0 && (flag&1)) { + mode_flag= 1 | 128; + idx= -1; + if(strlen(mode)>14) + sscanf(mode+14, "%d", &idx); + if(idx<0 || idx>255) + goto unusable_index; + mode_flag|= (idx<<8); + } else if(strncmp(mode, "by_size_", 8) == 0 && (flag & 1)) { + size= (off_t) Scanf_io_size(mode + 8, 0); + if(size <= 0) { +unusable_size:; + sprintf(xorriso->info_text, + "-format: mode '%s' provides unusable size value", mode); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + mode_flag= 2; + } else if(strncmp(mode, "fast_by_size_", 13) == 0 && (flag & 1)) { + size= (off_t) Scanf_io_size(mode + 13, 0); + if(size <= 0) + goto unusable_size; + mode_flag= 3; + } else { + sprintf(xorriso->info_text, + "%s: Unknown %s mode '%s'", + cmd, ((flag&1) ? "-format" : "-blank"), mode); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + if(as_needed) + ret= Xorriso_blank_as_needed(xorriso, (flag&1)<<2); + else if(flag&1) + ret= Xorriso_format_media(xorriso, size, mode_flag & 0xff83); + else + ret= Xorriso_blank_media(xorriso, mode_flag&3); + if(ret==0) + return(ret); + strcpy(drive_name, xorriso->outdev); + if(ret <= 0) { /* in case of success, above functions will have re-aquired */ + aq_ret= Xorriso_reaquire_outdev(xorriso, 0); /* actually give up drive */ + if(ret<aq_ret) + return(ret); + if(aq_ret<=0) + return(aq_ret); + } + return(1); +} + + +/* Option -boot_image */ +int Xorriso_option_boot_image(struct XorrisO *xorriso, char *form, + char *treatment, int flag) +{ + int was_ok= 1, ret; + char *formpt, *treatpt; + double num; + + formpt= form; + if(formpt[0]=='-') + formpt++; + treatpt= treatment; + if(treatpt[0]=='-') + treatpt++; + if(strcmp(formpt, "any")==0) { + if(strcmp(treatpt, "keep")==0) { + xorriso->keep_boot_image= 1; + xorriso->patch_isolinux_image= 0; + xorriso->boot_image_bin_path[0]= 0; + } else if(strcmp(treatpt, "discard")==0) { + xorriso->keep_boot_image= 0; + xorriso->patch_isolinux_image= 0; + xorriso->boot_image_bin_path[0]= 0; + } else if(strcmp(treatpt, "show_status")==0) { +show_status:; + sprintf(xorriso->result_line, "------------------------------------\n"); + Xorriso_result(xorriso, 0); + sprintf(xorriso->result_line, "Status of loaded boot image :\n"); + Xorriso_result(xorriso, 0); + sprintf(xorriso->result_line, "------------------------------------\n"); + Xorriso_result(xorriso, 0); + Xorriso_show_boot_info(xorriso, 0); + sprintf(xorriso->result_line, "------------------------------------\n"); + Xorriso_result(xorriso, 0); + sprintf(xorriso->result_line, "Boot image settings for next commit:\n"); + Xorriso_result(xorriso, 0); + sprintf(xorriso->result_line, "------------------------------------\n"); + Xorriso_result(xorriso, 0); + Xorriso_status(xorriso, "-boot_image", NULL, 0); + sprintf(xorriso->result_line, "------------------------------------\n"); + Xorriso_result(xorriso, 0); + } else + was_ok= 0; + } else if(strcmp(formpt, "isolinux")==0) { + if(strcmp(treatpt, "patch")==0 || + strcmp(treatpt, "keep")==0) { /* no real "keep" with ISOLINUX */ + xorriso->keep_boot_image= 1; + xorriso->patch_isolinux_image= 1; + xorriso->boot_image_bin_path[0]= 0; + } else if(strcmp(treatpt, "discard")==0) { + xorriso->keep_boot_image= 0; + xorriso->patch_isolinux_image= 0; + xorriso->boot_image_bin_path[0]= 0; + } else if(strcmp(treatpt, "show_status")==0) { + goto show_status; + } else if(strncmp(treatpt, "dir=", 4) == 0) { + /* The three locations mentioned in http://syslinux.zytor.com/iso.php */ + if(strcmp(treatpt + 4, "/") == 0) + strcpy(xorriso->boot_image_bin_path, "/"); + else if(strcmp(treatpt + 4, "isolinux") == 0 + || strcmp(treatpt + 4, "/isolinux") == 0) + strcpy(xorriso->boot_image_bin_path, "/isolinux/"); + else if(strcmp(treatpt + 4, "boot/isolinux") == 0 + || strcmp(treatpt + 4, "/boot/isolinux") == 0 + || strcmp(treatpt + 4, "boot") == 0 + || strcmp(treatpt + 4, "/boot") == 0) + strcpy(xorriso->boot_image_bin_path, "/boot/isolinux/"); + else { + sprintf(xorriso->info_text, + "Unrecognized keyword with -boot_image %s %s", + form, treatment); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + sprintf(xorriso->info_text, + "Allowed with dir= are / , /isolinux . /boot/isolinux"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0); + return(0); + } + strcpy(xorriso->boot_image_cat_path, xorriso->boot_image_bin_path); + strcat(xorriso->boot_image_bin_path, "isolinux.bin"); + strcat(xorriso->boot_image_cat_path, "boot.cat"); + xorriso->boot_image_load_size= 4 * 512; + xorriso->keep_boot_image= 0; + xorriso->patch_isolinux_image= 0; + } else if(strncmp(treatpt, "bin_path=", 9) == 0) { + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, treatpt + 9, + xorriso->boot_image_bin_path, 2); + if(ret <= 0) + return(ret); + xorriso->keep_boot_image= 0; + xorriso->patch_isolinux_image= 0; + if(xorriso->boot_image_bin_path[0]) + xorriso->boot_image_load_size= 4 * 512; + } else if(strncmp(treatpt, "cat_path=", 9) == 0) { + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, treatpt + 9, + xorriso->boot_image_cat_path, 2); + if(ret <= 0) + return(ret); + } else if(strncmp(treatpt, "load_size=", 10) == 0) { + num= Scanf_io_size(treatpt + 10, 0); + if(num < 512) { + sprintf(xorriso->info_text, + "-boot_image isolinux : load_size too small (%s < 512)", + treatpt + 10); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + xorriso->boot_image_load_size= num; + } else if(strncmp(treatpt, "isohybrid=", 10) == 0) { + if(strcmp(treatpt + 10, "off") == 0) + xorriso->boot_image_isohybrid= 0; + else if(strcmp(treatpt + 10, "auto") == 0) + xorriso->boot_image_isohybrid= 1; + else if(strcmp(treatpt + 10, "on") == 0) + xorriso->boot_image_isohybrid= 2; + else if(strcmp(treatpt + 10, "force") == 0) + xorriso->boot_image_isohybrid= 3; + else { + sprintf(xorriso->info_text, + "Unrecognized keyword with -boot_image %s %s", + form, treatment); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + sprintf(xorriso->info_text, + "Allowed with isohybrid= are: off , auto , on , force"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0); + return(0); + + } + } else + was_ok= 0; + } else + was_ok= 0; + + /* >>> BOOT : check whether directories and/or files exist: + bin_path , dirname(cat_path), + isolinux.cfg in / , /isolinux , or /boot/isolinux + */ + + if(!was_ok) { + sprintf(xorriso->info_text, "Unrecognized options with -boot_image: %s %s", + form, treatment); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + return(1); +} + + +/* Option -cd alias -cdi */ +int Xorriso_option_cdi(struct XorrisO *xorriso, char *iso_rr_path, int flag) +{ + char sfe[5*SfileadrL], path[SfileadrL], eff_path[SfileadrL]; + int ret; + + if (strlen(iso_rr_path)>sizeof(xorriso->wdi)) { + sprintf(xorriso->info_text,"-cdi: iso_rr_path too long (%d > %d)", + (int) strlen(iso_rr_path), (int) sizeof(xorriso->wdi)-1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + Xorriso_warn_of_wildcards(xorriso, iso_rr_path, 1); + sprintf(xorriso->info_text,"previous working directory:\n"); + Xorriso_info(xorriso,0); + sprintf(xorriso->result_line,"%s/\n",Text_shellsafe(xorriso->wdi, sfe, 0)); + Xorriso_result(xorriso,0); + if(strcmp(iso_rr_path,"/")==0 || iso_rr_path[0]==0) { + strcpy(xorriso->wdi,""); + Xorriso_option_pwdi(xorriso, 0); + return(1); + } else if(iso_rr_path[0]!='/') { + strcpy(path, xorriso->wdi); + if(Sfile_add_to_path(path,iso_rr_path,0)<=0) + return(-1); + } else { + if(Sfile_str(path,iso_rr_path,0)<=0) + return(-1); + } + + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, path, eff_path, 1); + if(ret<0) + return(ret); + if(ret==0) { + sprintf(xorriso->info_text, "-cdi: not existing yet in ISO image : %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, path, eff_path, 2); + if(ret<=0) + return(ret); + } else if(ret!=2) { + sprintf(xorriso->info_text, "-cdi: not a directory : %s", + Text_shellsafe(eff_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + strcpy(xorriso->wdi, eff_path); + + Xorriso_option_pwdi(xorriso, 0); + return(1); +} + + +/* Option -cdx */ +int Xorriso_option_cdx(struct XorrisO *xorriso, char *disk_path, int flag) +{ + char sfe[5*SfileadrL], path[SfileadrL], eff_path[SfileadrL]; + int ret; + + if (strlen(disk_path)>sizeof(xorriso->wdx)) { + sprintf(xorriso->info_text,"-cdx: disk_path too long (%d > %d)", + (int) strlen(disk_path), (int) sizeof(xorriso->wdx)-1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + Xorriso_warn_of_wildcards(xorriso, disk_path, 1|2); + sprintf(xorriso->info_text,"previous working directory on hard disk:\n"); + Xorriso_info(xorriso,0); + sprintf(xorriso->result_line,"%s/\n",Text_shellsafe(xorriso->wdx, sfe, 0)); + Xorriso_result(xorriso,0); + if(strcmp(disk_path,"/")==0) { + strcpy(xorriso->wdx,""); + Xorriso_option_pwdx(xorriso, 0); + return(1); + } else if(disk_path[0]!='/') { + strcpy(path, xorriso->wdx); + if(Sfile_add_to_path(path,disk_path,0)<=0) + return(-1); + } else { + if(Sfile_str(path,disk_path,0)<=0) + return(-1); + } + + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, path, eff_path, 2|4); + if(ret<=0) + return(ret); + if(eff_path[0]) { + ret= Sfile_type(eff_path,1|4|8); + if(ret<0) { + Xorriso_msgs_submit(xorriso, 0, eff_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text,"-cdx: file not found : %s", + Text_shellsafe(eff_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + if(ret!=2) { + Xorriso_msgs_submit(xorriso, 0, eff_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, + "-cdx: not a directory : %s", + Text_shellsafe(eff_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + } + if(Sfile_str(xorriso->wdx,eff_path,0)<=0) + return(-1); + Xorriso_option_pwdx(xorriso, 0); + return(1); +} + + +/* Option -charset */ +/* @param flag bit0= set in_charset + bit1= set out_charset + bit2= set local_charset +*/ +int Xorriso_option_charset(struct XorrisO *xorriso, char *name, int flag) +{ + int ret; + char *name_pt= NULL, sfe[5 * SfileadrL], *local_charset; + iconv_t iconv_ret= (iconv_t) -1; + + if(name != NULL) + if(name[0] != 0) + name_pt= name; + if(flag & 4) { + ret= Xorriso_set_local_charset(xorriso, name_pt, 0); + if(ret <= 0) + return(ret); + } + if(flag & 1) { + if(name_pt != NULL) { + Xorriso_get_local_charset(xorriso, &local_charset, 0); + iconv_ret= iconv_open(local_charset, name_pt); + if(iconv_ret == (iconv_t) -1) { + sprintf(xorriso->info_text, + "-%scharset: Cannot convert from character set %s", + flag & 2 ? "" : "in_", Text_shellsafe(name_pt, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", + 0); + return(0); + } else + iconv_close(iconv_ret); + } + if(Sregex_string(&(xorriso->in_charset), name_pt, 0) <= 0) { + Xorriso_no_malloc_memory(xorriso, NULL, 0); + return(-1); + } + } + if(flag & 2) { + if(name_pt != NULL) { + Xorriso_get_local_charset(xorriso, &local_charset, 0); + iconv_ret= iconv_open(local_charset, name_pt); + if(iconv_ret == (iconv_t) -1) { + sprintf(xorriso->info_text, "-%scharset: Cannot convert to charset %s", + flag & 1 ? "" : "out_", Text_shellsafe(name_pt, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", + 0); + return(0); + } else + iconv_close(iconv_ret); + } + if(Sregex_string(&(xorriso->out_charset), name_pt, 0) <= 0) { + Xorriso_no_malloc_memory(xorriso, NULL, 0); + return(-1); + } + } + if(flag & 3) { + if(name_pt == NULL) + Xorriso_get_local_charset(xorriso, &name_pt, 0); + sprintf(xorriso->info_text, "Character set for %sconversion is now: %s", + (flag & 3) == 1 ? "input " : (flag & 3) == 2 ? "output " : "", + Text_shellsafe(name_pt, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + } + return(1); +} + + +/* Option -check_media */ +int Xorriso_option_check_media(struct XorrisO *xorriso, + int argc, char **argv, int *idx, int flag) +{ + int ret, i, count, lba, blocks, quality; + int end_idx, old_idx, os_errno; + char quality_name[80], head_buffer[64*1024]; + struct SpotlisT *spotlist= NULL; + struct CheckmediajoB *job= NULL; + struct FindjoB *findjob= NULL; + struct stat dir_stbuf; + + old_idx= *idx; + end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1); + (*idx)= end_idx; + + ret= Checkmediajob_new(&job, 0); + if(ret <= 0) + goto ex; + ret= Xorriso_check_media_setup_job(xorriso, job, argv, old_idx, end_idx, 0); + if(ret <= 0) + goto ex; + + if((job->report_mode == 1 || job->report_mode == 2) && job->use_dev == 1) { + sprintf(xorriso->info_text, + "-check_media: cannot report=*files while use=outdef"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + if(job->patch_lba0 && job->data_to_path[0] == 0) { + sprintf(xorriso->info_text, + "-check_media: cannot apply patch_lba0= while data_to= has empty value"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + + if(job->use_dev == 2) { + if(job->sector_map_path[0] == 0) { + sprintf(xorriso->info_text, + "-check_media: option use=sector_map but sector_map=''"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + ret= Sectorbitmap_from_file(&(job->sector_map), job->sector_map_path, + xorriso->info_text, &os_errno, 0); + if(ret <= 0) { + if(xorriso->info_text[0]) + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, os_errno, + "FAILURE", 0); + goto ex; + } + ret= Xorriso_sectormap_to_spotlist(xorriso, job, &spotlist, 0); + if(ret <= 0) + goto ex; + Sectorbitmap_destroy(&(xorriso->in_sector_map), 0); + ret= Sectorbitmap_clone(job->sector_map, &(xorriso->in_sector_map), 0); + if(ret <= 0) + goto ex; + } else { + ret= Xorriso_check_media(xorriso, &spotlist, job, 0); + if(ret <= 0) + goto ex; + } + + if(job->patch_lba0) { + ret= Xorriso_open_job_data_to(xorriso, job, 0); + if(ret <= 0) + goto ex; + if(ret == 1) { + ret= Xorriso_update_iso_lba0(xorriso, job->patch_lba0_msc1, 0, + head_buffer, job, + (8 * (job->patch_lba0 == 1)) | + 4 | (job->patch_lba0_msc1 < 0)); + if(ret <= 0) + goto ex; + } + } + + if(job->report_mode == 0 || job->report_mode == 2) { /* report blocks */ + sprintf(xorriso->result_line, + "MCL layout : lba , size , quality\n"); + Xorriso_result(xorriso,0); + count= Spotlist_count(spotlist, 0); + for(i= 0; i < count; i++) { + ret= Spotlist_get_item(spotlist, i, &lba, &blocks, &quality, 0); + if(ret <= 0) + continue; + sprintf(xorriso->result_line, "MCL item : %10d , %10d , %s\n", + lba, blocks, Spotlist__quality_name(quality, quality_name, 0)); + Xorriso_result(xorriso,0); + } + } + if(job->report_mode == 1 || job->report_mode == 2) { /* report files */ + ret= Findjob_new(&findjob, "/", 0); + if(ret<=0) { + Xorriso_no_findjob(xorriso, "-check_media report=files", 0); + {ret= -1; goto ex;} + } + Findjob_set_damage_filter(findjob, 1, 0); + Findjob_set_action_target(findjob, 21, NULL, 0); + ret= Xorriso_findi(xorriso, findjob, NULL, (off_t) 0, + NULL, "/", &dir_stbuf, 0, 0); + Findjob_destroy(&findjob, 0); + if(ret <= 0) + goto ex; + } + ret= 1; +ex:; + Spotlist_destroy(&spotlist, 0); + Checkmediajob_destroy(&job, 0); + return(ret); +} + + +/* Option -check_media_defaults */ +int Xorriso_option_check_media_defaults(struct XorrisO *xorriso, + int argc, char **argv, int *idx, int flag) +{ + int ret, old_idx, end_idx; + struct CheckmediajoB *job= NULL; + + old_idx= *idx; + end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1); + (*idx)= end_idx; + + ret= Checkmediajob_new(&job, 0); + if(ret <= 0) + goto ex; + ret= Xorriso_check_media_setup_job(xorriso, job, argv, old_idx, end_idx, 0); + if(ret <= 0) + goto ex; + Checkmediajob_destroy(&(xorriso->check_media_default), 0); + xorriso->check_media_default= job; + job= NULL; + ret= 1; +ex:; + Checkmediajob_destroy(&job, 0); + return(ret); +} + + +/* Option -chgrp alias -chgrpi , chgrp_r alias chgrpi */ +/* @param flag bit0=recursive (-chgrp_r) +*/ +int Xorriso_option_chgrpi(struct XorrisO *xorriso, char *gid, + int argc, char **argv, int *idx, int flag) +{ + int i, ret, was_failure= 0, end_idx, fret; + gid_t gid_number; + int optc= 0; + char **optv= NULL; + struct FindjoB *job= NULL; + struct stat dir_stbuf; + + ret= Xorriso_opt_args(xorriso, "-chgrpi", argc, argv, *idx, &end_idx, &optc, + &optv, 0); + if(ret<=0) + goto ex; + ret= Xorriso_convert_gidstring(xorriso, gid, &gid_number, 0); + if(ret<=0) + goto ex; + for(i= 0; i<optc; i++) { + if(flag&1) { + ret= Findjob_new(&job, optv[i], 0); + if(ret<=0) { + Xorriso_no_findjob(xorriso, "-chgrp_r", 0); + {ret= -1; goto ex;} + } + Findjob_set_action_chgrp(job, gid_number, 0); + ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0, + NULL, optv[i], &dir_stbuf, 0, 0); + Findjob_destroy(&job, 0); + } else + ret= Xorriso_set_gid(xorriso, optv[i], gid_number, 0); + if(ret>0 && !xorriso->request_to_abort) + continue; /* regular bottom of loop */ + was_failure= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); + if(fret>=0) + continue; + goto ex; + } + ret= 1; +ex:; + (*idx)= end_idx; + Xorriso_opt_args(xorriso, "-chgrpi", argc, argv, *idx, &end_idx, &optc, &optv, + 256); /* clean up */ + if(ret<=0) + return(ret); + Findjob_destroy(&job, 0); + return(!was_failure); +} + + +/* Option -chmod alias -chmodi , -chmod_r alias chmod_ri */ +/* @param flag bit0=recursive (-chmod_r) +*/ +int Xorriso_option_chmodi(struct XorrisO *xorriso, char *mode, + int argc, char **argv, int *idx, int flag) +{ + int i, ret, was_failure= 0, end_idx, fret; + mode_t mode_and= ~0, mode_or= 0; + int optc= 0; + char **optv= NULL; + struct FindjoB *job= NULL; + struct stat dir_stbuf; + + ret= Xorriso_opt_args(xorriso, "-chmodi", argc, argv, *idx, &end_idx, &optc, + &optv, 0); + if(ret<=0) + goto ex; + ret= Xorriso_convert_modstring(xorriso, "-chmodi", + mode, &mode_and, &mode_or, 0); + if(ret<=0) + goto ex; + for(i= 0; i<optc; i++) { + if(flag&1) { + ret= Findjob_new(&job, optv[i], 0); + if(ret<=0) { + Xorriso_no_findjob(xorriso, "-chmod_r", 0); + {ret= -1; goto ex;} + } + Findjob_set_action_chmod(job, mode_and, mode_or, 0); + ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0, + NULL, optv[i], &dir_stbuf, 0, 0); + Findjob_destroy(&job, 0); + } else { + ret= Xorriso_set_st_mode(xorriso, optv[i], mode_and, mode_or, 0); + } + if(ret>0 && !xorriso->request_to_abort) + continue; /* regular bottom of loop */ + was_failure= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); + if(fret>=0) + continue; + ret= 0; goto ex; + } + ret= 1; +ex:; + (*idx)= end_idx; + Xorriso_opt_args(xorriso, "-chmodi", argc, argv, *idx, &end_idx, &optc, &optv, + 256); + Findjob_destroy(&job, 0); + if(ret<=0) + return(ret); + return(!was_failure); +} + + +/* Option -chown alias -chowni , chown_r alias chown_ri */ +/* @param flag bit0=recursive (-chown_r) +*/ +int Xorriso_option_chowni(struct XorrisO *xorriso, char *uid, + int argc, char **argv, int *idx, int flag) +{ + int i, ret, was_failure= 0, end_idx, fret; + uid_t uid_number; + int optc= 0; + char **optv= NULL; + struct FindjoB *job= NULL; + struct stat dir_stbuf; + + ret= Xorriso_opt_args(xorriso, "-chowni", argc, argv, *idx, &end_idx, + &optc, &optv, 0); + if(ret<=0) + goto ex; + ret= Xorriso_convert_uidstring(xorriso, uid, &uid_number, 0); + if(ret<=0) + goto ex; + for(i= 0; i<optc; i++) { + if(flag&1) { + ret= Findjob_new(&job, optv[i], 0); + if(ret<=0) { + Xorriso_no_findjob(xorriso, "-chown_r", 0); + {ret= -1; goto ex;} + } + Findjob_set_action_chown(job, uid_number, 0); + ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0, + NULL, optv[i], &dir_stbuf, 0, 0); + Findjob_destroy(&job, 0); + } else + ret= Xorriso_set_uid(xorriso, optv[i], uid_number, 0); + if(ret>0 && !xorriso->request_to_abort) + continue; /* regular bottom of loop */ + was_failure= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); + if(fret>=0) + continue; + ret= 0; goto ex; + } + ret= 1; +ex:; + (*idx)= end_idx; + Xorriso_opt_args(xorriso, "-chowni", argc, argv, *idx, &end_idx, + &optc, &optv, 256); + Findjob_destroy(&job, 0); + if(ret<=0) + return(ret); + return(!was_failure); +} + + +/* Option -close "on"|"off" */ +int Xorriso_option_close(struct XorrisO *xorriso, char *mode, int flag) +{ + xorriso->do_close= !!strcmp(mode, "off"); + return(1); +} + + +/* Option -commit */ +/* @param flag bit0= leave indrive and outdrive aquired as they were, + i.e. do not aquire outdrive as new in-out-drive + bit1= do not perform eventual -reassure + @return <=0 error , 1 success, 2 revoked by -reassure , 3 no change pending +*/ +int Xorriso_option_commit(struct XorrisO *xorriso, int flag) +{ + int ret; + char newdev[SfileadrL]; + + if(!xorriso->volset_change_pending) { + sprintf(xorriso->info_text, "-commit: No image modifications pending"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); + return(3); + } + if(!(flag&2)) { + ret= Xorriso_reassure(xorriso, "-commit", + "write the pending image changes to media", 0); + if(ret<=0) + return(2); + } + Xorriso_process_errfile(xorriso, 0, "burn session start", 0, 1); + ret= Xorriso_write_session(xorriso, 0); + Xorriso_process_errfile(xorriso, 0, "burn session end", 0, 1); + if(ret<=0) + return(ret); + Xorriso_write_session_log(xorriso, 0); + xorriso->volset_change_pending= 0; + xorriso->no_volset_present= 0; + if(flag&1) + return(1); + if(Sregex_string(&(xorriso->in_charset), xorriso->out_charset, 0) <= 0) + return(-1); + strcpy(newdev, xorriso->outdev); + if(xorriso->grow_blindly_msc2>=0) + ret= Xorriso_option_dev(xorriso, "", 3|4); + else + ret= Xorriso_option_dev(xorriso, newdev, 3|4); + return(ret); +} + + +/* Option -commit_eject */ +/* @return <=0 error , 1 success, 2 revoked by -reassure +*/ +int Xorriso_option_commit_eject(struct XorrisO *xorriso, char *which, int flag) +{ + int ret, eret; + + ret= Xorriso_option_commit(xorriso, 1); + if(ret<=0 || ret==2 || ret==3) + return(ret); + if(strcmp(which, "none")==0) + eret= 1; + else + eret= Xorriso_option_eject(xorriso, which, 1); + ret= Xorriso_option_dev(xorriso, "", 3|4); + if(eret<ret) + return(eret); + return(ret); +} + + +/* Options -compare and -compare_r + @param flag bit0= issue summary message + bit1= do not reset pacifier, no final pacifier message + bit2= do not issue pacifier messages at all + bit3= recursive: -compare_r +*/ +int Xorriso_option_compare(struct XorrisO *xorriso, char *disk_path, + char *iso_path, int flag) +{ + int ret, mem_pci, zero= 0, result, follow_links; + double mem_lut= 0.0; + char *ipth, *argv[6], eff_origin[SfileadrL], eff_dest[SfileadrL]; + + ipth= iso_path; + if(ipth[0]==0) + ipth= disk_path; + if(disk_path[0]==0) { + sprintf(xorriso->info_text, "-compare: Empty disk_path given"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 1); + return(0); + } + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, eff_origin, + 2|4|8); + if(ret<=0) + return(ret); + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, ipth, eff_dest, 2|8); + if(ret<=0) + return(ret); + + if(xorriso->disk_excl_mode&8) + ret= Xorriso_path_is_excluded(xorriso, eff_origin, 1); + else + ret= 0; + if(ret!=0) + goto report_outcome; + if(!(flag&2)) { + Xorriso_pacifier_reset(xorriso, 0); + mem_lut= xorriso->last_update_time; + } + mem_pci= xorriso->pacifier_interval; + xorriso->pacifier_interval= 5.0; + + if(flag&8) { + xorriso->find_compare_result= 1; + argv[0]= eff_dest; + argv[1]= "-exec"; + argv[2]= "compare"; + argv[3]= eff_origin; + zero= 0; + ret= Xorriso_option_find(xorriso, 4, argv, &zero, 2); /* -findi */ + if(ret>0) { + argv[0]= eff_origin; + argv[1]= "-exec"; + argv[2]= "not_in_iso"; + argv[3]= eff_dest; + zero= 0; + ret= Xorriso_option_find(xorriso, 4, argv, &zero, 1|2); /* -findx */ + if(ret>0 && !xorriso->do_follow_mount) { + argv[0]= eff_origin; + argv[1]= "-type"; + argv[2]= "m"; + argv[3]= "-exec"; + argv[4]= "is_full_in_iso"; + argv[5]= eff_dest; + zero= 0; + ret= Xorriso_option_find(xorriso, 6, argv, &zero, 1|2); /* -findx */ + } + if(ret>0) + ret= xorriso->find_compare_result; + else + ret= -1; + } else + ret= -1; + } else { + follow_links= (xorriso->do_follow_links || xorriso->do_follow_param) << 28; + ret= Xorriso_compare_2_files(xorriso, eff_origin, eff_dest, "", &result, + 2 | follow_links | ((flag&4)<<27) | (1<<30)); + } + + xorriso->pacifier_interval= mem_pci; + if(mem_lut!=xorriso->last_update_time && !(flag&2)) + Xorriso_pacifier_callback(xorriso, "content bytes read", + xorriso->pacifier_count, 0, "", 1); +report_outcome:; + if(ret>0) { + sprintf(xorriso->result_line, + "Both file objects match as far as expectable.\n"); + } else if(ret==0) { + sprintf(xorriso->result_line, "Differences detected.\n"); + } else { + sprintf(xorriso->result_line, "Comparison failed due to error.\n"); + } + if(flag&1) + Xorriso_result(xorriso,0); + if(ret<0) + return(ret); + return(1); +} + + +/* Option -cpr alias -cpri */ +int Xorriso_option_cpri(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag) +{ + int i, ret, is_dir= 0, was_failure= 0, fret, end_idx_dummy; + char eff_origin[SfileadrL], eff_dest[SfileadrL]; + char dest_dir[SfileadrL], leafname[SfileadrL]; + int optc= 0; + char **optv= NULL; + + ret= Xorriso_cpmv_args(xorriso, "-cpri", argc, argv, idx, + &optc, &optv, eff_dest, 1|2); + if(ret<=0) + goto ex; + if(ret==2) { + is_dir= 1; + strcpy(dest_dir, eff_dest); + } + + /* Perform graft-ins */ + Xorriso_pacifier_reset(xorriso, 0); + for(i= 0; i<optc && !xorriso->request_to_abort; i++) { + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, optv[i], eff_origin, + 2|4); + if(ret<=0 || xorriso->request_to_abort) + goto problem_handler; + if(is_dir) { + ret= Sfile_leafname(eff_origin, leafname, 0); + if(ret<=0) + goto problem_handler; + strcpy(eff_dest, dest_dir); + ret= Sfile_add_to_path(eff_dest, leafname, 0); + if(ret<=0) { + sprintf(xorriso->info_text, "Effective path gets much too long (%d)", + (int) (strlen(eff_dest)+ strlen(leafname)+1)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + goto problem_handler; + } + } + ret= Xorriso_graft_in(xorriso, NULL, eff_origin, eff_dest, + (off_t) 0, (off_t) 0, 0); + if(ret<=0 || xorriso->request_to_abort) + goto problem_handler; + sprintf(xorriso->info_text, "Added to ISO image: %s '%s'='%s'\n", + (ret>1 ? "directory" : "file"), (eff_dest[0] ? eff_dest : "/"), + eff_origin); + if(!(flag&1)) + Xorriso_info(xorriso, 0); + continue; /* regular bottom of loop */ +problem_handler:; + was_failure= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); + if(fret>=0) + continue; + goto ex; + } + Xorriso_pacifier_callback(xorriso, "files added", xorriso->pacifier_count, + xorriso->pacifier_total, "", 1); + ret= !was_failure; +ex:; + Xorriso_opt_args(xorriso, "-cpri", + argc, argv, *idx, &end_idx_dummy, &optc, &optv, 256); + return(ret); +} + + +/* Options -cpx , -cpax, -cp_rx , -cp_rax */ +/* @param flag bit0= recursive (-cp_rx, -cp_rax) + bit1= full property restore (-cpax, -cp_rax) +*/ +int Xorriso_option_cpx(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag) +{ + int i, ret, is_dir= 0, was_failure= 0, fret, end_idx_dummy; + char eff_origin[SfileadrL], eff_dest[SfileadrL]; + char dest_dir[SfileadrL], leafname[SfileadrL], sfe[5*SfileadrL]; + int optc= 0; + char **optv= NULL; + struct stat stbuf; + + ret= Xorriso_cpmv_args(xorriso, "-cp*x", argc, argv, idx, + &optc, &optv, eff_dest, 1|4); + if(ret<=0) + goto ex; + if(ret==2) { + is_dir= 1; + strcpy(dest_dir, eff_dest); + } + if(!xorriso->allow_restore) { + sprintf(xorriso->info_text, + "-cpx: image-to-disk copies are not enabled by option -osirrox"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + + /* Perform copying */ + Xorriso_pacifier_reset(xorriso, 0); + for(i= 0; i<optc && !xorriso->request_to_abort; i++) { + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, optv[i], eff_origin, + 2|8); + if(ret<=0 || xorriso->request_to_abort) + goto problem_handler; + + ret= Xorriso_iso_lstat(xorriso, eff_origin, &stbuf, 2|4); + if(ret==-1) + goto problem_handler; + if(S_ISDIR(stbuf.st_mode) && !(flag&1)) { + /* only allow directories if they actually represent split data files */ + ret= 0; + if(xorriso->do_concat_split) + ret= Xorriso_is_split(xorriso, eff_origin, NULL, 2); + if(ret<0) + goto problem_handler; + if(ret==0) { + sprintf(xorriso->info_text, "-cpx: May not copy directory %s", + Text_shellsafe(eff_origin, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto problem_handler; + } + } + + if(is_dir && strcmp(eff_origin, "/")!=0) { + ret= Sfile_leafname(eff_origin, leafname, 0); + if(ret<=0) + goto problem_handler; + strcpy(eff_dest, dest_dir); + ret= Sfile_add_to_path(eff_dest, leafname, 0); + if(ret<=0) { + sprintf(xorriso->info_text, "Effective path gets much too long (%d)", + (int) (strlen(eff_dest)+strlen(leafname)+1)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + goto problem_handler; + } + } + ret= Xorriso_restore(xorriso, eff_origin, eff_dest, (off_t) 0, (off_t) 0, + 16 | ((!(flag&2))<<6)); + if(ret<=0 || xorriso->request_to_abort) + goto problem_handler; + if(ret==3 || (flag&1)) + continue; + sprintf(xorriso->info_text, + "Copied from ISO image to disk: %s '%s' = '%s'\n", + (ret>1 ? "directory" : "file"), eff_origin, eff_dest); + Xorriso_info(xorriso, 0); + continue; /* regular bottom of loop */ +problem_handler:; + was_failure= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); + if(fret>=0) + continue; + goto ex; + } + if(xorriso->pacifier_count>0) + Xorriso_pacifier_callback(xorriso, "files restored",xorriso->pacifier_count, + xorriso->pacifier_total, "", 1|4); + ret= !was_failure; +ex:; + Xorriso_opt_args(xorriso, "-cp*x", + argc, argv, *idx, &end_idx_dummy, &optc, &optv, 256); + return(ret); +} + + +/* Option -cut_out */ +int Xorriso_option_cut_out(struct XorrisO *xorriso, char *disk_path, + char *start, char *count, char *iso_rr_path, int flag) +{ + int ret; + double num; + off_t startbyte, bytecount; + + num= Scanf_io_size(start, 0); + if(num<0 || num > 1.0e18) { /* 10^18 = 10^3 ^ 6 < 2^10 ^ 6 = 2^60 */ + sprintf(xorriso->info_text, + "-cut_out: startbyte address negative or much too large (%s)", start); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + startbyte= num; + num= Scanf_io_size(count, 0); + if(num<=0 || num > 1.0e18) { + sprintf(xorriso->info_text, + "-cut_out: bytecount zero, negative or much too large (%s)", count); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + bytecount= num; + sprintf(xorriso->info_text, + "-cut_out from %s , byte %.f to %.f, and graft as %s", + disk_path, (double) startbyte, (double) (startbyte+bytecount), + iso_rr_path); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + + ret= Xorriso_cut_out(xorriso, disk_path, startbyte, bytecount, + iso_rr_path, 0); + return(ret); +} + + +/* Options -dev , -indev, -outdev */ +/** @param flag bit0= use as indev + bit1= use as outdev + bit2= do not -reassure + bit3= regard overwriteable media as blank + bit4= if the drive is a regular disk file: truncate it to + the write start address + bit5= do not print toc of aquired drive + @return <=0 error , 1 success, 2 revoked by -reassure +*/ +int Xorriso_option_dev(struct XorrisO *xorriso, char *in_adr, int flag) +{ + int ret; + char sfe[5*SfileadrL], *adr; + + adr= in_adr; + if(strcmp(in_adr, "-")==0) + adr= "stdio:/dev/fd/1"; + if(strncmp(adr, "stdio:", 6)==0) { + if(strlen(adr)==6 || strcmp(adr, "stdio:/")==0 || + strcmp(adr, "stdio:.")==0 || strcmp(adr, "stdio:..")==0 || + strcmp(adr, "stdio:-")==0) { + sprintf(xorriso->info_text, + "No suitable path given by device address '%s'", adr); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + } + + if(xorriso->volset_change_pending && (flag&1)) { + sprintf(xorriso->info_text, + "%s: Image changes pending. -commit or -rollback first", + (flag&2) ? "-dev" : "-indev"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + if((flag&1) && (xorriso->in_drive_handle != NULL || adr[0]) && !(flag&4)) { + ret= Xorriso_reassure(xorriso, (flag&2) ? "-dev" : "-indev", + "eventually discard the current image", 0); + if(ret<=0) + return(2); + } + + if(adr[0]==0) { + if((flag&1) && xorriso->in_drive_handle != NULL) { + if(xorriso->in_drive_handle == xorriso->out_drive_handle) + sprintf(xorriso->info_text,"Giving up -dev %s", + Text_shellsafe(xorriso->indev, sfe, 0)); + else + sprintf(xorriso->info_text,"Giving up -indev %s", + Text_shellsafe(xorriso->indev, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + } + if((flag&2) && xorriso->out_drive_handle != NULL && + xorriso->in_drive_handle != xorriso->out_drive_handle) { + sprintf(xorriso->info_text,"Giving up -outdev %s", + Text_shellsafe(xorriso->outdev, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + } + ret= Xorriso_give_up_drive(xorriso, (flag&3)|((flag&32)>>2)); + } else + ret= Xorriso_aquire_drive(xorriso, adr, (flag&(3|32))|(((flag&(8|16))>>1))); + if(ret<=0) + return(ret); + if(xorriso->in_drive_handle == NULL) + xorriso->image_start_mode= 0; /* session setting is invalid by now */ + return(1); +} + + +/* Option -devices */ +/* @return <=0 error , 1 success, 2 revoked by -reassure +*/ +int Xorriso_option_devices(struct XorrisO *xorriso, int flag) +{ + int ret; + char sfe[5*SfileadrL]; + + if(xorriso->volset_change_pending) { + sprintf(xorriso->info_text, + "-devices: Image changes pending. -commit or -rollback first"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + ret= Xorriso_reassure(xorriso, "-devices", + "eventually discard the current image", 0); + if(ret<=0) + return(2); + xorriso->info_text[0]= 0; + if(xorriso->in_drive_handle!=NULL || xorriso->out_drive_handle!=NULL) { + if(xorriso->in_drive_handle == xorriso->out_drive_handle) { + sprintf(xorriso->info_text, "Gave up -dev %s", + Text_shellsafe(xorriso->indev, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + }else { + if(xorriso->in_drive_handle!=NULL) { + sprintf(xorriso->info_text, "Gave up -indev %s", + Text_shellsafe(xorriso->indev, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + } + if(xorriso->out_drive_handle!=NULL) { + sprintf(xorriso->info_text, "Gave up -outdev %s", + Text_shellsafe(xorriso->outdev, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + } + } + Xorriso_give_up_drive(xorriso, 3); + } + ret= Xorriso_show_devices(xorriso, 0); + return(ret); +} + + +/* Option -dialog "on"|"single_line"|"off" */ +int Xorriso_option_dialog(struct XorrisO *xorriso, char *mode, int flag) +{ + if(strcmp(mode, "on") == 0 || strcmp(mode, "multi_line") == 0) + xorriso->dialog= 2; + else if(strcmp(mode, "single_line") == 0) + xorriso->dialog= 2; + else if(strcmp(mode, "off") == 0) + xorriso->dialog= 0; + else { + sprintf(xorriso->info_text, "-dialog: unknown mode '%s'", mode); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + return(1); +} + + +/* Option -disk_pattern "on"|"ls"|"off" */ +int Xorriso_option_disk_pattern(struct XorrisO *xorriso, char *mode, int flag) +{ + if(strcmp(mode, "off")==0) + xorriso->do_disk_pattern= 0; + else if(strcmp(mode, "on")==0) + xorriso->do_disk_pattern= 1; + else if(strcmp(mode, "ls")==0) + xorriso->do_disk_pattern= 2; + else { + sprintf(xorriso->info_text, "-disk_pattern: unknown mode '%s'", mode); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + return(1); +} + + +/* Option -drive_class */ +int Xorriso_option_drive_class(struct XorrisO *xorriso, + char *class, char *pattern, int flag) +{ + int ret= 1; + + if(strcmp(class, "banned") == 0) { + ret= Xorriso_lst_new(&(xorriso->drive_blacklist), pattern, + xorriso->drive_blacklist, 1); + } else if(strcmp(class, "caution") == 0) { + ret= Xorriso_lst_new(&(xorriso->drive_greylist), pattern, + xorriso->drive_greylist, 1); + } else if (strcmp(class, "harmless") == 0) { + ret= Xorriso_lst_new(&(xorriso->drive_whitelist), pattern, + xorriso->drive_whitelist, 1); + } else if (strcmp(class, "clear_list") == 0) { + if(strcmp(pattern, "banned") == 0) + Xorriso_lst_destroy_all(&(xorriso->drive_blacklist), 0); + else if(strcmp(pattern, "caution") == 0) + Xorriso_lst_destroy_all(&(xorriso->drive_greylist), 0); + else if(strcmp(pattern, "harmless") == 0) + Xorriso_lst_destroy_all(&(xorriso->drive_whitelist), 0); + else if(strcmp(pattern, "all") == 0) { + Xorriso_lst_destroy_all(&(xorriso->drive_blacklist), 0); + Xorriso_lst_destroy_all(&(xorriso->drive_greylist), 0); + Xorriso_lst_destroy_all(&(xorriso->drive_whitelist), 0); + } else { + sprintf(xorriso->info_text, "-drive_class clear : unknown class '%s'", + pattern); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + ret= 1; + } else { + sprintf(xorriso->info_text, "-drive_class: unknown class '%s'", class); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + return(ret); +} + + +/* Option -dummy "on"|"off" */ +int Xorriso_option_dummy(struct XorrisO *xorriso, char *mode, int flag) +{ + xorriso->do_dummy= !!strcmp(mode, "off"); + return(1); +} + + +/* Option -eject */ +/* @param flag bit0=do not report toc of eventually remaining drives +*/ +int Xorriso_option_eject(struct XorrisO *xorriso, char *which, int flag) +{ + int gu_flag= 4, ret; + + if(strncmp(which,"in",2)==0) + gu_flag|= 1; + else if(strncmp(which,"out",3)==0) + gu_flag|= 2; + else + gu_flag|= 3; + if((gu_flag&1) && xorriso->volset_change_pending) { + sprintf(xorriso->info_text, + "-eject: Image changes pending. -commit or -rollback first"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + if(flag&1) + gu_flag|= 8; + ret= Xorriso_give_up_drive(xorriso, gu_flag); + return(ret); +} + + +/* Options -end , and -rollback_end */ +/* @param flag bit0= discard pending changes + bit1= do not -reassure + @return <=0 error , 1 success, 2 revoked by -reassure +*/ +int Xorriso_option_end(struct XorrisO *xorriso, int flag) +{ + int ret; + char *cmd, *which_will; + + if(flag&1) + cmd= "-rollback_end"; + else + cmd= "-end"; + if(xorriso->volset_change_pending) { + if(flag&1) + which_will= "end the program discarding image changes"; + else + which_will= "commit image changes and then end the program"; + } else { + which_will= "end the program"; + } + if(!(flag&2)) { + ret= Xorriso_reassure(xorriso, cmd, which_will, 0); + if(ret<=0) + return(2); + } + + if(xorriso->volset_change_pending) { + if(flag&1) { + xorriso->volset_change_pending= 0; + } else { + ret= Xorriso_option_commit(xorriso, 1); + xorriso->volset_change_pending= 0; /* no further tries to commit */ + if(ret<=0) + return(ret); + } + } + ret= Xorriso_give_up_drive(xorriso, 3); + if(ret<=0) + return(ret); + return(1); +} + + +/* Option -errfile_log marked|plain path|-|"" */ +int Xorriso_option_errfile_log(struct XorrisO *xorriso, + char *mode, char *path, int flag) +{ + int ret, mode_word; + FILE *fp= NULL; + char sfe[5*SfileadrL]; + + if(path[0]==0 || path[0]=='-') { + /* ok */; + } else { + fp= fopen(path, "a"); + if(fp==0) { + sprintf(xorriso->info_text, "-errfile_log: Cannot open file %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + } + mode_word= xorriso->errfile_mode; + if(strcmp(mode, "marked")==0) + mode_word|= 1; + else if(strcmp(mode, "plain")==0) + mode_word&= ~1; + else { + sprintf(xorriso->info_text, "-errfile_log: Unknown mode %s", + Text_shellsafe(mode, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + + Xorriso_process_errfile(xorriso, 0, "log end", 0, 1); + if(xorriso->errfile_fp!=NULL) + fclose(xorriso->errfile_fp); + xorriso->errfile_fp= fp; + xorriso->errfile_mode= mode_word; + ret= Sfile_str(xorriso->errfile_log, path, 0); + if(ret>0) + ret= Xorriso_process_errfile(xorriso, 0, "log start", 0, 1); + if(ret<=0) + return(ret); + return(1); +} + + +/* Option -error_behavior */ +int Xorriso_option_error_behavior(struct XorrisO *xorriso, + char *occasion, char *behavior, int flag) +{ + if(strcmp(occasion, "image_loading")==0) { + if(strcmp(behavior, "best_effort")==0) + xorriso->img_read_error_mode= 0; + else if(strcmp(behavior, "failure")==0 || strcmp(behavior, "FAILURE")==0) + xorriso->img_read_error_mode= 1; + else if(strcmp(behavior, "fatal")==0 || strcmp(behavior, "FATAL")==0) + xorriso->img_read_error_mode= 2; + else { +unknown_behavior:; + sprintf(xorriso->info_text, + "-error_behavior: with '%s': unknown behavior '%s'", + occasion, behavior); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + } else if(strcmp(occasion, "file_extraction")==0) { + if(strcmp(behavior, "best_effort")==0) + xorriso->extract_error_mode= 0; + else if(strcmp(behavior, "keep")==0) + xorriso->extract_error_mode= 1; + else if(strcmp(behavior, "delete")==0) + xorriso->extract_error_mode= 2; + else + goto unknown_behavior; + } else { + sprintf(xorriso->info_text, "-error_behavior: unknown occasion '%s'", + occasion); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + return(1); +} + + +/* Options -extract , -extract_single */ +/* @param flag bit0=do not report the restored item + bit1=do not reset pacifier, no final pacifier message + bit5= -extract_single: eventually do not insert directory tree +*/ +int Xorriso_option_extract(struct XorrisO *xorriso, char *iso_path, + char *disk_path, int flag) +{ + int ret; + char eff_origin[SfileadrL], eff_dest[SfileadrL], *ipth; + + if(!xorriso->allow_restore) { + sprintf(xorriso->info_text, + "-extract: image-to-disk copies are not enabled by option -osirrox"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + if(!(flag&2)) + Xorriso_pacifier_reset(xorriso, 0); + + ipth= iso_path; + if(ipth[0]==0) + ipth= disk_path; + if(disk_path[0]==0) { + sprintf(xorriso->info_text, "-extract: Empty disk_path given"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 1); + return(0); + } + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, eff_dest, + 2|4); + if(ret<=0) + return(ret); + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, ipth, eff_origin, 2|8); + if(ret<=0) + return(ret); + ret= Xorriso_restore(xorriso, eff_origin, eff_dest, + (off_t) 0, (off_t) 0, (flag&32)); + if(!(flag&2)) + Xorriso_pacifier_callback(xorriso, "files restored",xorriso->pacifier_count, + xorriso->pacifier_total, "", 1|4); + if(ret<=0) + return(ret); + + if(!(flag&1)) { + sprintf(xorriso->info_text, "Extracted from ISO image: %s '%s'='%s'\n", + (ret>1 ? "directory" : "file"), eff_origin, eff_dest); + Xorriso_info(xorriso,0); + } + return(1); +} + + +/* Option -extract_cut */ +int Xorriso_option_extract_cut(struct XorrisO *xorriso, char *iso_rr_path, + char *start, char *count, char *disk_path, int flag) +{ + int ret; + double num; + off_t startbyte, bytecount; + + num= Scanf_io_size(start, 0); + if(num<0 || num > 1.0e18) { /* 10^18 = 10^3 ^ 6 < 2^10 ^ 6 = 2^60 */ + sprintf(xorriso->info_text, + "-extract_cut: startbyte address negative or much too large (%s)", + start); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + startbyte= num; + num= Scanf_io_size(count, 0); + if(num<=0 || num > 1.0e18) { + sprintf(xorriso->info_text, + "-extract_cut: bytecount zero, negative or much too large (%s)", + count); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + bytecount= num; + sprintf(xorriso->info_text, + "-extract_cut from %s , byte %.f to %.f, and store as %s", + disk_path, (double) startbyte, (double) (startbyte+bytecount), + iso_rr_path); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + + ret= Xorriso_extract_cut(xorriso, iso_rr_path, disk_path, + startbyte, bytecount, 0); + return(ret); +} + + +/* Option -file_size_limit */ +int Xorriso_option_file_size_limit(struct XorrisO *xorriso, + int argc, char **argv, int *idx, int flag) +{ + int ret, i, end_idx; + off_t new_limit= 0; + + end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1); + if(*idx >= end_idx) + {ret= 2; goto ex;} + if(*idx + 1 == end_idx && strcmp(argv[*idx], "off") == 0) { + xorriso->file_size_limit= 0; + ret= 1; goto ex; + } + for(i= *idx; i < end_idx; i++) + new_limit+= Scanf_io_size(argv[i], 0); + if(new_limit <= 0) { + sprintf(xorriso->info_text, "-file_size_limit: values sum up to %.f", + (double) new_limit); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 1); + ret= 0; goto ex; + } + xorriso->file_size_limit= new_limit; + ret= 1; +ex:; + (*idx)= end_idx; + if(ret > 0) { + if(xorriso->file_size_limit > 0) + sprintf(xorriso->info_text, "-file_size_limit now at %.f\n", + (double) xorriso->file_size_limit); + else + sprintf(xorriso->info_text, "-file_size_limit now off\n"); + Xorriso_info(xorriso,0); + } + return(ret); +} + + +/* Option -find alias -findi, and -findx */ +/* @param flag bit0= -findx rather than -findi + bit1= do not reset pacifier, no final pacifier message + do not reset find_compare_result + bit2= do not count deleted files with rm and rm_r +*/ +int Xorriso_option_find(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag) +{ + int ret, i, end_idx, type= 0, action, deleter= 0, start_lba, count; + struct FindjoB *job, *first_job= NULL, *new_job; + char *start_path, sfe[5*SfileadrL], *cpt, other_path_start[SfileadrL]; + struct stat dir_stbuf; + uid_t user= 0; + gid_t group= 0; + time_t date= 0; + mode_t mode_or= 0, mode_and= ~1; + double mem_lut= 0.0; + + end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1); + start_path= "."; + if(end_idx > *idx && start_path[0]!=0) + start_path= argv[*idx]; + ret= Findjob_new(&first_job, start_path, 0); + if(ret<=0) { + Xorriso_no_findjob(xorriso, "-find[ix]", 0); + {ret= -1; goto ex;} + } + job= first_job; + if(!(flag&2)) + xorriso->find_compare_result= 1; + for(i= *idx+1; i<end_idx; i++) { + if(strcmp(argv[i], "-name")==0) { + if(i+1>=end_idx) { +not_enough_arguments:; + sprintf(xorriso->info_text, + "-find[ix]: not enough arguments with -exec %s", + Text_shellsafe(argv[i], sfe, 0)); + goto sorry_ex; + } + i++; + ret= Findjob_set_name_expr(job, argv[i], 0); + if(ret<=0) { + sprintf(xorriso->info_text, "-find[ix]: cannot set -name expression %s", + Text_shellsafe(argv[i], sfe, 0)); + goto sorry_ex; + } + } else if(strcmp(argv[i], "-type")==0) { + if(i+1>=end_idx) + goto not_enough_arguments; + i++; + ret= Findjob_set_file_type(job, argv[i][0], 0); + if(ret<=0) { + sprintf(xorriso->info_text, "-find[ix]: unknown -type '%c'",argv[i][0]); + goto sorry_ex; + } + } else if(strcmp(argv[i], "-damaged")==0) { + Findjob_set_damage_filter(job, 1, 0); + } else if(strcmp(argv[i], "-undamaged")==0) { + Findjob_set_damage_filter(job, -1, 0); + } else if(strcmp(argv[i], "-lba_range")==0) { + if(i+2>=end_idx) + goto not_enough_arguments; + i+= 2; + sscanf(argv[i-1], "%d", &start_lba); + sscanf(argv[i], "%d", &count); + Findjob_set_lba_range(job, start_lba, count, 0); + } else if(strcmp(argv[i], "-pending_data")==0) { + Findjob_set_commit_filter(job, 1, 1, 0); + } else if(strcmp(argv[i], "-exec")==0) { + if(i+1>=end_idx) + goto not_enough_arguments; + i++; + cpt= argv[i]; + if(*cpt=='-') + cpt++; + if(strcmp(cpt, "echo")==0) { + Findjob_set_action_target(job, 0, NULL, 0); + } else if(strcmp(cpt, "rm")==0) { + Findjob_set_action_target(job, 1, NULL, 0); + deleter= 1; + } else if(strcmp(cpt, "rm_r")==0) { + Findjob_set_action_target(job, 2, NULL, 0); + deleter= 1; + +#ifdef NIX +/* >>> not implemented yet */; + } else if(strcmp(cpt, "mv")==0) { + if(i+1>=end_idx) + goto not_enough_arguments; + i++; + Findjob_set_action_target(job, 3, argv[i], 0); +#endif + + } else if(strcmp(cpt, "chown")==0 || strcmp(cpt, "chown_r")==0) { + if(i+1>=end_idx) + goto not_enough_arguments; + i++; + ret= Xorriso_convert_uidstring(xorriso, argv[i], &user, 0); + if(ret<=0) + goto ex; + ret= Findjob_set_action_chown(job, user, strlen(cpt)>5); + if(ret<=0) { + Xorriso_no_findjob(xorriso, "-find -exec chown_r", 0); + goto ex; + } + } else if(strcmp(cpt, "chgrp")==0 || strcmp(cpt, "chgrp_r")==0) { + if(i+1>=end_idx) + goto not_enough_arguments; + i++; + ret= Xorriso_convert_gidstring(xorriso, argv[i], &group, 0); + if(ret<=0) + goto ex; + ret= Findjob_set_action_chgrp(job, group, strlen(cpt)>5); + if(ret<=0) { + Xorriso_no_findjob(xorriso, "-find -exec chgrp_r", 0); + goto ex; + } + } else if(strcmp(cpt, "chmod")==0 || strcmp(cpt, "chmod_r")==0) { + if(i+1>=end_idx) + goto not_enough_arguments; + i++; + ret= Xorriso_convert_modstring(xorriso, "-find -exec chmod", + argv[i], &mode_and, &mode_or, 0); + if(ret<=0) + goto ex; + ret= Findjob_set_action_chmod(job, mode_and, mode_or, strlen(cpt)>5); + if(ret<=0) { + Xorriso_no_findjob(xorriso, "-find -exec chmod_r", 0); + goto ex; + } + } else if(strcmp(cpt, "alter_date")==0 || strcmp(cpt, "alter_date_r")==0){ + if(i+2>=end_idx) + goto not_enough_arguments; + i+= 2; + ret= Xorriso_convert_datestring(xorriso, "-find -exec alter_date", + argv[i-1], argv[i], &type, &date, 0); + if(ret<=0) + goto ex; + ret= Findjob_set_action_ad(job, type, date, strlen(cpt)>10); + if(ret<=0) { + Xorriso_no_findjob(xorriso, "-find -exec alter_date_r", 0); + goto ex; + } + } else if(strcmp(cpt, "lsdl")==0) { + Findjob_set_action_target(job, 8, NULL, 0); + + } else if(strcmp(cpt, "find")==0) { + ret= Findjob_new(&new_job, "", 0); + if(ret<=0) { + Xorriso_no_findjob(xorriso, "-find[ix]", 0); + {ret= -1; goto ex;} + } + Findjob_set_action_subjob(job, 13, new_job, 0); + job= new_job; + + } else if(strcmp(cpt, "compare")==0 || strcmp(cpt, "update")==0) { + if(i+1>=end_idx) + goto not_enough_arguments; + i++; + action= 14; + if(strcmp(cpt, "update")==0) + action= 17; + ret= Xorriso_make_abs_adr(xorriso, xorriso->wdx, argv[i], + other_path_start, 1|2|4|8); + if(ret<=0) + goto ex; + Findjob_set_action_target(job, action, other_path_start, 0); + ret= Xorriso_make_abs_adr(xorriso, xorriso->wdi, start_path,sfe, 1|2|4); + if(ret<=0) + goto ex; + Findjob_set_start_path(job, sfe, 0); + if(!(flag&2)) { + Xorriso_pacifier_reset(xorriso, 0); + mem_lut= xorriso->last_update_time; + } + } else if(strcmp(cpt, "in_iso")==0 || + strcmp(cpt, "not_in_iso")==0 || + strcmp(cpt, "add_missing")==0 || + strcmp(cpt, "empty_iso_dir")==0 || + strcmp(cpt, "is_full_in_iso")==0) { + if(i+1>=end_idx) + goto not_enough_arguments; + i++; + ret= Xorriso_make_abs_adr(xorriso, xorriso->wdi, argv[i], + other_path_start, 1|2|4); + if(ret<=0) + goto ex; + if(strcmp(cpt, "in_iso")==0) + action= 15; + else if(strcmp(cpt, "add_missing")==0) + action= 18; + else if(strcmp(cpt, "empty_iso_dir")==0) + action= 19; + else if(strcmp(cpt, "is_full_in_iso")==0) + action= 20; + else + action= 16; + Findjob_set_action_target(job, action, other_path_start, 0); + ret= Xorriso_make_abs_adr(xorriso, xorriso->wdx, start_path, sfe, + 1|2|4|8); + if(ret<=0) + goto ex; + Findjob_set_start_path(job, sfe, 0); + + } else if(strcmp(cpt, "report_damage")==0) { + Findjob_set_action_target(job, 21, NULL, 0); + } else if(strcmp(cpt, "report_lba")==0) { + Findjob_set_action_target(job, 22, NULL, 0); + } else { + sprintf(xorriso->info_text, "-find -exec: unknown action %s", + Text_shellsafe(argv[i], sfe, 0)); + goto sorry_ex; + } + } else { + sprintf(xorriso->info_text, "-find[ix]: unknown option %s", + Text_shellsafe(argv[i], sfe, 0)); +sorry_ex:; + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + } + if(flag&1) + ret= Xorriso_findx(xorriso, first_job, "", start_path, &dir_stbuf, 0, NULL, + 0); + else + ret= Xorriso_findi(xorriso, first_job, NULL, (off_t) 0, NULL, + start_path, &dir_stbuf, 0, (flag&4)>>1); +ex:; + if(deleter && !(flag&2)) + Xorriso_pacifier_callback(xorriso, "iso_rr_paths deleted", + xorriso->pacifier_count, 0, "", 1|2); + else if(mem_lut!=xorriso->last_update_time && mem_lut!=0.0 && !(flag&2)) + Xorriso_pacifier_callback(xorriso, "content bytes read", + xorriso->pacifier_count, 0, "", 1); + Findjob_destroy(&first_job, 0); + (*idx)= end_idx; + return(ret); +} + + +/* Option -follow */ +int Xorriso_option_follow(struct XorrisO *xorriso, char *mode, int flag) +{ + int was_fl, was_fm, was_fpr, was_fpt, l; + double num; + char *cpt, *npt; + + was_fpt= xorriso->do_follow_pattern; + was_fpr= xorriso->do_follow_param; + was_fl= xorriso->do_follow_links; + was_fm= xorriso->do_follow_mount; + xorriso->do_follow_pattern= 0; + xorriso->do_follow_param= 0; + xorriso->do_follow_links= 0; + xorriso->do_follow_mount= 0; + npt= cpt= mode; + for(cpt= mode; npt!=NULL; cpt= npt+1) { + npt= strchr(cpt,':'); + if(npt==NULL) + l= strlen(cpt); + else + l= npt-cpt; + if(l==0) + goto unknown_mode; + if(strncmp(cpt, "off", l)==0) { + xorriso->do_follow_pattern= 0; + xorriso->do_follow_param= 0; + xorriso->do_follow_links= 0; + xorriso->do_follow_mount= 0; + } else if(strncmp(cpt, "on", l)==0) { + xorriso->do_follow_pattern= 1; + xorriso->do_follow_param= 1; + xorriso->do_follow_links= 1; + xorriso->do_follow_mount= 1; + } else if(strncmp(cpt, "default", l)==0) { + xorriso->do_follow_pattern= 1; + xorriso->do_follow_param= 0; + xorriso->do_follow_links= 0; + xorriso->do_follow_mount= 1; + xorriso->follow_link_limit= 100; + } else if(strncmp(cpt, "link", l)==0 || strncmp(cpt,"links", l)==0) { + xorriso->do_follow_links= 1; + } else if(strncmp(cpt, "mount", l)==0) { + xorriso->do_follow_mount= 1; + } else if(strncmp(cpt,"param", l)==0) { + xorriso->do_follow_param= 1; + } else if(strncmp(cpt, "pattern", l)==0) { + xorriso->do_follow_pattern= 1; + } else if(strncmp(cpt, "limit=", 6)==0) { + sscanf(cpt+6, "%lf", &num); + if(num<=0 || num>1.0e6) { + sprintf(xorriso->info_text, "-follow: Value too %s with '%s'", + num<=0 ? "small" : "large", cpt+6); + goto sorry_ex; + } + xorriso->follow_link_limit= num; + } else { +unknown_mode:; + if(l<SfileadrL) + sprintf(xorriso->info_text, "-follow: unknown mode '%s'", cpt); + else + sprintf(xorriso->info_text, "-follow: oversized mode parameter (%d)",l); +sorry_ex: + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + xorriso->do_follow_pattern= was_fpt; + xorriso->do_follow_param= was_fpr; + xorriso->do_follow_links= was_fl; + xorriso->do_follow_mount= was_fm; + return(0); + } + } + return(1); +} + + +/* Option -fs */ +int Xorriso_option_fs(struct XorrisO *xorriso, char *size, int flag) +{ + double num; + + num= Scanf_io_size(size, 0); + if(num < 64*1024 || num > 1024.0 * 1024.0 * 1024.0) { + sprintf(xorriso->info_text, "-fs: wrong size %.f (allowed: %.f - %.f)", + num, 64.0 * 1024.0, 1024.0 * 1024.0 * 1024.0); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + xorriso->fs= num / 2048.0; + if(xorriso->fs * 2048 < num) + xorriso->fs++; + return(1); +} + + +/* Option -gid */ +int Xorriso_option_gid(struct XorrisO *xorriso, char *gid, int flag) +{ + int ret; + + xorriso->do_global_gid= 0; + if(gid[0]==0 || strcmp(gid,"-")==0) + return(1); + ret= Xorriso_convert_gidstring(xorriso, gid, &(xorriso->global_gid), 0); + if(ret>0) + xorriso->do_global_gid= 1; + return(ret); +} + + +/* Option -grow_blindly */ +int Xorriso_option_grow_blindly(struct XorrisO *xorriso, char *msc2, int flag) +{ + double num; + int l; + + if(msc2[0]==0 || msc2[0]=='-' || strcmp(msc2, "off")==0) { + xorriso->grow_blindly_msc2= -1; + return(1); + } + num= Scanf_io_size(msc2, 0); + l= strlen(msc2); + if(msc2[l-1]<'0' || msc2[l-1]>'9') + num/= 2048.0; + xorriso->grow_blindly_msc2= num; + return(1); +} + + +/* Option -help and part of -prog_help */ +int Xorriso_option_help(struct XorrisO *xorriso, int flag) +{ + static char text[][80]={ + +#ifdef Xorriso_no_helP + +"This binary program does not contain a help text.", +"If available, read: man 1 xorriso", + +#else + +"This program creates, loads, manipulates and writes ISO 9660 filesystem", +"images with Rock Ridge extensions. Write targets can be drives with optical", +"media or local filesystem objects.", +"", +"Preparation options:", +"Drive addresses are either /dev/... as listed with option -devices or", +"disk files, eventually with prefix \"stdio:\" if non-CD-drive in /dev tree.", +"E.g. /dev/sr0 , /tmp/pseudo_drive , stdio:/dev/sdc", +" -dev address Set input and output drive and load eventual ISO image.", +" Set the image expansion method to growing.", +" -indev address Set input drive and load eventual ISO image. Use expansion", +" methods modifying or blind growing.", +" -outdev address", +" Set output drive and use modifying or blind growing.", +" -drive_class \"harmless\"|\"banned\"|\"risky\"|\"clear_list\" disk_pattern", +" Add a drive path pattern to one of the safety lists or make", +" those lists empty. Defaulty entry in \"risky\" is \"/dev\".", +" -grow_blindly \"off\"|predicted_nwa", +" Switch between modifying and blind growing.", +" -load \"session\"|\"track\"|\"lba\"|\"sbsector\"|\"volid\"|\"auto\" id", +" Load a particular (outdated) ISO image from a -dev or", +" -indev which hosts more than one session.", +" -rom_toc_scan \"on\"|\"off\"[:\"emul_on\"|\"emul_off\"]", +" Enable scanning for ISO sessions on read-only drives/media", +" resp. on overwriteable media with emulated TOC.", +" -assert_volid pattern severity", +" Accept input image only if its volume id matches pattern.", +" -charset name Set the character set name to be used for file name", +" conversion from and to media.", +" -in_charset name", +" Like -charset but only for conversion from media.", +" -out_charset name", +" Like -charset but only for conversion to media.", +" -local_charset name", +" Override system assumption of the local character set name.", +" -ban_stdio_write", +" Allow for writing only the usage of optical drives.", +" -blank \"fast\"|\"all\"|\"deformat\"|\"deformat_quickest\"", +" Blank media resp. invalidate ISO image on media.", +" -format \"as_needed\"|\"full\"|\"fast\"|\"by_index_#\"|\"by_size_#\"", +" Format BD-RE, DVD-RAM, DVD-RW, DVD+RW.", +" -volid volume_id", +" Specifies the volume ID text. (32 chars out of [A-Z0-9_])", +" -publisher name", +" Specifies the publisher name. (128 chars)", +" -application_id name", +" Specifies the application id. (128 chars)", +" -joliet \"on\"|\"off\"", +" Generate Joliet info additional to Rock Ridge info.", +" -compliance rule[:rule...]", +" Allow more or less harmless deviations from strict standards", +" compliance.", +" -boot_image \"any\"|\"isolinux\" \"discard\"|\"keep\"|\"patch\"|\"dir=\"", +" \"bin_path=\"|\"cat_path=\"|\"load_size=\"", +" Whether to discard or keep an exiting El Torito boot image.", +" ISOLINUX can be made bootable by dir=/ or dir=/isolinux", +" or dir=/boot/isolinux or by bin_path=... and cat_path=...", +" The ISOLINUX files need to be added to the ISO image by", +" help of the usual commands like -map or -add.", +"", +" -uid uid User id to be used for the whole multi-session ISO image.", +" -gid gid Group id for the same purpose.", +"", +" -devices Show list of available optical drives and their addresses.", +"", +" -toc Show media specific table of content (sessions).", +"", +" -mount_cmd drive entity id path", +" Print to result channel a command suitable to mount the", +" depicted entity (see -load) at the given directory path.", +" -session_string drive entity id \"linux:\"path|\"freebsd:\"path|form", +" Print foreign OS command or custom line.", +"", +" -list_formats Show media specific list of format descriptors.", +"", +" -print_size Print the foreseeable consumption by next -commit.", +"", +" -tell_media_space", +" Print foreseeable available space on output media", +"", +"Options with variable length path list [...] need the list delimiter text", +"as end mark if they are followed by another option. By default this delimiter", +"is \"--\". In dialog and with options read from files, the line end serves", +"as such a mark. With program arguments this mark can be omitted only with", +"the last option in the list of arguments.", +"For brevity the list delimiter is referred as \"--\" throughout this text.", +"", +" -list_delimiter text Set the list delimiter to be used instead of \"--\"", +" It has to be a single word, must not be empty, not longer", +" than 80 characters, may mot contain quotation marks.", +"", +"Manipulation options:", +"disk_path is a path to an object in the local filesystem tree.", +"iso_rr_path is the Rock Ridge name of a file object in the ISO image.", +"pathspec is either a disk_path or (if allowed) a pair: iso_rr_path=disk_path", +"Options marked by [***] have variable argument length and perform pattern", +"expansion if enabled by -iso_rr_pattern resp. -disk_pattern.", +"", +" -pathspecs \"on\"|\"off\" Allow or disallow pathspecs of form ", +" iso_rr_path=disk_path . Only \"off\" allows eventual", +" -disk_pattern expansion.", +" -add pathspec [...] | disk_path [***]", +" Insert the given files or directory trees from", +" filesystem into the ISO image. Much like mkisofs.", +" -add_plainly \"none\"|\"unknown\"|\"dashed\"|\"any\"", +" Whether to add lonely arguments as pathspec resp. disk_path.", +" -path_list disk_path", +" Like -add but read the pathspecs from file disk_path.", +" -quoted_path_list disk_path", +" Like -path_list but with line rules as -dialog \"on\".", +"", +" -map disk_path iso_rr_path", +" Insert disk file object at the given iso_rr_path.", +" -map_single disk_path iso_rr_path", +" Like -map but with directory do not insert its sub tree.", +" -map_l disk_prefix iso_rr_prefix disk_path [***]", +" Performs -map with each disk_path.", +" -update disk_path iso_rr_path", +" Compare both file objects and do what is necessary to make", +" iso_rr_path a matching copy of disk_path.", +" -update_r disk_path iso_rr_path", +" Like -update but affecting all files below directories.", +" -update_l disk_prefix iso_rr_prefix disk_path [***]", +" Performs -update_r with each disk_path.", +" -cut_out disk_path byte_offset byte_count iso_rr_path", +" Map a byte interval of a regular disk file into a regular", +" file in the ISO image.", +"", +" -cpr disk_path [***] iso_rr_path", +" Insert the given files or directory trees from filesystem", +" into the ISO image, according to the rules of cp -r.", +"", +" -rm iso_rr_path [***]", +" Delete the given files from the ISO image.", +" -rm_r iso_rr_path [***]", +" Delete the given directory trees from ISO image.", +" -mv iso_rr_path [***] iso_rr_path", +" Rename the given file objects in the ISO tree to the last", +" argument in the list.", +" -chown uid iso_rr_path [***]", +" Equivalent to chown in the ISO image.", +" -chown_r uid iso_rr_path [***]", +" Like -chown but affecting all files below directories.", +" -chgrp gid iso_rr_path [***]", +" Equivalent to chgrp in the ISO image.", +" -chgrp_r gid iso_rr_path [***]", +" Like -chgrp but affecting all files below directories.", +" -chmod mode iso_rr_path [***]", +" Equivalent to chmod in the ISO image.", +" -chmod_r mode iso_rr_path [***]", +" Like -chmod but affecting all files below directories.", +" -alter_date type timestring iso_rr_path [***]", +" Alter the date entries of a file in the ISO image. type is", +" one of \"a\", \"m\", \"b\" for:", +" access time, modification time, both times.", +" -alter_date_r type timestring iso_rr_path [***]", +" Like -alter_date but affecting all files below directories.", +" -find iso_rr_path [test [test ...]] [-exec action [params]]", +" performs an action on files below the current working", +" directory in the ISO image. If -name pattern is given", +" then only files with matching leaf names are processed.", +" If -type is given then only files with matching type are", +" processed. Types: block,char,dir,pipe,file,link,socket.", +" Further tests: -damaged, -undamaged, -lba_range start count", +" action may be one of: echo, chown, chown_r, chgrp, chgrp_r", +" chmod, chmod_r, alter_date, alter_date_r, lsdl, compare,", +" rm, rm_r, compare, update, report_damage, find.", +" params are their arguments except iso_rr_path.", +" echo, lsdl, rm, rm_r, report_damage have no params at all.", +" -mkdir iso_rr_path [...]", +" Create empty directories if they do not exist yet.", +" -rmdir iso_rr_path [***]", +" Delete empty directories.", +" -- Default list delimiter marking the end of action argument", +" list. It may be changed by option -list_delimiter.", +"", +" -not_paths disk_path [***]", +" Add the given paths to the list of excluded absolute paths.", +" -not_leaf pattern", +" Add the given pattern to the list of leafname exclusions.", +" -not_list disk_path", +" Read lines from disk_path and use as -not_paths (with \"/\")", +" or as -not_leaf (without \"/\").", +" -quoted_not_list disk_path", +" Like -not_list but with line rules as -dialog \"on\".", +" -not_mgt \"reset\"|\"on\"|\"off\"|\"param_on\"|\"subtree_on\"|\"ignore_on\"", +" Control effect of exclusion lists.", +" -follow \"on\"|\"pattern:param:link:mount:limit=#\"|\"default\"|\"off\"", +" Follow symbolic links and mount points within disk_path.", +" -overwrite \"on\"|\"nondir\"|\"off\"", +" Allow or disallow to overwrite existing files in ISO image.", +" -split_size number[\"k\"|\"m\"]", +" Set the threshold for automatic splitting of regular files.", +" -reassure \"on\"|\"tree\"|\"off\"", +" If \"on\" then ask the user for \"y\" or \"n\" with any", +" file before deleting or overwriting it in the ISO image.", +"", +"Write-to-media options:", +"", +" -rollback Discard the manipulated ISO image and reload it.", +"", +" -commit Perform the write operation and then perform -dev outdrive.", +" Hint: To perform a final write operation with no new -dev", +" and no new loading of image, execute option -end.", +" -commit_eject \"in\"|\"out\"|\"all\"|\"none\"", +" Like -commit but rather eject than load image from outdrive.", +" Give up any unejected drive afterwards.", +" -close \"on\"|\"off\"", +" If \"on\" then mark the written media as not appendable.", +" -padding number[\"k\"|\"m\"]", +" Append extra bytes to image stream. (Default is 300k)", +" -dummy \"on\"|\"off\"", +" If \"on\" simulate burning. Refuse if media cannot simulate.", +" -speed number[\"k/s\"|\"m/s\"|\"[x]CD\"|\"[x]DVD\"|\"[x]BD\"]", +" Set the burn speed. Default is 0 = maximum speed.", +" -stream_recording \"on\"|\"off\"", +" Try to circumvent slow checkread on DVD-RAM and BD-RE.", +" -fs number[\"k\"|\"m\"]", +" Set the size of the fifo buffer. (Default is 4m)", +" -eject \"in\"|\"out\"|\"all\"", +" Immediately eject the media in -indev, resp. -outdev,", +" resp. both.", +"", +"Navigation options:", +"", +" -cd iso_rr_path Change working directory in the ISO image. iso_rr_paths", +" which do not begin with '/' will be inserted beginning at", +" the path given with -cd. -ls patterns will eventually", +" looked up at this path.", +" -cdi disk_path Same as -cd disk_path", +" -cdx disk_path Change the current working directory in the local", +" filesystem. disk_paths which do not begin with '/'", +" will be looked up beginning at the path given with -cdx.", +" -lsx patterns will eventually be looked up at this path.", +" -pwd tells the current working directory in the ISO image.", +" -pwdi same as -pwd.", +" -pwdx tells the current working directory in the local filesystem.", +"", +" -iso_rr_pattern \"on\"|\"ls\"|\"off\"", +" Enable or disable pattern expansions for ISO image commands", +" marked by [***]. \"ls\" restricts it to -ls and -du.", +" -disk_pattern \"on\"|\"ls\"|\"off\"", +" Enable or disable pattern expansions for local filesystem", +" commands marked by [***]. \"ls\" restricts to -ls*x and -du*x.", +"", +" -ls pattern [***] lists files of the ISO image which match one of the", +" given shell parser patterns. (I.e. wildcards '*' '?').", +" Directories are listed by their content.", +" -lsd pattern [***] like -ls but listing directories as single items.", +" -lsl pattern [***] like -ls but also telling some file attributes.", +" -lsdl pattern [***] like -lsd but also telling some file attributes.", +"", +" -lsx pattern [***] lists files of the local filesystem which match one", +" of the patterns. Directories are listed by their content.", +" -lsdx pattern [***] like -lsx but listing directories as single items.", +" -lslx pattern [***] like -lsx but also telling some file attributes.", +" -lsdlx pattern [***] like -lsdx but also telling some file attributes.", +"", +" -du pattern [***] recursively lists sizes of files or directories in the", +" ISO image which match one of the shell parser patterns.", +" -dux pattern [***] recursively lists sizes of files or directories in the", +" local filesystem which match one of the shell parser", +" patterns.", +" -dus pattern [***] like -du but summing up subdirectories without", +" listing them explicitely.", +" -dusx pattern [***] like -dux but summing up subdirectories without", +" listing them explicitely.", +"", +" -findx disk_path [-name pattern] [-type t] [-exec action [params]]", +" Like -find but operating on local filesystem. Most -exec", +" actions are defaulted to action is always echo. Supported", +" actions are: in_iso, not_in_iso, is_full_in_iso,", +" add_missing, empty_iso_dir.", +"", +" -compare disk_path iso_rr_path", +" compare attributes and in case of regular data files the", +" content of filesystem object and ISO object.", +" -compare_r disk_path iso_rr_path ", +" Like -compare but affecting all files below directories.", +" -compare_l disk_prefix iso_rr_prefix disk_path [***]", +" Performs -compare_r with each disk_path.", +"", +"Restore options which copy file objects from ISO image to disk filesystem:", +" -osirrox \"on\"|\"device_files\"|\"off\":\"concat_split_on\"|\"concat_split_off\"", +" By default \"off\" the inverse operation of xorriso from ISO", +" image to disk filesystem is disabled. \"on\" allows xorriso", +" to create, overwrite, delete files in the disk filesystem.", +" -extract iso_rr_path disk_path", +" Copy tree under iso_rr_path onto disk address disk_path.", +" This avoids the pitfalls of cp -r addressing rules.", +" -extract_l iso_rr_prefix disk_prefix iso_rr_path [***]", +" Perform -extract_r with each iso_rr_path.", +" -extract_single iso_rr_path disk_path", +" Like -extract but with directory do not restore sub tree.", +" -extract_cut iso_rr_path byte_offset byte_count disk_path", +" Copy a byte interval from iso_rr_path to disk_path.", +" This is governed in part by -check_media_defaults.", +" -cpx iso_rr_path [***] disk_path", +" Copy leaf file objects from ISO image to disk filesystem.", +" -cpax iso_rr_path [***] disk_path", +" Like -cpx but trying to restore timestamps and ownership.", +" -cp_rx iso_rr_path [***] disk_path", +" Copy directory trees from ISO image to disk filesystem.", +" -cp_rax iso_rr_path [***] disk_path", +" Like -cp_rx but trying to restore timestamps and ownership.", +" -paste_in iso_rr_path disk_path byte_offset byte_count", +" Copy ISO file content into a byte interval of a disk file.", +" -mount drive entity id path", +" Like -mount_cmd but actually performing that command if it", +" not setuid or setgid is active.", +"", +"Evaluation of readability:", +" -check_media [options] --", +" Try to read data blocks from media and report about the", +" outcome. Several options modify the behavior:", +" use=indev|outdev , what=track|session ,", +" min_lba=blockadr , max_lba=blockadr ,", +" abort_file=path , time_limit=seconds , item_limit=number ,", +" retry=on|off|default , data_to=filepath ,", +" sector_map=filepath , map_with_volid=on|off ,", +" patch_lba0=on|off|force|blockadr[:force] ,", +" report=blocks|files|blocks_files", +" -check_media_defaults [options] --", +" Preset options for runs of -check_media and -extract_cut.", +"", +"Compatibility emulation (argument list may be ended by list delimiter --):", +" -as mkisofs [-help|-version|-o|-R|-J|-V|-P|-f|-m|-exclude-list|-no-pad|", +" -M|-C|-graft-points|-path-list|pathspecs|", +" -no-emul-boot|-b|-c|-boot-info-table|-boot-load-size]", +" Perform some mkisofs gestures, understand pathspecs as mkisofs", +" does. Commit happens outside emulation at usual occasions.", +" -as cdrecord [-help|-v|dev=|speed=|blank=|fs=|-eject|-atip|padsize=|path|-]", +" Perform some cdrecord gestures, eventually write at most one", +" data track to blank or overwriteable media.", +" -pacifier \"xorriso\"|\"cdrecord\"|\"mkisofs\"", +" Choose format of UPDATE pacifier during write operations.", +"", +"General options:", +" -help Print this text", +" -abort_on severity Set the threshhold for events to abort the program.", +" Useful severities: NEVER, ABORT, FATAL, FAILURE, SORRY, WARNING", +" -return_with severity exit_value Set the threshhold for events to return", +" at program end the given exit_value even if not aborted.", +" exit_value may be 0 or 32 to 63.", +" -report_about severity Set the threshhold for events to be reported.", +" Use -abort_on severities or: HINT, NOTE, UPDATE, DEBUG, ALL", +" -error_behavior \"image_loading\"|\"file_extraction\" behavior", +" Behavior \"best_effort\" is most endurant but may produce", +" results which are correct only on the first glimpse.", +" -dialog \"on\"|\"off\"|\"single_line\"", +" After all arguments are processed, enter dialog mode.", +" \"single_line\" does not support newline characters within", +" open quotation marks and no line continuation by trailing \\.", +" -page len width Prompt user after len output lines (0=no prompt).", +" width (default 80) can adjust line number computation", +" to the output terminal's line width.", +#ifdef Xorriso_with_readlinE +" -use_stdin Use raw standard input even if libreadline is available", +" -use_readline Use libreadline for dialog if available", +" -history text Copy text into libreadline history. This command", +" itself is not copied to the history list.", +#endif /* Xorriso_with_readlinE */ +" -backslash_codes \"on\"|\"off\"|", +" \"in_double_quotes\"|\"in_quotes\"|\"with_quoted_input\"", +" [:\"with_program_arguments\"][:\"encode_output\"]", +" Disable or enable interpretation of \\a \\b \\e \\f \\n \\r \\t \\v", +" \\\\ \\NNN \\xNN \\cC in input or program arguments.", +" -pkt_output \"on\"|\"off\" Direct output to stdout and prefix each line", +" by a short header which tells channel id and a mode number.", +" Each such output packet is finalized by a newline.", +" Channel ids are 'R:' for result lines, 'I:' for notes", +" and error messages, 'M:' for -mark texts. Bit 0 of the", +" mode number tells whether the newline is also part of the", +" packet payload. Example of a info message with newline:", +" I:1: enter option text :", +" -pkt_output:on is intended for use by frontend programs.", +" -logfile channel fileaddress Copy output of a channel to the given file.", +" channel may be 'R','I','M' as with -pkt_output or '.'", +" for the consolidated -pkt_output stream.", +" -mark text If text is not empty it will get put out each time an", +" option is completed.", +" -temp_mem_limit number[\"k\"|\"m\"]", +" Set the maximum size for pattern expansion. (Default is 16m)", +" -prog text Use text as this program's name in subsequent messages", +" -prog_help text Use text as this program's name and perform -help", +" -status mode|filter Report the current settings of persistent options.", +" Modes:", +" short... print only important or altered options", +" long ... print options even if they have default settings", +" long_history like long plus -history: lines", +" Filters begin with '-' and are compared literally against the", +" output lines of -status long_history. A line is put out only", +" if its start matches the filter.", +" -status_history_max number Maximum number of history lines to be reported", +" with -status:long_history", +" -options_from_file fileaddress", +" Reads lines from the given file and executes them as program", +" options.", +" -no_rc Only if used as first command line argument this option", +" prevents reading and interpretation of startup files.", +" -print text", +" Print a text to result channel.", +" -prompt text", +" Wait for Enter key resp. for a line of input at stdin.", +" -errfile_log mode path|channel", +" Log disk paths of files involved in problem events.", +" -session_log path", +" Set path of a file where a log record gets appended after", +" each session. Form: timestamp start_lba size volume-id", +" # any text Is ignored. In dialog mode the input line will be stored in", +" the eventual readline history, nevertheless.", +" -version Tell program and version number", +" -end End program. Commit eventual pending changes.", +" -rollback_end", +" End program. Discard pending changes.", +"", +"", +"Option -page causes a user prompt after the given number of result lines.", +"Empty input resumes output until the next prompt. Other input may be:", +" @ suppresses paging until the current action is done", +" @@ suppresses further result output but continues the action", +" @@@ aborts the current action", +" other aborts the current action and executes input as new", +" option", +"", + +#endif /* ! Xorriso_no_helP */ + +"@ENDE_OF_HELPTEXT_(HOPEFULLY_UNIQUELY_SILLY_TEXT)@" + }; + + char *tpt= NULL; + int i,pass; + + Xorriso_restxt(xorriso,"\n"); + sprintf(xorriso->result_line,"usage: %s [settings|actions]\n", + xorriso->progname); + Xorriso_result(xorriso,0); + Xorriso_restxt(xorriso,"\n"); + for(pass=0;pass<1;pass++) { + for(i=0;1;i++) { + if(pass==0) + tpt= text[i]; + + if(strcmp(tpt,"@ENDE_OF_HELPTEXT_(HOPEFULLY_UNIQUELY_SILLY_TEXT)@")==0) + break; + sprintf(xorriso->result_line,"%s\n",tpt); + Xorriso_result(xorriso,0); + if(xorriso->request_to_abort) + return(1); + } + } + Xorriso_restxt(xorriso,"\n"); + return(1); +} + + +/* Option -history */ +int Xorriso_option_history(struct XorrisO *xorriso, char *line, int flag) +{ + Xorriso_dialog_input(xorriso,line,strlen(line)+1,2); + return(1); +} + + +/* Option -iso_rr_pattern "on"|"ls"|"off" */ +int Xorriso_option_iso_rr_pattern(struct XorrisO *xorriso, char *mode,int flag) +{ + if(strcmp(mode, "off")==0) + xorriso->do_iso_rr_pattern= 0; + else if(strcmp(mode, "on")==0) + xorriso->do_iso_rr_pattern= 1; + else if(strcmp(mode, "ls")==0) + xorriso->do_iso_rr_pattern= 2; + else { + sprintf(xorriso->info_text, "-iso_rr_pattern: unknown mode '%s'", mode); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + return(1); +} + + +/* Option -joliet "on"|"off" */ +int Xorriso_option_joliet(struct XorrisO *xorriso, char *mode, int flag) +{ + if(strcmp(mode, "off")==0) + xorriso->do_joliet= 0; + else if(strcmp(mode, "on")==0) + xorriso->do_joliet= 1; + else { + sprintf(xorriso->info_text, "-joliet: unknown mode '%s'", mode); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + return(1); +} + + +/* Option -list_delimiter */ +int Xorriso_option_list_delimiter(struct XorrisO *xorriso, char *text, + int flag) +{ + int ret, argc; + char **argv= NULL; + + if(text[0] == 0) { + sprintf(xorriso->info_text, + "-list_delimiter: New delimiter text is empty"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + if(strlen(text) > 80) { + sprintf(xorriso->info_text, + "-list_delimiter: New delimiter text is too long"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + ret= Sfile_make_argv(xorriso->progname, text, &argc, &argv, 4); + if(ret > 0) { + if(argc > 2) { + sprintf(xorriso->info_text, + "-list_delimiter: New delimiter text contains more than one word"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + } + Sfile_make_argv(xorriso->progname, text, &argc, &argv, 2); + if(argc > 2) + return(0); + } + if(strchr(text, '"') != NULL || strchr(text, '\'') != NULL) { + sprintf(xorriso->info_text, + "-list_delimiter: New delimiter text contains quotation marks"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + strcpy(xorriso->list_delimiter, text); + return(1); +} + + +/* Option -list_formats */ +int Xorriso_option_list_formats(struct XorrisO *xorriso, int flag) +{ + int ret; + + ret= Xorriso_list_formats(xorriso, 0); + return(ret); +} + + +/* Option -load session|track|sbsector value */ +/* @param flag bit0= with adr_mode sbsector: adr_value is possibly 16 too high + @return <=0 error , 1 success, 2 revoked by -reassure +*/ +int Xorriso_option_load(struct XorrisO *xorriso, char *adr_mode, + char *adr_value, int flag) +{ + int ret; + + if(xorriso->volset_change_pending) { + sprintf(xorriso->info_text, + "-load: Image changes pending. -commit or -rollback first"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + ret= Xorriso_reassure(xorriso, "-load", "loads an alternative image", 0); + if(ret<=0) + return(2); + +#ifndef NIX + + ret= Xorriso_decode_load_adr(xorriso, "-load", adr_mode, adr_value, + &(xorriso->image_start_mode), + xorriso->image_start_value, 0); + if(ret <= 0) + return(ret); + +#else + + double num; + int l; + + if(strcmp(adr_mode, "auto")==0) + xorriso->image_start_mode= 0; + else if(strcmp(adr_mode, "session")==0) + xorriso->image_start_mode= 1; + else if(strcmp(adr_mode, "track")==0) + xorriso->image_start_mode= 2; + else if(strcmp(adr_mode, "lba")==0 || strcmp(adr_mode, "sbsector")==0) + xorriso->image_start_mode= 3 | ((flag&1) << 16); + else if(strcmp(adr_mode, "volid")==0) + xorriso->image_start_mode= 4; + else { + sprintf(xorriso->info_text, "-load: unknown address mode '%s'", adr_mode); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + l= strlen(adr_value); + if(l==0) + xorriso->image_start_mode= 0; + + if(xorriso->image_start_mode>=1 && xorriso->image_start_mode<= 3) { + num= Scanf_io_size(adr_value, 0); + if(xorriso->image_start_mode==3 && + (adr_value[l-1]<'0' || adr_value[l-1]>'9')) + num/= 2048.0; + sprintf(xorriso->image_start_value, "%.f", num); + } else { + if(strlen(adr_value)>80) { + sprintf(xorriso->info_text, "-load: address value too long (80 < %d)", + (int) strlen(adr_value)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + strcpy(xorriso->image_start_value, adr_value); + } + +#endif /* NIX */ + + xorriso->image_start_mode|= (1<<30); /* enable non-default msc1 processing */ + if(strlen(xorriso->indev)>0) { + ret= Xorriso_option_rollback(xorriso, 1); /* Load image, no -reassure */ + if(ret<=0) + return(ret); + } + return(1); +} + + +/* Option -logfile */ +int Xorriso_option_logfile(struct XorrisO *xorriso, char *channel, + char *fileadr, int flag) +{ + int hflag,channel_no= 0, ret; + + if(channel[0]==0) { +logfile_wrong_form:; + sprintf(xorriso->info_text,"Wrong form. Correct would be: -logfile \".\"|\"R\"|\"I\"|\"M\" file_address"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + hflag= 2; + if(channel[0]=='R') + channel_no= 1; + else if(channel[0]=='I') + channel_no= 2; + else if(channel[0]=='M') + channel_no= 3; + else if(channel[0]=='.') + hflag= 4; + else + goto logfile_wrong_form; + if(strcmp(fileadr,"-")==0 || fileadr[0]==0) + hflag|= (1<<15); + xorriso->logfile[channel_no][0]= 0; + ret= Xorriso_write_to_channel(xorriso, fileadr, channel_no, hflag); + if(ret<=0) { + sprintf(xorriso->info_text, "Cannot open logfile: %s", fileadr); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + } else if(!(hflag&(1<<15))) + if(Sfile_str(xorriso->logfile[channel_no], fileadr, 0)<=0) + return(-1); + return(ret>0); +} + + +/* Options -ls alias -lsi and -lsl alias -lsli + and -lsd alias -lsdi and -lsdl alias -lsdli + and -du alias -dui and -dus alias -dusi + @param flag bit0= long format (-lsl , -du) + bit1= do not expand patterns but use literally + bit2= du rather than ls + bit3= list directories as themselves (ls -d) +*/ +int Xorriso_option_lsi(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag) +{ + int ret, end_idx, filec= 0, nump, i; + char **filev= NULL, **patterns= NULL; + off_t mem= 0; + struct stat stbuf; + + end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1); + if(xorriso->do_iso_rr_pattern==0) + flag|= 2; + + nump= end_idx - *idx; + if((flag&2) && nump>0 ) { + ; + } else if(nump <= 0) { + if(Xorriso_iso_lstat(xorriso, xorriso->wdi, &stbuf, 0)<0) { + sprintf(xorriso->info_text, + "Current -cd path does not yet exist in the ISO image"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + {ret= 0; goto ex;} + } + if(!S_ISDIR(stbuf.st_mode)) { + sprintf(xorriso->info_text, + "Current -cd meanwhile points to a non-directory in ISO image"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + {ret= 0; goto ex;} + } + patterns= calloc(1, sizeof(char *)); + if(patterns == NULL) { +no_memory:; + sprintf(xorriso->info_text, + "Cannot allocate enough memory for pattern expansion"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + {ret= -1; goto ex;} + } + nump= 1; + if(flag&8) + patterns[0]= "."; + else + patterns[0]= "*"; + flag&= ~2; + } else { + patterns= calloc(nump, sizeof(char *)); + if(patterns==NULL) + goto no_memory; + for(i= 0; i<nump; i++) { + if(argv[i + *idx][0]==0) + patterns[i]= "*"; + else + patterns[i]= argv[i + *idx]; + } + } + if(flag&2) { + ret= Xorriso_ls_filev(xorriso, xorriso->wdi, nump, argv + (*idx), mem, + flag&(1|4|8)); + } else if(nump==1 && strcmp(patterns[0],"*")==0 && !(flag&4)){ + /* save temporary memory by calling simpler function */ + ret= Xorriso_ls(xorriso, (flag&1)|4); + } else { + ret= Xorriso_expand_pattern(xorriso, nump, patterns, 0, &filec, &filev, + &mem, 0); + if(ret<=0) + {ret= 0; goto ex;} + ret= Xorriso_ls_filev(xorriso, xorriso->wdi, filec, filev, mem, + flag&(1|4|8)); + } + if(ret<=0) + {ret= 0; goto ex;} + + ret= 1; +ex:; + if(patterns!=NULL) + free((char *) patterns); + Sfile_destroy_argv(&filec, &filev, 0); + (*idx)= end_idx; + return(ret); +} + + +/* Options -lsx, -lslx, -lsdx , -lsdlx , -dux , -dusx + @param flag bit0= long format (-lslx , -dux) + bit1= do not expand patterns but use literally + bit2= du rather than ls + bit3= list directories as themselves (ls -d) +*/ +int Xorriso_option_lsx(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag) +{ + int ret, end_idx, filec= 0, nump, i; + char **filev= NULL, **patterns= NULL; + off_t mem= 0; + + end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1|2); + if(xorriso->do_disk_pattern==0) + flag|= 2; + + nump= end_idx - *idx; + if((flag&2) && nump>0) { + ; + } else if(nump <= 0) { + patterns= calloc(1, sizeof(char *)); + if(patterns == NULL) { +no_memory:; + sprintf(xorriso->info_text, + "Cannot allocate enough memory for pattern expansion"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + {ret= -1; goto ex;} + } + nump= 1; + if(flag&8) + patterns[0]= "."; + else + patterns[0]= "*"; + flag&= ~2; + } else { + patterns= calloc(nump, sizeof(char *)); + if(patterns==NULL) + goto no_memory; + for(i= 0; i<nump; i++) { + if(argv[i + *idx][0]==0) + patterns[i]= "*"; + else + patterns[i]= argv[i + *idx]; + } + } + if(flag&2) { + ret= Xorriso_lsx_filev(xorriso, xorriso->wdx, + nump, argv + (*idx), mem, flag&(1|4|8)); + +#ifdef Not_yeT + } else if(nump==1 && strcmp(patterns[0],"*")==0 && !(flag&4)){ + /* save temporary memory by calling simpler function */ + ret= Xorriso_ls(xorriso, (flag&1)|4); +#endif + + } else { + ret= Xorriso_expand_disk_pattern(xorriso, nump, patterns, 0, &filec, &filev, + &mem, 0); + if(ret<=0) + {ret= 0; goto ex;} + ret= Xorriso_lsx_filev(xorriso, xorriso->wdx, filec, filev, mem, + flag&(1|4|8)); + } + if(ret<=0) + {ret= 0; goto ex;} + + ret= 1; +ex:; + if(patterns!=NULL) + free((char *) patterns); + Sfile_destroy_argv(&filec, &filev, 0); + (*idx)= end_idx; + return(ret); +} + + +/* Option -map , -map_single */ +/* @param flag bit0=do not report the added item + bit1=do not reset pacifier, no final pacifier message + bit5=eventually do not insert directory tree +*/ +int Xorriso_option_map(struct XorrisO *xorriso, char *disk_path, + char *iso_path, int flag) +{ + int ret; + char eff_origin[SfileadrL], eff_dest[SfileadrL], *ipth; + + if(!(flag&2)) + Xorriso_pacifier_reset(xorriso, 0); + + ipth= iso_path; + if(ipth[0]==0) + ipth= disk_path; + if(disk_path[0]==0) { + sprintf(xorriso->info_text, "-map: Empty disk_path given"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 1); + return(0); + } + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, eff_origin, + 2|4); + if(ret<=0) + return(ret); + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, ipth, eff_dest, 2); + if(ret<=0) + return(ret); + ret= Xorriso_graft_in(xorriso, NULL, eff_origin, eff_dest, + (off_t) 0, (off_t) 0, 2|(flag&32)); + if(!(flag&2)) + Xorriso_pacifier_callback(xorriso, "files added", xorriso->pacifier_count, + xorriso->pacifier_total, "", 1); + if(ret<=0) + return(ret); + + if(!(flag&1)) { + sprintf(xorriso->info_text, "Added to ISO image: %s '%s'='%s'\n", + (ret>1 ? "directory" : "file"), (eff_dest[0] ? eff_dest : "/"), + eff_origin); + Xorriso_info(xorriso,0); + } + return(1); +} + + +/* Options -map_l , -compare_l , -update_l , -extract_l */ +/* @param flag bit8-11= mode 0= -map_l + 1= -compare_l + 2= -update_l + 3= -extract_l +*/ +int Xorriso_option_map_l(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag) +{ + int ret, end_idx, optc= 0, was_failure= 1, i, fret, mode; + int ns_flag= 2|4, nt_flag= 2, opt_args_flag= 2; + char source_prefix[SfileadrL], target_prefix[SfileadrL], *cmd, **optv= NULL; + char eff_source[SfileadrL], eff_target[SfileadrL], *source_pt, *s_wd, *t_wd; + char sfe[5*SfileadrL]; + + cmd= "-map_l"; + s_wd= xorriso->wdx; + t_wd= xorriso->wdi; + Xorriso_pacifier_reset(xorriso, 0); + mode= (flag>>8) & 15; + + if(mode==1) + cmd= "-compare_l"; + else if(mode==2) + cmd= "-update_l"; + else if(mode==3) { + cmd= "-extract_l"; + ns_flag= 2; + s_wd= xorriso->wdi; + nt_flag= 2|4; + t_wd= xorriso->wdx; + opt_args_flag= 0; + } + + end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1|2); + if(end_idx - (*idx) < 3) { + sprintf(xorriso->info_text, "%s: Not enough arguments given (%d < 3)", cmd, + end_idx - (*idx)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 1); + ret= 0; goto ex; + } + ret= Xorriso_normalize_img_path(xorriso, s_wd, argv[*idx], + source_prefix, ns_flag | 64); + if(ret<=0) + goto ex; + ret= Xorriso_normalize_img_path(xorriso, t_wd, argv[(*idx)+1], + target_prefix, nt_flag); + if(ret<=0) + goto ex; + ret= Xorriso_opt_args(xorriso, cmd, argc, argv, (*idx)+2, &end_idx, + &optc, &optv, opt_args_flag); + if(ret<=0) + goto ex; + + for(i= 0; i<optc; i++) { + ret= Xorriso_normalize_img_path(xorriso, s_wd, optv[i], + eff_source, ns_flag); + if(ret<=0) + goto ex; + strcpy(eff_target, target_prefix); + source_pt= eff_source; + if(source_prefix[0]) { + if(strncmp(source_prefix, eff_source, strlen(source_prefix))!=0) { + sprintf(xorriso->info_text, + "%s: disk_path %s does not begin with disk_prefix ", cmd, + Text_shellsafe(eff_source, sfe, 0)); + Text_shellsafe(source_prefix, + xorriso->info_text+strlen(xorriso->info_text), 0); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 1); + ret= 0; goto ex; + } + source_pt+= strlen(source_prefix); + } + strcat(eff_target, source_pt); + +#ifdef NIX + if(1) + fprintf(stderr, "xorriso_debug: %s %s %s\n", cmd, eff_source, eff_target); + else +#endif + + if(mode==0) + ret= Xorriso_option_map(xorriso, eff_source, eff_target, 2); + else if(mode==1) + ret= Xorriso_option_compare(xorriso, eff_source, eff_target, 2|8); + else if(mode==2) + ret= Xorriso_option_update(xorriso, eff_source, eff_target, 2|8); + else if(mode==3) + ret= Xorriso_option_extract(xorriso, eff_source, eff_target, 2); + + if(ret>0 && !xorriso->request_to_abort) + continue; /* regular bottom of loop */ + was_failure= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 2); + if(fret>=0) + continue; + goto ex; + } + if(mode==0) + Xorriso_pacifier_callback(xorriso, "files added", xorriso->pacifier_count, + xorriso->pacifier_total, "", 1); + else if(mode==1 || mode==2) + Xorriso_pacifier_callback(xorriso, "content bytes read", + xorriso->pacifier_count, 0, "", 1); + else if(mode==3) + Xorriso_pacifier_callback(xorriso, "files restored",xorriso->pacifier_count, + xorriso->pacifier_total, "", 1|4); + ret= 1; +ex:; + (*idx)= end_idx; + Xorriso_opt_args(xorriso, cmd, argc, argv, *idx, &end_idx, &optc, &optv, + 256); + if(ret<=0) + return(ret); + return(!was_failure); +} + + +/* Option -mark */ +int Xorriso_option_mark(struct XorrisO *xorriso, char *mark, int flag) +{ + if(mark[0]==0) + xorriso->mark_text[0]= 0; + else + strncpy(xorriso->mark_text,mark,sizeof(xorriso->mark_text)-1); + xorriso->mark_text[sizeof(xorriso->mark_text)-1]= 0; + return(1); +} + + +/* Option -mkdir alias -mkdiri */ +int Xorriso_option_mkdiri(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag) +{ + int i, end_idx, ret, was_failure= 0, fret; + + end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 0); + + for(i= *idx; i<end_idx; i++) { + ret= Xorriso_mkdir(xorriso, argv[i], 0); + if(ret>0 && !xorriso->request_to_abort) + continue; /* regular bottom of loop */ + was_failure= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); + if(fret>=0) + continue; + goto ex; + } + ret= 1; +ex:; + (*idx)= end_idx; + if(ret<=0) + return(ret); + return(!was_failure); +} + + +/* Options -mount , -mount_mds , -session_string */ +/* @param bit0= -mount_cmd: print mount command to result channel rather + than performing it + bit1= preform -session_string rather than -mount_cmd +*/ +int Xorriso_option_mount(struct XorrisO *xorriso, char *dev, char *adr_mode, + char *adr, char *cmd, int flag) +{ + int ret, entity_code= 0, m_flag; + char entity_id[81], *mnt; + + if(flag & 1) + mnt= "-mount_cmd"; + else if(flag & 2) + mnt= "-session_string"; + else { + mnt= "-mount"; + if(!xorriso->allow_restore) { + sprintf(xorriso->info_text, + "-mount: image-to-disk features are not enabled by option -osirrox"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + if(xorriso->volset_change_pending) { + sprintf(xorriso->info_text, + "%s: Image changes pending. -commit or -rollback first", mnt); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + } + ret= Xorriso_decode_load_adr(xorriso, mnt, adr_mode, adr, + &entity_code, entity_id, 0); + if(ret <= 0) + return(ret); + if(flag & 2) + m_flag= 1 | 4; + else + m_flag= (flag & 1) | 2; + ret= Xorriso_mount(xorriso, dev, entity_code, entity_id, cmd, m_flag); + return(ret); +} + + +/* Option -mv alias -mvi */ +int Xorriso_option_mvi(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag) +{ + int i, end_idx_dummy, ret, is_dir= 0, was_failure= 0, fret; + char sfe[5*SfileadrL], sfe2[5*SfileadrL]; + char eff_origin[SfileadrL], eff_dest[SfileadrL], dest_dir[SfileadrL]; + char leafname[SfileadrL]; + int optc= 0; + char **optv= NULL; + + ret= Xorriso_cpmv_args(xorriso, "-mvi", argc, argv, idx, + &optc, &optv, eff_dest, 0); + if(ret<=0) + goto ex; + if(ret==2) { + is_dir= 1; + strcpy(dest_dir, eff_dest); + } + /* Perform movements */ + for(i= 0; i<optc; i++) { + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi,optv[i],eff_origin,0); + if(ret<=0 || xorriso->request_to_abort) + goto problem_handler; + if(is_dir) { + ret= Sfile_leafname(eff_origin, leafname, 0); + if(ret<=0) + goto problem_handler; + strcpy(eff_dest, dest_dir); + ret= Sfile_add_to_path(eff_dest, leafname, 0); + if(ret<=0) { + sprintf(xorriso->info_text, "Effective path gets much too long (%d)", + (int) (strlen(eff_dest)+strlen(leafname)+1)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + goto problem_handler; + } + } + ret= Xorriso_rename(xorriso, NULL, eff_origin, eff_dest, 0); + if(ret<=0 || xorriso->request_to_abort) + goto problem_handler; + sprintf(xorriso->info_text, "Renamed in ISO image: %s to %s\n", + Text_shellsafe(eff_origin,sfe,0),Text_shellsafe(eff_dest,sfe2,0)); + Xorriso_info(xorriso, 0); + + continue; /* regular bottom of loop */ +problem_handler:; + was_failure= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); + if(fret>=0) + continue; + goto ex; + } + ret= !was_failure; +ex:; + Xorriso_opt_args(xorriso, "-mvi", + argc, argv, *idx, &end_idx_dummy, &optc, &optv, 256); + return(ret); +} + + +/* Option -no_rc */ +int Xorriso_option_no_rc(struct XorrisO *xorriso, int flag) +{ + xorriso->no_rc= 1; + return(1); +} + + +/* Option -not_leaf */ +int Xorriso_option_not_leaf(struct XorrisO *xorriso, char *pattern, int flag) +{ + regex_t re; + char regexpr[2*SfileadrL+2], sfe[5*SfileadrL]; + int ret= 0; + + if(pattern[0]==0) + {ret= 0; goto cannot_add;} + Xorriso__bourne_to_reg(pattern, regexpr, 0); + if(regcomp(&re, regexpr, 0)!=0) + {ret= 0; goto cannot_add;} + ret= Exclusions_add_not_leafs(xorriso->disk_exclusions, pattern, &re, 0); + if(ret<=0) { +cannot_add:; + sprintf(xorriso->info_text,"Cannot add pattern: -not_leaf %s", + Text_shellsafe(pattern, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(ret); + } + return(1); +} + + +/* Option -not_list , -quoted_not_list */ +/* @param flag bit0= -quoted_not_list */ +int Xorriso_option_not_list(struct XorrisO *xorriso, char *adr, int flag) +{ + int ret, linecount= 0, insertcount= 0, null= 0, argc= 0, i; + FILE *fp= NULL; + char sfe[5*SfileadrL], **argv= NULL; + + Xorriso_pacifier_reset(xorriso, 0); + if(adr[0]==0) { + sprintf(xorriso->info_text, "Empty file name given with %s", + (flag & 1) ? "-quoted_not_list" : "-not_list"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + ret= Xorriso_afile_fopen(xorriso, adr, "rb", &fp, 0); + if(ret <= 0) + return(0); + while(1) { + ret= Xorriso_read_lines(xorriso, fp, &linecount, &argc, &argv, + 4 | (flag & 1) ); + if(ret <= 0) + goto ex; + if(ret == 2) + break; + for(i= 0; i < argc; i++) { + if(argv[i][0] == 0) + continue; + if(strchr(argv[i], '/')!=NULL) { + null= 0; + ret= Xorriso_option_not_paths(xorriso, 1, argv + i, &null, 0); + } else + ret= Xorriso_option_not_leaf(xorriso, argv[i], 0); + if(ret<=0) + goto ex; + insertcount++; + } + } + ret= 1; +ex:; + if(fp!=NULL) + fclose(fp); + Xorriso_read_lines(xorriso, fp, &linecount, &argc, &argv, 2); + if(ret<=0) { + sprintf(xorriso->info_text, "Aborted reading of file %s in line number %d", + Text_shellsafe(adr, sfe, 0), linecount); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + } + sprintf(xorriso->info_text, "Added %d exclusion list items from file %s\n", + insertcount, Text_shellsafe(adr, sfe, 0)); + Xorriso_info(xorriso,0); + return(ret); +} + + +/* Option -not_mgt */ +int Xorriso_option_not_mgt(struct XorrisO *xorriso, char *setting, int flag) +{ + int ret; + char what_data[SfileadrL], *what, *what_next; + + if(Sfile_str(what_data, setting, 0)<=0) { + sprintf(xorriso->info_text, + "-not_mgt: setting string is much too long (%d)", + (int) strlen(setting)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + for(what= what_data; what!=NULL; what= what_next) { + what_next= strchr(what, ':'); + if(what_next!=NULL) { + *what_next= 0; + what_next++; + } + + if(strcmp(what, "reset")==0 || strcmp(what, "erase")==0) { + if(strcmp(what, "reset")==0) + xorriso->disk_excl_mode= 1; + Exclusions_destroy(&(xorriso->disk_exclusions), 0); + ret= Exclusions_new(&(xorriso->disk_exclusions), 0); + if(ret<=0) { + Xorriso_no_malloc_memory(xorriso, NULL, 0); + return(ret); + } + } else if(strcmp(what, "on")==0) { + xorriso->disk_excl_mode|= 1; + } else if(strcmp(what, "off")==0) { + xorriso->disk_excl_mode&= ~1; + } else if(strcmp(what, "param_on")==0) { + xorriso->disk_excl_mode|= 2; + } else if(strcmp(what, "param_off")==0) { + xorriso->disk_excl_mode&= ~2; + } else if(strcmp(what, "subtree_on")==0) { + xorriso->disk_excl_mode|= 4; + } else if(strcmp(what, "subtree_off")==0) { + xorriso->disk_excl_mode&= ~4; + } else if(strcmp(what, "ignore_on")==0) { + xorriso->disk_excl_mode|= 8; + } else if(strcmp(what, "ignore_off")==0) { + xorriso->disk_excl_mode&= ~8; + } else { + sprintf(xorriso->info_text, "-not_mgt: unknown setting '%s'", what); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + } + return(1); +} + + +/* Option -not_paths */ +int Xorriso_option_not_paths(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag) +{ + int ret, end_idx, num_descr, dummy, optc= 0, i; + char **descr= NULL, **optv= NULL, sfe[5*SfileadrL], eff_path[SfileadrL]; + + + end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, + (xorriso->do_disk_pattern==1) | 2); + if(end_idx<=0) + return(end_idx); + num_descr= end_idx - *idx; + if(num_descr<=0) + {ret= 1; goto ex;} + + /* produce absolute patterns */ + descr= TSOB_FELD(char *, num_descr); + if(descr==NULL) { +no_memory:; + Xorriso_no_pattern_memory(xorriso, sizeof(char *) * (off_t) num_descr, 0); + ret= -1; goto ex; + } + for(i= 0; i<num_descr; i++) + descr[i]= NULL; + for(i= 0; i<num_descr; i++) { + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, argv[i+*idx], + eff_path, 2|4); + if(ret<=0) + goto ex; + descr[i]= strdup(eff_path); + if(descr[i]==NULL) + goto no_memory; + } + + ret= Xorriso_opt_args(xorriso, "-not_paths", + num_descr, descr, 0, &dummy, &optc, &optv, 2); + if(ret<=0) + goto ex; + ret= Exclusions_add_not_paths(xorriso->disk_exclusions, + num_descr, descr, optc, optv, 0); + if(ret<=0) { + sprintf(xorriso->info_text,"Cannot add path list: -not_paths %s%s %s", + Text_shellsafe(argv[*idx], sfe, 0), (num_descr>1 ? " ..." : ""), + xorriso->list_delimiter); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + } +ex:; + (*idx)= end_idx; + Xorriso_opt_args(xorriso, "-not_paths", + num_descr, descr, 0, &dummy, &optc, &optv, 256); + if(descr!=NULL) { + for(i= 0; i<num_descr; i++) + if(descr[i]!=NULL) + free(descr[i]); + free((char *) descr); + descr= NULL; + } + return(ret); +} + + +/* Option -options_from_file */ +int Xorriso_option_options_from_file(struct XorrisO *xorriso, char *adr, + int flag) +/* + bit0= called from Xorriso_prescan_args, + therefore execute via that same function +*/ +/* +return: + <=0 error , 1 = success , 3 = end program run +*/ +{ + int ret,linecount= 0, argc= 0, was_failure= 0, fret; + FILE *fp= NULL; + char shellsafe[5*SfileadrL]; + char **argv= NULL; + int linec= 0; + char *line= NULL, **linev= NULL; + + if(adr[0]==0) { + sprintf(xorriso->info_text,"Empty file name given with -options_from_file"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + Text_shellsafe(adr,shellsafe,0); + if(xorriso->is_dialog) { + sprintf(xorriso->info_text,"+ performing command lines from file %s :\n", + shellsafe); + Xorriso_info(xorriso,1); + } + ret= Xorriso_afile_fopen(xorriso, adr, "rb", &fp, 0); + if(ret <= 0) + return(0); + while(1) { + ret= Xorriso_read_lines(xorriso, fp, &linecount, &linec, &linev, 1 | 8); + if(ret <= 0) + goto ex; /* no problem_handler because there is no sense in going on */ + if(ret == 2) + break; + line= linev[0]; + if(line[0]==0 || line[0]=='#') + continue; + + if(flag&1) { + ret= Sfile_make_argv(xorriso->progname, line, &argc, &argv, + 4 | 8 | ((xorriso->bsl_interpretation & 3) << 5)); + if(ret<=0) + goto problem_handler; + ret= Xorriso_prescan_args(xorriso,argc,argv,1); + if(ret==0) + {ret= 3; goto ex;} + if(ret<0) + goto problem_handler; + } else { + if(xorriso->is_dialog) { + sprintf(xorriso->info_text,"+ %d: %s\n",linecount,line); + Xorriso_info(xorriso,1); + } + ret= Xorriso_execute_option(xorriso,line,1|(1<<16)); + if(ret==3) + goto ex; + if(ret<=0) + goto problem_handler; + } + + continue; /* regular bottom of loop */ +problem_handler:; + was_failure= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1); + if(fret>=0) + continue; + goto ex; + } + ret= 1; +ex:; + Sfile_make_argv("", "", &argc, &argv, 2); /* release memory */ + Xorriso_read_lines(xorriso, fp, &linecount, &linec, &linev, 2); + Xorriso_reset_counters(xorriso,0); + if(fp!=NULL) + fclose(fp); + if(ret<=0) { + sprintf(xorriso->info_text, + "error triggered by line %d of file:\n %s\n", + linecount,shellsafe); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 1); + } + if(ret!=1) + return(ret); + return(!was_failure); +} + + +/* Option -osirrox "on"|"off" */ +int Xorriso_option_osirrox(struct XorrisO *xorriso, char *mode, int flag) +{ + int l; + char *npt, *cpt; + + npt= cpt= mode; + for(cpt= mode; npt!=NULL; cpt= npt+1) { + npt= strchr(cpt,':'); + if(npt==NULL) + l= strlen(cpt); + else + l= npt-cpt; + if(l==0 && mode[0]!=0) + goto unknown_mode; + if(strncmp(cpt, "off", l)==0) + xorriso->allow_restore= 0; + else if(strncmp(cpt, "device_files", l)==0) + xorriso->allow_restore= 2; + else if(strncmp(cpt, "on", l)==0 || mode[0]==0) + xorriso->allow_restore= 1; + else if(strncmp(cpt, "concat_split_on", l)==0) + xorriso->do_concat_split= 1; + else if(strncmp(cpt, "concat_split_off", l)==0) + xorriso->do_concat_split= 0; + else if(strncmp(cpt, "auto_chmod_on", l)==0) + xorriso->do_auto_chmod= 1; + else if(strncmp(cpt, "auto_chmod_off", l)==0) + xorriso->do_auto_chmod= 0; + else { +unknown_mode:; + sprintf(xorriso->info_text, "-osirrox: unknown mode '%s'", cpt); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + } + sprintf(xorriso->info_text, + "Copying of file objects from ISO image to disk filesystem is: %s\n", + xorriso->allow_restore ? "Enabled" : "Disabled"); + Xorriso_info(xorriso, 0); + return(1); +} + + +/* Option -overwrite "on"|"nondir"|"off" */ +int Xorriso_option_overwrite(struct XorrisO *xorriso, char *mode, int flag) +{ + if(strcmp(mode, "off")==0) + xorriso->do_overwrite= 0; + else if(strcmp(mode, "on")==0) + xorriso->do_overwrite= 1; + else if(strcmp(mode, "nondir")==0) + xorriso->do_overwrite= 2; + else { + sprintf(xorriso->info_text, "-overwrite: unknown mode '%s'", mode); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + return(1); +} + + +/* Option -pacifier */ +int Xorriso_option_pacifier(struct XorrisO *xorriso, char *style, int flag) +{ + if(strcmp(style, "xorriso")==0 || strcmp(style, "default")==0) + xorriso->pacifier_style= 0; + else if(strcmp(style, "mkisofs")==0 || strcmp(style, "genisofs")==0 || + strcmp(style, "genisoimage")==0 || strcmp(style, "xorrisofs")==0) + xorriso->pacifier_style= 1; + else if(strcmp(style, "cdrecord")==0 || strcmp(style, "cdrskin")==0 || + strcmp(style, "wodim")==0 || strcmp(style, "xorrecord")==0) + xorriso->pacifier_style= 2; + else { + sprintf(xorriso->info_text, "-pacifier: unknown behavior code '%s'", style); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + return(1); +} + + +/* Option -padding */ +int Xorriso_option_padding(struct XorrisO *xorriso, char *size, int flag) +{ + double num; + + num= Scanf_io_size(size, 0); + if(num < 0 || num > 1024.0 * 1024.0 * 1024.0) { + sprintf(xorriso->info_text, "-padding: wrong size %.f (allowed: %.f - %.f)", + num, 0.0, 1024.0 * 1024.0 * 1024.0); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + xorriso->padding= num; + if(xorriso->padding/2048 != num/2048.0) + xorriso->padding++; + return(1); +} + + +/* Option -page */ +int Xorriso_option_page(struct XorrisO *xorriso, int len, int width, int flag) +{ + if(len<0 || width<=0) { + sprintf(xorriso->info_text, + "Improper numeric value of arguments of -page: %d %d", + len, width); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + xorriso->result_page_length= len; + xorriso->result_page_width= width; + return(1); +} + + +/* Option -paste_in */ +int Xorriso_option_paste_in(struct XorrisO *xorriso, char *iso_rr_path, + char *disk_path, char *start, char *count, int flag) +{ + int ret; + double num; + off_t startbyte, bytecount; + + num= Scanf_io_size(start, 0); + if(num<0 || num > 1.0e18) { /* 10^18 = 10^3 ^ 6 < 2^10 ^ 6 = 2^60 */ + sprintf(xorriso->info_text, + "-paste_in: startbyte address negative or much too large (%s)", start); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + startbyte= num; + num= Scanf_io_size(count, 0); + if(num<=0 || num > 1.0e18) { + sprintf(xorriso->info_text, + "-paste_in : bytecount zero, negative or much too large (%s)", count); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + bytecount= num; + sprintf(xorriso->info_text, "-paste_in from %s to %s, byte %.f to %.f", + disk_path, iso_rr_path, + (double) startbyte, (double) (startbyte+bytecount)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + + ret= Xorriso_paste_in(xorriso, disk_path, startbyte, bytecount, + iso_rr_path, 0); + return(ret); +} + + +/* Option -path_list , -quoted_path_list */ +/* @param flag bit0= -quoted_path_list */ +int Xorriso_option_path_list(struct XorrisO *xorriso, char *adr, int flag) +{ + int ret,linecount= 0, insertcount= 0, null= 0, was_failure= 0, fret= 0; + int was_ferror= 0, argc= 0, i; + FILE *fp= NULL; + char sfe[5*SfileadrL], **argv= NULL; + + Xorriso_pacifier_reset(xorriso, 0); + if(adr[0]==0) { + sprintf(xorriso->info_text,"Empty file name given with %s", + flag & 1 ? "-quoted_path_list" : "-path_list"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); + return(0); + } + ret= Xorriso_afile_fopen(xorriso, adr, "rb", &fp, 0); + if(ret <= 0) + return(0); + while(1) { + ret= Xorriso_read_lines(xorriso, fp, &linecount, &argc, &argv, + 4 | (flag & 1) ); + if(ret <= 0) + goto ex; + if(ret == 2) + break; + for(i= 0; i < argc; i++) { + if(argv[i][0] == 0) + continue; + null= 0; + ret= Xorriso_option_add(xorriso, 1, argv + i, &null, 1|2); + if(ret<=0 || xorriso->request_to_abort) + goto problem_handler; + insertcount++; + } + + continue; /* regular bottom of loop */ +problem_handler:; + was_failure= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); + if(fret>=0) + continue; + goto ex; + } + ret= 1; +ex:; + if(flag & 1) + Xorriso_read_lines(xorriso, fp, &linecount, &argc, &argv, 2); + + if(fp!=NULL) + fclose(fp); + Xorriso_pacifier_callback(xorriso, "files added", xorriso->pacifier_count, + xorriso->pacifier_total, "", 1); + if(ret<=0) { + sprintf(xorriso->info_text, "Aborted reading of file %s in line number %d", + Text_shellsafe(adr, sfe, 0), linecount); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, + (fret==-2 ? "NOTE" : "FAILURE"), 0); + } else + ret= !was_ferror; + sprintf(xorriso->info_text, "Added %d items from file %s\n", + insertcount, Text_shellsafe(adr, sfe, 0)); + Xorriso_info(xorriso,0); + if(ret<=0) + return(ret); + return(!was_failure); +} + + +/* Option -pathspecs */ +int Xorriso_option_pathspecs(struct XorrisO *xorriso, char *mode, int flag) +{ + if(strcmp(mode, "off")==0) + xorriso->allow_graft_points= 0; + else if(strcmp(mode, "on")==0) + xorriso->allow_graft_points= 1; + else { + sprintf(xorriso->info_text, "-pathspecs: unknown mode '%s'", mode); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + return(1); +} + + +/* Option -pkt_output */ +int Xorriso_option_pkt_output(struct XorrisO *xorriso, char *mode, int flag) +{ + if(strcmp(mode,"off")==0) + xorriso->packet_output= 0; + else + xorriso->packet_output= 1; + return(1); +} + + +/* Option -print */ +int Xorriso_option_print(struct XorrisO *xorriso, char *text, int flag) +{ + sprintf(xorriso->result_line,"%s\n",text); + Xorriso_result(xorriso,1); + return(1); +} + + +/* Option -print_size + @param flag bit0= report in mkisofs compatible form on real stdout +*/ +int Xorriso_option_print_size(struct XorrisO *xorriso, int flag) +{ + int ret, fd; + + if(!xorriso->volset_change_pending) { + sprintf(xorriso->info_text,"-print_size: No image modifications pending"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); + sprintf(xorriso->result_line,"Image size : 0s\n"); + Xorriso_result(xorriso,0); + return(2); + } + ret= Xorriso_write_session(xorriso, 1); + if(ret<=0) { + sprintf(xorriso->info_text,"-print_size: Failed to set up virtual -commit"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + if(flag&1) { + sprintf(xorriso->result_line,"%d\n", ret); + fd= xorriso->dev_fd_1; + if(fd<0) + fd= 1; + write(fd, xorriso->result_line, strlen(xorriso->result_line)); + fsync(fd); + } else { + sprintf(xorriso->result_line,"Image size : %ds\n", ret); + Xorriso_result(xorriso,0); + } + return(1); +} + + +/* Option -prog */ +int Xorriso_option_prog(struct XorrisO *xorriso, char *name, int flag) +{ + if(strlen(name)>=sizeof(xorriso->progname)) { + sprintf(xorriso->info_text, + "Name too long with option -prog (%d > %d)", + (int) strlen(name), (int) sizeof(xorriso->progname)-1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + if(Sfile_str(xorriso->progname,name,0)<=0) + return(-1); + return(1); +} + + +/* Option -prog_help */ +int Xorriso_option_prog_help(struct XorrisO *xorriso, char *name, int flag) +{ + int ret; + + ret= Xorriso_option_prog(xorriso, name, 0); + if(ret<=0) + return(ret); + ret= Xorriso_option_help(xorriso, 0); + return(ret); +} + + +/* Option -prompt */ +int Xorriso_option_prompt(struct XorrisO *xorriso, char *text, int flag) +{ + int ret; + char line[80]; + + strncpy(xorriso->result_line,text,sizeof(xorriso->result_line)-1); + xorriso->result_line[sizeof(xorriso->result_line)-1]= 0; + Xorriso_result(xorriso,0); + ret= Xorriso_dialog_input(xorriso, line, sizeof(line),1); + return(ret); +} + + +/* Option -publisher */ +int Xorriso_option_publisher(struct XorrisO *xorriso, char *name, int flag) +{ +#ifdef NIX + int ret; +#endif + + if(strlen(name)>=sizeof(xorriso->publisher)) { + sprintf(xorriso->info_text, + "Name too long with option -publisher (%d > %d)", + (int) strlen(name), (int) sizeof(xorriso->publisher)-1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + +#ifdef NIX + ret= Xorriso_set_publisher(xorriso, name, 0); + if(ret<=0) + return(ret); +#endif /* NIX */ + + if(Sfile_str(xorriso->publisher,name,0)<=0) + return(-1); + return(1); +} + + +/* Option -pwd alias -pwdi */ +int Xorriso_option_pwdi(struct XorrisO *xorriso, int flag) +{ + char sfe[5 * SfileadrL]; + + sprintf(xorriso->info_text,"current working directory in ISO image:\n"); + Xorriso_info(xorriso,0); + sprintf(xorriso->result_line,"%s/\n", Text_shellsafe(xorriso->wdi, sfe, 0)); + Xorriso_result(xorriso,0); + return(1); +} + + +/* Option -pwdx */ +int Xorriso_option_pwdx(struct XorrisO *xorriso, int flag) +{ + sprintf(xorriso->info_text,"current working directory on hard disk:\n"); + Xorriso_info(xorriso,0); + sprintf(xorriso->result_line,"%s/\n",xorriso->wdx); + Xorriso_result(xorriso,0); + return(1); +} + + +/* Option -reassure "on"|"tree"|"off" */ +int Xorriso_option_reassure(struct XorrisO *xorriso, char *mode, int flag) +{ + if(strcmp(mode, "off")==0) + xorriso->do_reassure= 0; + else if(strcmp(mode, "on")==0) + xorriso->do_reassure= 1; + else if(strcmp(mode, "tree")==0) + xorriso->do_reassure= 2; + else { + sprintf(xorriso->info_text, "-reassure: unknown mode '%s'", mode); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + return(1); +} + + +/* Option -compliance */ +int Xorriso_option_compliance(struct XorrisO *xorriso, char *mode, + int flag) +{ + return(Xorriso_relax_compliance(xorriso, mode, 0)); +} + + +/* Option -report_about */ +int Xorriso_option_report_about(struct XorrisO *xorriso, char *severity, + int flag) +{ + int ret, sev; + char sfe[5*SfileadrL]; + + ret= Xorriso__text_to_sev(severity, &sev, 0); + if(ret<=0) { + sprintf(xorriso->info_text, + "-report_about: Not a known severity name : %s", + Text_shellsafe(severity, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); + return(ret); + } + if(Sfile_str(xorriso->report_about_text,severity,0)<=0) + return(-1); + xorriso->report_about_severity= sev; + return(1); +} + + +/* Option -return_with */ +int Xorriso_option_return_with(struct XorrisO *xorriso, char *severity, + int exit_value, int flag) +{ + int ret, sev; + char sfe[5*SfileadrL]; + + ret= Xorriso__text_to_sev(severity, &sev, 0); + if(ret<=0) { + sprintf(xorriso->info_text, + "-return_with: Not a known severity name : %s", + Text_shellsafe(severity, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(ret); + } + if(exit_value && (exit_value < 32 || exit_value > 63)) { + sprintf(xorriso->info_text, + "-return_with: Not an allowed exit_value. Use 0, or 32 to 63."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + if(Sfile_str(xorriso->return_with_text,severity,0)<=0) + return(-1); + xorriso->return_with_severity= sev; + xorriso->return_with_value= exit_value; + return(1); +} + + +/* Options -rm alias -rmi , -rm_r alias -rm_ri , -rmdir alias -rmdiri */ +/* @param flag bit0=recursive , bit1= remove empty directory: rmdir */ +int Xorriso_option_rmi(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag) +{ + int i, ret, end_idx, was_failure= 0, fret; + char path[SfileadrL], eff_path[SfileadrL], sfe[5*SfileadrL]; + int optc= 0; + char **optv= NULL; + + ret= Xorriso_opt_args(xorriso, "-rm*i", + argc, argv, *idx, &end_idx, &optc, &optv, 0); + if(ret<=0) + goto ex; + for(i= 0; i<optc; i++) { + if(Sfile_str(path,optv[i],0)<=0) + {ret= -1; goto problem_handler;} + if(path[0]!='/') { + ret= Sfile_prepend_path(xorriso->wdi, path, 0); + if(ret<=0) + goto problem_handler; + } + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, path, eff_path, 1); + if(ret<0) + goto problem_handler; + if(ret==0) { + sprintf(xorriso->info_text, + "Cannot find path %s in loaded ISO image for removal", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + goto problem_handler; + } + strcpy(path, eff_path); + + ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, path, flag&(1|2)); + if(ret<=0 || xorriso->request_to_abort) + goto problem_handler; + if(ret<3) { + sprintf(xorriso->info_text, "Removed from ISO image: %s '%s'\n", + ((flag&2) ? "directory" : (ret>1 ? "subtree" : "file")), path); + Xorriso_info(xorriso, 0); + } + + continue; /* regular bottom of loop */ +problem_handler:; + was_failure= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); + if(fret>=0) + continue; + goto ex; + } + ret= 1; +ex:; + (*idx)= end_idx; + Xorriso_opt_args(xorriso, "-rm*i", + argc, argv, *idx, &end_idx, &optc, &optv, 256); + if(ret<=0) + return(ret); + return(!was_failure); +} + + +/* Option -rollback */ +/* @param flag bit0= do not -reassure + @return <=0 error , 1 success, 2 revoked by -reassure +*/ +int Xorriso_option_rollback(struct XorrisO *xorriso, int flag) +{ + int ret; + char indev[SfileadrL], *which_will; + + if(xorriso->volset_change_pending) + which_will= "revoke the pending image changes"; + else + which_will= "reload the image"; + if(!(flag&1)) { + ret= Xorriso_reassure(xorriso, "-rollback", which_will, 0); + if(ret<=0) + return(2); + } + + if(Sfile_str(indev, xorriso->indev, 0)<=0) + return(-1); + ret= Xorriso_give_up_drive(xorriso, 1|8); + if(ret<=0) + return(ret); + xorriso->image_start_mode&= ~(1<<31); /* reactivate eventual -load address */ + ret= Xorriso_option_dev(xorriso, indev, 1|4); + return(ret); +} + + +/* Option -rom_toc_scan */ +int Xorriso_option_rom_toc_scan(struct XorrisO *xorriso, char *mode, int flag) +{ + int l; + char *cpt, *npt; + + xorriso->toc_emulation_flag= 0; + npt= cpt= mode; + for(cpt= mode; npt != NULL; cpt= npt + 1) { + npt= strchr(cpt,':'); + if(npt==NULL) + l= strlen(cpt); + else + l= npt-cpt; + if(l==0) + goto unknown_mode; + if(strncmp(cpt, "off", l) == 0) + xorriso->toc_emulation_flag&= ~1; + else if(strncmp(cpt, "on", l) == 0) + xorriso->toc_emulation_flag|= 1; + else if(strncmp(cpt, "emul_off", l) == 0) + xorriso->toc_emulation_flag|= 2; + else if(strncmp(cpt, "emul_on", l) == 0) + xorriso->toc_emulation_flag&= ~2; + else { +unknown_mode:; + sprintf(xorriso->info_text, "-rom_toc_scan: unknown mode in '%s'", mode); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + } + return(1); +} + + +/* Option -session_log */ +int Xorriso_option_session_log(struct XorrisO *xorriso, char *path, int flag) +{ + if(Sfile_str(xorriso->session_logfile, path, 0)<=0) + return(-1); + return(1); +} + + +/* Option -speed */ +int Xorriso_option_speed(struct XorrisO *xorriso, char *speed, int flag) +{ + int is_cd= 1, unit_found= 0, ret, profile_number; + double num; + char *cpt, profile_name[80]; + + if(speed[0]==0 || strcmp(speed, "any")==0) { + xorriso->speed= 0; /* full speed */ + return(1); + } + + sscanf(speed,"%lf",&num); + for(cpt= speed+strlen(speed)-1; cpt>=speed; cpt--) + if(isdigit(*cpt) || *cpt=='.') + break; + cpt++; + + if(*cpt=='k' || *cpt=='K') { + /* is merchand kilobyte, stays merchand kilobyte */ + unit_found= 1; + } else if(*cpt=='m' || *cpt=='M') { + num*= 1000; + unit_found= 1; + } else if(*cpt=='x' || *cpt=='X') + cpt++; + + if (unit_found) { + ; + } else if(*cpt=='c' || *cpt=='C') { +cd_speed:; + num*= 176.4; + } else if(*cpt=='d' || *cpt=='D') { +dvd_speed:; + num*= 1385; + } else if(*cpt=='b' || *cpt=='B') { +bd_speed:; + num*= 4495.625; + } else { + ret= Xorriso_get_profile(xorriso, &profile_number, profile_name, 2); + is_cd= (ret==2); + if(is_cd) + goto cd_speed; + else if (ret == 3) + goto bd_speed; + else + goto dvd_speed; + } + + if(num> 2.0e9) { + sprintf(xorriso->info_text, + "-speed: Value too large or not recognizable: '%s'", speed); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + xorriso->speed= num; + if(xorriso->speed<num) + xorriso->speed++; + return(1); +} + + +/* Option -split_size */ +int Xorriso_option_split_size(struct XorrisO *xorriso, char *size, int flag) +{ + double num; + + num= Scanf_io_size(size, 0); + if(num > xorriso->file_size_limit && xorriso->file_size_limit > 0) { + sprintf(xorriso->info_text, "-split_size: too large %.f (allowed: %.f)", + num, (double) xorriso->file_size_limit); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } else if(num < 0) + num= 0.0; + xorriso->split_size= num; + return(1); +} + + +/* Option -status */ +int Xorriso_option_status(struct XorrisO *xorriso, char *mode, int flag) +{ + if(strcmp(mode,"short")==0) + Xorriso_status(xorriso,NULL,NULL,1); + else if(strcmp(mode,"long")==0) + Xorriso_status(xorriso,NULL,NULL,0); + else if(strcmp(mode,"long_history")==0) + Xorriso_status(xorriso,NULL,NULL,8); + else if(mode[0]=='-') + Xorriso_status(xorriso,mode,NULL,8); + else + Xorriso_status(xorriso,NULL,NULL,1); + return(1); +} + + +/* Option -status_history_max */ +int Xorriso_option_status_history_max(struct XorrisO *xorriso, int num, + int flag) +{ + if(num>=0 && num<1000000) + xorriso->status_history_max= num; + return(1); +} + + +/* Option -stream_recording */ +int Xorriso_option_stream_recording(struct XorrisO *xorriso, char *mode, + int flag) +{ + if(strcmp(mode,"on")==0 || mode[0]==0) + xorriso->do_stream_recording= 1; + else + xorriso->do_stream_recording= 0; + return(1); +} + + +/* Option -tell_media_space */ +int Xorriso_option_tell_media_space(struct XorrisO *xorriso, int flag) +{ + int ret, free_space= 0, media_space= 0; + + ret= Xorriso_tell_media_space(xorriso, &media_space, &free_space, 0); + if(ret<=0) { + sprintf(xorriso->info_text, "Cannot -tell_media_space"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + if(free_space<0) { + sprintf(xorriso->info_text, + "Pending image size larger than free space on media"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); + } + sprintf(xorriso->result_line, "Media space : %ds\n", media_space); + Xorriso_result(xorriso, 0); + sprintf(xorriso->result_line, "After commit : %ds\n", free_space); + Xorriso_result(xorriso, 0); + return(1); +} + + +/* Option -temp_mem_limit */ +int Xorriso_option_temp_mem_limit(struct XorrisO *xorriso, char *size, + int flag) +{ + double num; + + num= Scanf_io_size(size, 0); + if(num < 64.0 * 1024.0 || num > 1024.0 * 1024.0 * 1024.0) { + sprintf(xorriso->info_text, + "-temp_mem_limit: wrong size %.f (allowed: %.f - %.f)", + num, 64.0 * 1024.0, 1024.0 * 1024.0 * 1024.0); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + xorriso->temp_mem_limit= num; + return(1); +} + + +/* Option -toc */ +int Xorriso_option_toc(struct XorrisO *xorriso, int flag) +{ + int ret, in_ret= 1000; + + if(strcmp(xorriso->indev,xorriso->outdev)==0) + ret= Xorriso_toc(xorriso, 0); + else { + if(xorriso->indev[0]!=0) + in_ret= Xorriso_toc(xorriso, 0); + if(xorriso->indev[0]!=0 && xorriso->outdev[0]!=0) { + strcpy(xorriso->result_line, "-------------: ---------------------------------------------------------------\n"); + Xorriso_result(xorriso,0); + } + ret= 1; + if(xorriso->outdev[0]!=0) + ret= Xorriso_toc(xorriso, 2); + if(in_ret<ret) + ret= in_ret; + } + return(ret); +} + + +/* Option -uid */ +int Xorriso_option_uid(struct XorrisO *xorriso, char *uid, int flag) +{ + int ret; + + xorriso->do_global_uid= 0; + if(uid[0]==0 || strcmp(uid,"-")==0) + return(1); + ret= Xorriso_convert_uidstring(xorriso, uid, &(xorriso->global_uid), 0); + if(ret>0) + xorriso->do_global_uid= 1; + return(ret); +} + + +/* Options -update and -update_r + @param flag bit0= issue start and summary message + bit1= do not reset pacifier, no final pacifier message + bit2= do not issue pacifier messages at all + bit3= recursive: -update_r +*/ +int Xorriso_option_update(struct XorrisO *xorriso, char *disk_path, + char *iso_path, int flag) +{ + int ret, mem_pci, zero= 0, result, uret, follow_links; + int not_in_iso= 0, not_on_disk= 0; + double mem_lut= 0.0, start_time; + char *ipth, *argv[6], sfe[5*SfileadrL]; + char eff_origin[SfileadrL], eff_dest[SfileadrL]; + struct stat stbuf; + + start_time= Sfile_microtime(0); + + ipth= iso_path; + if(ipth[0]==0) + ipth= disk_path; + if(disk_path[0]==0) { + sprintf(xorriso->info_text, "-update: Empty disk_path given"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 1); + return(0); + } + + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, eff_origin, + 2|4|8); + if(ret<=0) + return(ret); + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, ipth, eff_dest, 2|8); + if(ret<=0) + return(ret); + + if(!(flag&2)) { + Xorriso_pacifier_reset(xorriso, 0); + mem_lut= xorriso->last_update_time; + } + mem_pci= xorriso->pacifier_interval; + xorriso->pacifier_interval= 5.0; + + if(flag&1) { + sprintf(xorriso->info_text, "Updating %s to", + Text_shellsafe(eff_origin, sfe, 0)); + sprintf(xorriso->info_text+strlen(xorriso->info_text), " %s\n", + Text_shellsafe(eff_dest, sfe, 0)); + Xorriso_info(xorriso,0); + } + if(xorriso->disk_excl_mode&8) + ret= Xorriso_path_is_excluded(xorriso, eff_origin, 1); + else + ret= 0; + if(ret!=0) + goto report_outcome; + if(flag&8) { + xorriso->find_compare_result= 1; + ret= Xorriso_iso_lstat(xorriso, eff_dest, &stbuf, 0); + if(ret >= 0) { + argv[0]= eff_dest; + argv[1]= "-exec"; + argv[2]= "update"; + argv[3]= eff_origin; + zero= 0; + ret= Xorriso_option_find(xorriso, 4, argv, &zero, 2); /* -findi */ + } else if(ret==-2) { /* severe error (e.g. lack of image) */ + ret= -1; + goto report_outcome; + } else { + not_in_iso= 1; + ret= 1; + } + if(ret>0) { + ret= lstat(eff_origin, &stbuf); + if(ret != -1) { + argv[0]= eff_origin; + argv[1]= "-exec"; + argv[2]= "add_missing"; + argv[3]= eff_dest; + zero= 0; + ret= Xorriso_option_find(xorriso, 4, argv, &zero, 1|2); /* -findx */ + if(ret>0 && !xorriso->do_follow_mount) { + argv[0]= eff_origin; + argv[1]= "-type"; + argv[2]= "m"; + argv[3]= "-exec"; + argv[4]= "empty_iso_dir"; + argv[5]= eff_dest; + zero= 0; + ret= Xorriso_option_find(xorriso, 6, argv, &zero, 1|2); /* -findx */ + } + if(ret>0) + ret= xorriso->find_compare_result; + else + ret= -1; + } else { + ret= xorriso->find_compare_result; + not_on_disk= 1; + } + } else + ret= -1; + if(not_on_disk && not_in_iso) { + sprintf(xorriso->info_text, "Missing on disk and in ISO: disk_path %s", + Text_shellsafe(disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 1); + ret= -1; + } + } else { + /* compare ctime too, no filename reporting, eventually silent */ + follow_links= (xorriso->do_follow_links || xorriso->do_follow_param) <<28; + ret= Xorriso_compare_2_files(xorriso, eff_origin, eff_dest, "", &result, + 2 | follow_links | ((flag&4)<<27) | (3<<30)); + if(ret==0) { + uret= Xorriso_update_interpreter(xorriso, NULL, result, eff_origin, + eff_dest, 0); + if(uret<=0) + ret= -1; + if(uret==3) + ret= -1; + } + } + xorriso->pacifier_interval= mem_pci; + if(mem_lut!=xorriso->last_update_time && !(flag&2)) + Xorriso_pacifier_callback(xorriso, "content bytes read", + xorriso->pacifier_count, 0, "", 1); +report_outcome:; + if(ret>0) { + sprintf(xorriso->info_text, + "No file object needed update."); + } else if(ret==0) { + sprintf(xorriso->info_text, "Differences detected and updated."); + } else { + sprintf(xorriso->info_text, + "Not ok. Comparison or update failed due to error."); + } + sprintf(xorriso->info_text+strlen(xorriso->info_text), + " (runtime %.1f s)\n", Sfile_microtime(0)-start_time); + if(flag&1) + Xorriso_info(xorriso,0); + if(ret<0) + return(ret); + return(1); +} + + +/* Option -use_readline */ +int Xorriso_option_use_readline(struct XorrisO *xorriso, char *mode, int flag) +{ + if(strcmp(mode,"off")==0) + xorriso->use_stdin= 1; + else + xorriso->use_stdin= 0; + return(1); +} + + +/* Option -version */ +int Xorriso_option_version(struct XorrisO *xorriso, int flag) +{ + sprintf(xorriso->result_line, + "xorriso %s : RockRidge filesystem manipulator and burn program\n", + Xorriso_program_versioN); + sprintf(xorriso->result_line+strlen(xorriso->result_line), +"Copyright (C) 2008, Thomas Schmitt <scdbackup@gmx.net>, libburnia project\n"); + Xorriso_result(xorriso, 0); + sprintf(xorriso->result_line, + "xorriso version : %s\n", Xorriso_program_versioN); + sprintf(xorriso->result_line+strlen(xorriso->result_line), + "Version timestamp : %s\n",Xorriso_timestamP); + sprintf(xorriso->result_line+strlen(xorriso->result_line), + "Build timestamp : %s\n",Xorriso_build_timestamP); + Xorriso_result(xorriso, 0); + Xorriso_report_lib_versions(xorriso, 0); + return(1); +} + + +/* Option -volid */ +int Xorriso_option_volid(struct XorrisO *xorriso, char *volid, int flag) +{ + int warn_shell= 0, warn_ecma= 0, i, ret; + static char shell_chars[]= { + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-+=:.,~@"}; + static char ecma_chars[]= {"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"}; + + for(i=0; volid[i]!=0; i++) { + if(strchr(shell_chars, volid[i])==NULL) + warn_shell= 1; + if(strchr(ecma_chars, volid[i])==NULL) + warn_ecma= 1; + } + if(i>32) { + sprintf(xorriso->info_text, "-volid: Text too long (%d > 32)", i); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + if(warn_shell) { + sprintf(xorriso->info_text, + "-volid text problematic as automatic mount point name"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); + } + if(xorriso->do_joliet && strlen(volid)>16) { + sprintf(xorriso->info_text, + "-volid text is too long for Joliet (%d > 16)",(int) strlen(volid)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); + } + if(warn_ecma) { + sprintf(xorriso->info_text, + "-volid text does not comply to ISO 9660 / ECMA 119 rules"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); + } + strcpy(xorriso->volid, volid); + ret= Xorriso_set_volid(xorriso, volid, 0); + if(ret<=0) + return(ret); + xorriso->volid_default= (strcmp(xorriso->volid, "ISOIMAGE")==0 || + xorriso->volid[0]==0); + return(1); +} + + +/* ---------------------------- End Options API ------------------------ */ + + +/* @return <0 error , >=0 number of skipped dashes +*/ +int Xorriso_normalize_command(struct XorrisO *xorriso, char *original_cmd, + int argno, char *cmd_data, int sizeof_cmd_data, + char **cmd, int flag) +{ + int was_dashed= 0; + char *dash_pt; + + if(strlen(original_cmd)>= sizeof_cmd_data) { + if(argno>=0) + sprintf(xorriso->info_text, "Oversized argument #%d (length %d)\n", + argno, (int) strlen(original_cmd)); + else + sprintf(xorriso->info_text, "Oversized option (length %d)\n", + (int) strlen(original_cmd)); + return(-1); + } + strcpy(cmd_data, original_cmd); + *cmd= cmd_data; + if(strcmp(*cmd, xorriso->list_delimiter)==0) + return(1); + while((*cmd)[0]=='-') { + if((*cmd)[1]==0) + break; + was_dashed++; + (*cmd)++; + } + for(dash_pt= *cmd; *dash_pt!=0; dash_pt++) + if(*dash_pt=='-') + *dash_pt= '_'; + return(was_dashed); +} + + +/* @param flag bit0= do not warn of unknown option + @return <=0 error, + 1=count is valid, 2=dashed unknown, 3=undashed unknown +*/ +int Xorriso_count_args(struct XorrisO *xorriso, int argc, char **argv, + int *count, int flag) +{ + int ret, was_dashed= 0, i; + char *cmd, cmd_data[2*SfileadrL]; + static char arg0_commands[][40]= { + "ban_stdio_write","commit","devices","end","help", + "list_formats","no_rc","print_size","pwd","pwdi","pwdx", + "rollback","rollback_end","tell_media_space","toc","version", + "" + }; + static char arg1_commands[][40]= { + "abort_on","add_plainly","application_id","backslash_codes","blank", + "cd","cdi","cdx","charset","close","commit_eject","compliance", + "dev", "dummy","dialog","disk_pattern","eject","iso_rr_pattern","follow", + "format","fs","gid","grow_blindly", + "history","indev","in_charset","joliet","list_delimiter","local_charset", + "mark","not_leaf","not_list","not_mgt", + "options_from_file","osirrox","outdev","out_charset","overwrite", + "pacifier","padding","path_list","pathspecs","pkt_output","print","prompt", + "prog","prog_help","publisher","quoted_not_list","quoted_path_list", + "reassure","report_about","rom_toc_scan", + "session_log","speed","split_size","status","status_history_max", + "stream_recording","temp_mem_limit","uid","volid","use_readline", + "" + }; + static char arg2_commands[][40]= { + "assert_volid","boot_image","compare","compare_r","drive_class", + "errfile_log","error_behavior","extract","extract_single", + "load","logfile", + "map","map_single","page","return_with","update","update_r", + "" + }; + static char arg4_commands[][40]= { + "cut_out","extract_cut","mount","mount_cmd","paste_in","session_string", + "" + }; + static char argn_commands[][40]= { + "add","alter_date","alter_date_r","as", + "check_media","check_media_defaults", + "chgrp","chgrpi","chgrp_r","chgrp_ri","chmod","chmodi", + "chmod_r","chmod_ri","chown","chowni","chown_r","chown_ri", + "compare_l","cpr","cpri","cp_rax","cp_rx","cpax","cpx", + "du","dui","dus","dusi","dux","dusx","extract_l", + "file_size_limit","find","findi","findx", + "ls","lsi","lsl","lsli","lsd","lsdi","lsdl","lsdli", + "lsx","lslx","lsdx","lsdlx","map_l","mv","mvi","mkdir","mkdiri", + "not_paths","rm","rmi","rm_r","rm_ri","rmdir","rmdiri","update_l", + "" + }; + + *count= 0; + if(argc<=0) + return(-1); + ret= Xorriso_normalize_command(xorriso, argv[0], -1, + cmd_data, sizeof(cmd_data), &cmd, 0); + if(ret<0) + return(ret); + was_dashed= (ret>0); + if(cmd[0]=='#' || cmd[0]==0 || strcmp(cmd, xorriso->list_delimiter) == 0) { + /* ignore: comment line , empty option , orphaned list delimiter */ + return(1); + } + for(i=0; arg0_commands[i][0]!=0; i++) + if(strcmp(arg0_commands[i], cmd)==0) + return(1); + *count= 1; + for(i=0; arg1_commands[i][0]!=0; i++) + if(strcmp(arg1_commands[i], cmd)==0) + return(1); + *count= 2; + for(i=0; arg2_commands[i][0]!=0; i++) + if(strcmp(arg2_commands[i], cmd)==0) + return(1); + *count= 4; + for(i=0; arg4_commands[i][0]!=0; i++) + if(strcmp(arg4_commands[i], cmd)==0) + return(1); + *count= 0; + for(i=0; argn_commands[i][0]!=0; i++) + if(strcmp(argn_commands[i], cmd)==0) { + ret= Xorriso_end_idx(xorriso, argc, argv, 1, 1); + if(ret<1) + return(ret); + *count= ret-1; + return(1); + } + + if(!(flag&1)) { + sprintf(xorriso->info_text, "Unknown option : '%s'", argv[0]); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); + } + + return(2+!was_dashed); +} + + +/* @param flag bit0= recursion + bit1= these are command line arguments + (for xorriso->argument_emulation) +*/ +int Xorriso_interpreter(struct XorrisO *xorriso, + int argc, char **argv, int *idx, int flag) +/* +return: + <=0 error , 1 = success , 2 = problem event ignored , 3 = end program run +*/ +{ + int ret, was_dashed, end_ret, num1, num2; + char *cmd, *original_cmd, cmd_data[2*SfileadrL], *arg1, *arg2; + + if(xorriso==NULL) + return(0); + if(xorriso->is_dialog) { + xorriso->result_line_counter= xorriso->result_page_counter= 0; + if(xorriso->result_page_length<0) + xorriso->result_page_length= -xorriso->result_page_length; + } + +next_command:; + if(flag&2) { + ret= 1; + if(xorriso->argument_emulation==1) + ret= Xorriso_as_genisofs(xorriso, argc, argv, idx, 0); + else if(xorriso->argument_emulation==2) + ret= Xorriso_as_cdrskin(xorriso, argc, argv, idx, 0); + if(xorriso->argument_emulation>0) { + xorriso->argument_emulation= 0; + if(ret<=0) + goto eval_any_problems; + if((*idx)>=argc) + {ret= 1; goto ex;} + } + } + + xorriso->prepended_wd= 0; + xorriso->request_to_abort= xorriso->request_not_to_ask= 0; + Xorriso_set_problem_status(xorriso, "", 0); + if((*idx)<argc) + original_cmd= cmd= argv[*idx]; + else + original_cmd= cmd= ""; + if(xorriso->add_plainly==3 && cmd[0] && !xorriso->is_dialog) { + (*idx)++; + goto add_plain_argument; + } + was_dashed= 0; + + ret= Xorriso_normalize_command(xorriso, original_cmd, -1, + cmd_data, sizeof(cmd_data), &cmd, 0); + if(ret<0) + goto eval_any_problems; + was_dashed= ret; + + (*idx)++; + if((*idx)<argc) + arg1= argv[(*idx)]; + else + arg1= ""; + if((*idx)+1<argc) + arg2= argv[(*idx)+1]; + else + arg2= ""; + + ret= 1; + if(cmd[0]=='#' || cmd[0]==0) { + /* ignore comment line and empty option */; + + } else if(strcmp(cmd,"abort_on")==0) { + (*idx)++; + ret= Xorriso_option_abort_on(xorriso, arg1, 0); + + } else if(strcmp(cmd,"add")==0) { + ret= Xorriso_option_add(xorriso, argc, argv, idx, 0); + + } else if(strcmp(cmd,"add_plainly")==0) { + (*idx)++; + ret= Xorriso_option_add_plainly(xorriso, arg1, 0); + + } else if(strcmp(cmd,"alter_date")==0 || strcmp(cmd,"alter_date_r")==0) { + (*idx)+= 2; + ret= Xorriso_option_alter_date(xorriso, arg1, arg2, argc, argv, idx, + strlen(cmd)>10); + + } else if(strcmp(cmd,"application_id")==0) { + (*idx)++; + ret= Xorriso_option_application_id(xorriso, arg1, 0); + + } else if(strcmp(cmd,"as")==0) { + ret= Xorriso_option_as(xorriso, argc, argv, idx, 0); + + } else if(strcmp(cmd,"assert_volid")==0) { + (*idx)+= 2; + ret= Xorriso_option_assert_volid(xorriso, arg1, arg2, 0); + + } else if(strcmp(cmd,"backslash_codes")==0) { + (*idx)++; + ret= Xorriso_option_backslash_codes(xorriso, arg1, 0); + + } else if(strcmp(cmd,"ban_stdio_write")==0) { + ret= Xorriso_option_ban_stdio_write(xorriso, 0); + + } else if(strcmp(cmd,"blank")==0) { + (*idx)++; + ret= Xorriso_option_blank(xorriso, arg1, 0); + + } else if(strcmp(cmd,"boot_image")==0) { + (*idx)+= 2; + ret= Xorriso_option_boot_image(xorriso, arg1, arg2, 0); + + } else if(strcmp(cmd,"cd")==0 || strcmp(cmd,"cdi")==0) { + (*idx)++; + ret= Xorriso_option_cdi(xorriso, arg1, 0); + + } else if(strcmp(cmd,"cdx")==0) { + (*idx)++; + ret= Xorriso_option_cdx(xorriso, arg1, 0); + + } else if(strcmp(cmd,"charset")==0) { + (*idx)++; + ret= Xorriso_option_charset(xorriso, arg1, 3); + + } else if(strcmp(cmd,"check_media")==0) { + ret= Xorriso_option_check_media(xorriso, argc, argv, idx, 0); + + } else if(strcmp(cmd,"check_media_defaults")==0) { + ret= Xorriso_option_check_media_defaults(xorriso, argc, argv, idx, 0); + + } else if(strcmp(cmd,"chgrp")==0 || strcmp(cmd,"chgrpi")==0) { + (*idx)+= 1; + ret= Xorriso_option_chgrpi(xorriso, arg1, argc, argv, idx, 0); + + } else if(strcmp(cmd,"chgrp_r")==0 || strcmp(cmd,"chgrp_ri")==0) { + (*idx)+= 1; + ret= Xorriso_option_chgrpi(xorriso, arg1, argc, argv, idx, 1); + + } else if(strcmp(cmd,"chmod")==0 || strcmp(cmd,"chmodi")==0) { + (*idx)+= 1; + ret= Xorriso_option_chmodi(xorriso, arg1, argc, argv, idx, 0); + + } else if(strcmp(cmd,"chmod_r")==0 || strcmp(cmd,"chmod_ri")==0) { + (*idx)+= 1; + ret= Xorriso_option_chmodi(xorriso, arg1, argc, argv, idx, 1); + + } else if(strcmp(cmd,"chown_r")==0 || strcmp(cmd,"chown_ri")==0) { + (*idx)+= 1; + ret= Xorriso_option_chowni(xorriso, arg1, argc, argv, idx, 1); + + } else if(strcmp(cmd,"chown")==0 || strcmp(cmd,"chowni")==0) { + (*idx)+= 1; + ret= Xorriso_option_chowni(xorriso, arg1, argc, argv, idx, 0); + + } else if(strcmp(cmd,"close")==0) { + (*idx)++; + ret= Xorriso_option_close(xorriso, arg1, 0); + + } else if(strcmp(cmd,"commit")==0) { + ret= Xorriso_option_commit(xorriso, 0); + + } else if(strcmp(cmd,"commit_eject")==0) { + (*idx)++; + ret= Xorriso_option_commit_eject(xorriso, arg1, 0); + + } else if(strcmp(cmd,"compare")==0) { + (*idx)+= 2; + ret= Xorriso_option_compare(xorriso, arg1, arg2, 1); + + } else if(strcmp(cmd,"compare_l")==0) { + ret= Xorriso_option_map_l(xorriso, argc, argv, idx, 1<<8); + + } else if(strcmp(cmd,"compare_r")==0) { + (*idx)+= 2; + ret= Xorriso_option_compare(xorriso, arg1, arg2, 1|8); + + } else if(strcmp(cmd,"cpr")==0 || strcmp(cmd,"cpri")==0) { + ret= Xorriso_option_cpri(xorriso, argc, argv, idx, 0); + + } else if(strcmp(cmd,"cp_rx")==0 || strcmp(cmd,"cp_rax")==0) { + ret= Xorriso_option_cpx(xorriso, argc, argv, idx, + 1|((strcmp(cmd,"cp_rax")==0)<<1)); + + } else if(strcmp(cmd,"cpx")==0 || strcmp(cmd,"cpax")==0) { + ret= Xorriso_option_cpx(xorriso, argc, argv, idx, + (strcmp(cmd,"cpax")==0)<<1); + + } else if(strcmp(cmd,"cut_out")==0) { + (*idx)+= 4; + if((*idx)>argc) { + sprintf(xorriso->info_text, + "-cut_out: Not enough arguments. Needed are: disk_path start count so_rr_path"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; + } else + ret= Xorriso_option_cut_out(xorriso, arg1, arg2, + argv[(*idx)-2], argv[(*idx)-1], 0); + + } else if(strcmp(cmd,"dev")==0) { + (*idx)++; + ret= Xorriso_option_dev(xorriso, arg1, 3); + + } else if(strcmp(cmd,"devices")==0) { + ret= Xorriso_option_devices(xorriso, 0); + + } else if(strcmp(cmd,"drive_class")==0) { + (*idx)+= 2; + ret= Xorriso_option_drive_class(xorriso, arg1, arg2, 0); + + } else if(strcmp(cmd,"dummy")==0) { + (*idx)++; + ret= Xorriso_option_dummy(xorriso, arg1, 0); + + } else if(strcmp(cmd,"dialog")==0) { + (*idx)++; + ret= Xorriso_option_dialog(xorriso, arg1, 0); + + } else if(strcmp(cmd,"disk_pattern")==0) { + (*idx)++; + ret= Xorriso_option_disk_pattern(xorriso, arg1, 0); + + } else if(strcmp(cmd,"du")==0 || strcmp(cmd,"dui")==0 || + strcmp(cmd,"dus")==0 || strcmp(cmd,"dusi")==0) { + ret= Xorriso_option_lsi(xorriso, argc, argv, idx, (cmd[2]!='s')|4); + + } else if(strcmp(cmd,"dux")==0 || strcmp(cmd,"dusx")==0) { + ret= Xorriso_option_lsx(xorriso, argc, argv, idx, (cmd[2]!='s')|4); + + } else if(strcmp(cmd,"eject")==0) { + (*idx)++; + ret= Xorriso_option_eject(xorriso, arg1, 0); + + } else if(strcmp(cmd,"end")==0) { + end_ret= Xorriso_option_end(xorriso, 0); + ret= Xorriso_eval_problem_status(xorriso, ret, 0); + if(ret<0) + return(ret); + if(end_ret!=2) + {ret= 3; goto ex;} + + } else if(strcmp(cmd,"errfile_log")==0) { + (*idx)+= 2; + ret= Xorriso_option_errfile_log(xorriso, arg1, arg2, 0); + + } else if(strcmp(cmd,"error_behavior")==0) { + (*idx)+= 2; + ret= Xorriso_option_error_behavior(xorriso, arg1, arg2, 0); + + } else if(strcmp(cmd,"extract")==0) { + (*idx)+= 2; + ret= Xorriso_option_extract(xorriso, arg1, arg2, 0); + + } else if(strcmp(cmd,"extract_cut")==0) { + (*idx)+= 4; + if((*idx)>argc) { + sprintf(xorriso->info_text, + "-extract_cut: Not enough arguments. Needed are: disk_path start count so_rr_path"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; + } else + ret= Xorriso_option_extract_cut(xorriso, arg1, arg2, + argv[(*idx)-2], argv[(*idx)-1], 0); + + } else if(strcmp(cmd,"extract_l")==0) { + ret= Xorriso_option_map_l(xorriso, argc, argv, idx, 3<<8); + + } else if(strcmp(cmd,"extract_single")==0) { + (*idx)+= 2; + ret= Xorriso_option_extract(xorriso, arg1, arg2, 32); + + } else if(strcmp(cmd,"file_size_limit")==0) { + ret= Xorriso_option_file_size_limit(xorriso, argc, argv, idx, 0); + + } else if(strcmp(cmd,"find")==0 || strcmp(cmd,"findi")==0) { + ret= Xorriso_option_find(xorriso, argc, argv, idx, 0); + + } else if(strcmp(cmd,"findx")==0) { + ret= Xorriso_option_find(xorriso, argc, argv, idx, 1); + + } else if(strcmp(cmd,"follow")==0) { + (*idx)++; + ret= Xorriso_option_follow(xorriso, arg1, 0); + + } else if(strcmp(cmd,"format")==0) { + (*idx)++; + ret= Xorriso_option_blank(xorriso, arg1, 1); + + } else if(strcmp(cmd,"fs")==0) { + (*idx)++; + ret= Xorriso_option_fs(xorriso, arg1, 0); + + } else if(strcmp(cmd,"gid")==0) { + (*idx)++; + ret= Xorriso_option_gid(xorriso,arg1,0); + + } else if(strcmp(cmd,"grow_blindly")==0) { + (*idx)++; + ret= Xorriso_option_grow_blindly(xorriso,arg1,0); + + } else if(strcmp(cmd,"help")==0) { + Xorriso_option_help(xorriso,0); + + } else if(strcmp(cmd,"history")==0) { + /* add to readline history */ + (*idx)++; + ret= Xorriso_option_history(xorriso, arg1, 0); + + } else if(strcmp(cmd,"indev")==0) { + (*idx)++; + ret= Xorriso_option_dev(xorriso, arg1, 1); + + } else if(strcmp(cmd,"in_charset")==0) { + (*idx)++; + ret= Xorriso_option_charset(xorriso, arg1, 1); + + } else if(strcmp(cmd,"iso_rr_pattern")==0) { + (*idx)++; + ret= Xorriso_option_iso_rr_pattern(xorriso, arg1, 0); + + } else if(strcmp(cmd,"joliet")==0) { + (*idx)++; + ret= Xorriso_option_joliet(xorriso, arg1, 0); + + } else if(strcmp(cmd, "list_delimiter") == 0) { + (*idx)++; + ret= Xorriso_option_list_delimiter(xorriso, arg1, 0); + + } else if(strcmp(cmd,"list_formats")==0) { + ret= Xorriso_option_list_formats(xorriso, 0); + + } else if(strcmp(cmd,"load")==0) { + (*idx)+= 2; + ret= Xorriso_option_load(xorriso, arg1, arg2, 0); + + } else if(strcmp(cmd,"local_charset")==0) { + (*idx)++; + ret= Xorriso_option_charset(xorriso, arg1, 4); + + } else if(strcmp(cmd,"logfile")==0) { + (*idx)+= 2; + ret= Xorriso_option_logfile(xorriso, arg1, arg2, 0); + + } else if(strcmp(cmd,"ls")==0 || strcmp(cmd,"lsi")==0 || + strcmp(cmd,"lsl")==0 || strcmp(cmd,"lsli")==0) { + ret= Xorriso_option_lsi(xorriso, argc, argv, idx, (cmd[2]=='l')); + + } else if(strcmp(cmd,"lsd")==0 || strcmp(cmd,"lsdi")==0 || + strcmp(cmd,"lsdl")==0 || strcmp(cmd,"lsdli")==0) { + ret= Xorriso_option_lsi(xorriso, argc, argv, idx, (cmd[3]=='l')|8); + + } else if(strcmp(cmd,"lsdx")==0 || strcmp(cmd,"lsdlx")==0) { + ret= Xorriso_option_lsx(xorriso, argc, argv, idx, (cmd[3]=='l')|8); + + } else if(strcmp(cmd,"lsx")==0 || strcmp(cmd,"lslx")==0) { + ret= Xorriso_option_lsx(xorriso, argc, argv, idx, (cmd[2]=='l')); + + } else if(strcmp(cmd,"map")==0) { + (*idx)+= 2; + ret= Xorriso_option_map(xorriso, arg1, arg2, 0); + + } else if(strcmp(cmd,"map_l")==0) { + ret= Xorriso_option_map_l(xorriso, argc, argv, idx, 0); + + } else if(strcmp(cmd,"map_single")==0) { + (*idx)+= 2; + ret= Xorriso_option_map(xorriso, arg1, arg2, 32); + + } else if(strcmp(cmd,"mark")==0) { + (*idx)++; + ret= Xorriso_option_mark(xorriso, arg1, 0); + + } else if(strcmp(cmd, "mount") == 0 || strcmp(cmd, "mount_cmd") == 0) { + (*idx)+= 4; + if((*idx)>argc) { + sprintf(xorriso->info_text, + "-%s: Not enough arguments. Needed are: device entity id command", + cmd); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; + } else + ret= Xorriso_option_mount(xorriso, arg1, arg2, + argv[(*idx)-2], argv[(*idx)-1], + (strcmp(cmd, "mount_cmd") == 0)); + + } else if(strcmp(cmd,"mv")==0 || strcmp(cmd,"mvi")==0) { + ret= Xorriso_option_mvi(xorriso, argc, argv, idx, 0); + + } else if(strcmp(cmd,"mkdir")==0 || strcmp(cmd,"mkdiri")==0) { + ret= Xorriso_option_mkdiri(xorriso, argc, argv, idx, 0); + + } else if(strcmp(cmd,"no_rc")==0) { + ret= Xorriso_option_no_rc(xorriso, 0); + + } else if(strcmp(cmd,"not_leaf")==0) { + (*idx)++; + ret= Xorriso_option_not_leaf(xorriso, arg1, 0); + + } else if(strcmp(cmd,"not_list")==0) { + (*idx)++; + ret= Xorriso_option_not_list(xorriso, arg1, 0); + + } else if(strcmp(cmd,"not_mgt")==0) { + (*idx)++; + ret= Xorriso_option_not_mgt(xorriso, arg1, 0); + + } else if(strcmp(cmd,"not_paths")==0) { + ret= Xorriso_option_not_paths(xorriso, argc, argv, idx, 0); + + } else if(strcmp(cmd,"options_from_file")==0) { + (*idx)++; + ret= Xorriso_option_options_from_file(xorriso,arg1,0); + if(ret==3) + goto ex; + + } else if(strcmp(cmd,"osirrox")==0) { + (*idx)++; + ret= Xorriso_option_osirrox(xorriso,arg1,0); + + } else if(strcmp(cmd,"outdev")==0) { + (*idx)++; + ret= Xorriso_option_dev(xorriso, arg1, 2); + + } else if(strcmp(cmd,"out_charset")==0) { + (*idx)++; + ret= Xorriso_option_charset(xorriso, arg1, 2); + + } else if(strcmp(cmd,"overwrite")==0) { + (*idx)++; + ret= Xorriso_option_overwrite(xorriso,arg1,0); + + } else if(strcmp(cmd,"pacifier")==0) { + (*idx)++; + ret= Xorriso_option_pacifier(xorriso, arg1, 0); + + } else if(strcmp(cmd,"padding")==0) { + (*idx)++; + ret= Xorriso_option_padding(xorriso, arg1, 0); + + } else if(strcmp(cmd,"page")==0) { + (*idx)+= 2; + num1= num2= 0; + sscanf(arg1,"%d",&num1); + sscanf(arg2,"%d",&num2); + if(num1<0) + num1= 0; + if(arg1[0]==0) + num1= 16; + if(num2<=0) + num2= 80; + ret= Xorriso_option_page(xorriso, num1, num2, 0); + + } else if(strcmp(cmd,"paste_in")==0) { + (*idx)+= 4; + if((*idx)>argc) { + sprintf(xorriso->info_text, + "-paste_in: Not enough arguments. Needed are: disk_path start count so_rr_path"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; + } else + ret= Xorriso_option_paste_in(xorriso, arg1, arg2, + argv[(*idx)-2], argv[(*idx)-1], 0); + + } else if(strcmp(cmd,"path-list")==0 || strcmp(cmd,"path_list")==0) { + (*idx)++; + ret= Xorriso_option_path_list(xorriso, arg1, 0); + + } else if(strcmp(cmd,"pathspecs")==0) { + (*idx)++; + ret= Xorriso_option_pathspecs(xorriso, arg1, 0); + + } else if(strcmp(cmd,"pkt_output")==0) { + (*idx)++; + ret= Xorriso_option_pkt_output(xorriso, arg1, 0); + + } else if(strcmp(cmd,"print")==0) { + (*idx)++; + ret= Xorriso_option_print(xorriso, arg1, 0); + + } else if(strcmp(cmd,"print_size")==0) { + Xorriso_option_print_size(xorriso, 0); + + } else if(strcmp(cmd,"prompt")==0) { + (*idx)++; + ret= Xorriso_option_prompt(xorriso, arg1, 0); + + } else if(strcmp(cmd,"prog")==0) { + (*idx)++; + ret= Xorriso_option_prog(xorriso, arg1, 0); + + } else if(strcmp(cmd,"publisher")==0) { + (*idx)++; + Xorriso_option_publisher(xorriso, arg1, 0); + + } else if(strcmp(cmd,"pwd")==0 || strcmp(cmd,"pwdi")==0) { + Xorriso_option_pwdi(xorriso, 0); + + } else if(strcmp(cmd,"pwdx")==0) { + Xorriso_option_pwdx(xorriso, 0); + + } else if(strcmp(cmd,"quoted_not_list")==0) { + (*idx)++; + ret= Xorriso_option_not_list(xorriso, arg1, 1); + + } else if(strcmp(cmd,"quoted_path_list")==0) { + (*idx)++; + ret= Xorriso_option_path_list(xorriso, arg1, 1); + + } else if(strcmp(cmd,"reassure")==0) { + (*idx)++; + ret= Xorriso_option_reassure(xorriso, arg1, 0); + + } else if(strcmp(cmd,"compliance")==0) { + (*idx)++; + Xorriso_option_compliance(xorriso, arg1, 0); + + } else if(strcmp(cmd,"report_about")==0) { + (*idx)++; + ret= Xorriso_option_report_about(xorriso, arg1, 0); + + } else if(strcmp(cmd,"return_with")==0) { + (*idx)+= 2; + num2= 0; + sscanf(arg2,"%d",&num2); + ret= Xorriso_option_return_with(xorriso, arg1, num2, 0); + + } else if(strcmp(cmd,"rm")==0 || strcmp(cmd,"rmi")==0) { + ret= Xorriso_option_rmi(xorriso, argc, argv, idx, 0); + + } else if(strcmp(cmd,"rm_r")==0 || strcmp(cmd,"rm_ri")==0) { + ret= Xorriso_option_rmi(xorriso, argc, argv, idx, 1); + + } else if(strcmp(cmd,"rmdir")==0 || strcmp(cmd,"rmdiri")==0) { + ret= Xorriso_option_rmi(xorriso, argc, argv, idx, 2); + + } else if(strcmp(cmd,"rollback")==0) { + ret= Xorriso_option_rollback(xorriso, 0); + + } else if(strcmp(cmd,"rollback_end")==0) { + end_ret= Xorriso_option_end(xorriso, 1); + ret= Xorriso_eval_problem_status(xorriso, ret, 0); + if(ret<0) + return(ret); + if(end_ret!=2) + {ret= 3; goto ex;} + + } else if(strcmp(cmd,"rom_toc_scan")==0) { + (*idx)++; + Xorriso_option_rom_toc_scan(xorriso, arg1, 0); + + } else if(strcmp(cmd,"session_log")==0) { + (*idx)++; + ret= Xorriso_option_session_log(xorriso, arg1, 0); + + } else if(strcmp(cmd, "session_string") == 0) { + (*idx)+= 4; + if((*idx)>argc) { + sprintf(xorriso->info_text, + "-%s: Not enough arguments. Needed are: device entity id command", + cmd); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; + } else + ret= Xorriso_option_mount(xorriso, arg1, arg2, + argv[(*idx)-2], argv[(*idx)-1], 2); + + } else if(strcmp(cmd,"speed")==0) { + (*idx)++; + ret= Xorriso_option_speed(xorriso, arg1, 0); + + } else if(strcmp(cmd,"split_size")==0) { + (*idx)++; + ret= Xorriso_option_split_size(xorriso, arg1, 0); + + } else if(strcmp(cmd,"status")==0) { + (*idx)++; + ret= Xorriso_option_status(xorriso, arg1, 0); + + } else if(strcmp(cmd,"status_history_max")==0) { + (*idx)++; + sscanf(arg1,"%d",&num1); + ret= Xorriso_option_status_history_max(xorriso, num1, 0); + + } else if(strcmp(cmd,"stream_recording")==0) { + (*idx)++; + ret= Xorriso_option_stream_recording(xorriso, arg1, 0); + + } else if(strcmp(cmd,"tell_media_space")==0) { + Xorriso_option_tell_media_space(xorriso, 0); + + } else if(strcmp(cmd,"temp_mem_limit")==0) { + (*idx)++; + ret= Xorriso_option_temp_mem_limit(xorriso, arg1, 0); + + } else if(strcmp(cmd,"test")==0) { /* This option does not exist. */ + time_t t; + + (*idx)++; + Decode_timestring(arg1, &t, 0); + sprintf(xorriso->result_line, "%.f\n", (double) t); + Xorriso_result(xorriso, 0); + + } else if(strcmp(cmd,"toc")==0) { + Xorriso_option_toc(xorriso, 0); + + } else if(strcmp(cmd,"uid")==0) { + (*idx)++; + ret= Xorriso_option_uid(xorriso,arg1,0); + + } else if(strcmp(cmd,"update")==0) { + (*idx)+= 2; + ret= Xorriso_option_update(xorriso, arg1, arg2, 1); + + } else if(strcmp(cmd,"update_l")==0) { + ret= Xorriso_option_map_l(xorriso, argc, argv, idx, 2<<8); + + } else if(strcmp(cmd,"update_r")==0) { + (*idx)+= 2; + ret= Xorriso_option_update(xorriso, arg1, arg2, 1|8); + + } else if(strcmp(cmd,"use_readline")==0) { + (*idx)++; + ret= Xorriso_option_use_readline(xorriso, arg1, 0); + + } else if(strcmp(cmd,"version")==0){ + ret= Xorriso_option_version(xorriso, 0); + + } else if(strcmp(cmd,"volid")==0) { + (*idx)++; + ret= Xorriso_option_volid(xorriso,arg1,0); + + } else if(strcmp(cmd, xorriso->list_delimiter)==0){ + /* tis ok */; + + } else if(was_dashed) { + if(xorriso->add_plainly>1) + goto add_plain_argument; +unknown_option:; + sprintf(xorriso->info_text, "Not a known option: '%s'\n", + original_cmd); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto eval_any_problems;} + + } else { + if(xorriso->add_plainly<=0) + goto unknown_option; +add_plain_argument:; + (*idx)--; + ret= Xorriso_option_add(xorriso, (*idx)+1, argv, idx, 0); + (*idx)++; + + } + +eval_any_problems: + ret= Xorriso_eval_problem_status(xorriso, ret, 0); + if(ret<0) + return(ret); + + if(*idx<argc) + goto next_command; + +ex:; + if((!xorriso->is_dialog) && !(flag&1)) + Xorriso_mark(xorriso,0); + fflush(stdout); + return(ret); +} + + +int Xorriso_execute_option(struct XorrisO *xorriso, char *line, int flag) +/* + bit0-bit15 are forwarded to Xorriso_interpreter + + bit16= no pageing of info lines + bit17= print === bar even if xorriso->found<0 +*/ +{ + int ret,argc= 0, idx= 1; + char **argv= NULL; + double tdiff; + struct timeval tv; + struct timezone tz; + + gettimeofday(&tv,&tz); + Xorriso_reset_counters(xorriso,0); + xorriso->idle_time= 0.0; + tdiff= tv.tv_sec+(1.e-6*(double) tv.tv_usec); + + /* parse line into args */ + ret= Sfile_make_argv(xorriso->progname, line, &argc, &argv, + 4 | ((xorriso->bsl_interpretation & 3) << 5)); + if(ret < 0) { + Xorriso_msgs_submit(xorriso, 0, + "Severe lack of resources during command line parsing", 0, "FATAL", 0); + goto ex; + } + if(ret == 0) { + sprintf(xorriso->info_text, "Incomplete quotation in command line: %s", + line); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + goto ex; + } + if(argc<2) + {ret= 1; goto ex;} + if(argv[1][0]=='#') + {ret= 1; goto ex;} + + ret= Xorriso_interpreter(xorriso, argc, argv, &idx, flag&0xffff); + if(ret<0) + goto ex; + gettimeofday(&tv,&tz); + tdiff= tv.tv_sec+(1.e-6*(double) tv.tv_usec)-tdiff-xorriso->idle_time; + if(tdiff<0.001) + tdiff= 0.001; + if(xorriso->error_count>0) { + sprintf(xorriso->info_text, + "----------------------------- %7.f errors encountered\n", + xorriso->error_count); + Xorriso_info(xorriso,!(flag&(1<<16))); + } + + /* ??? >>> print elapsed time tdiff ? */; + + if((flag&(1<<17)) && !xorriso->bar_is_fresh) { + sprintf(xorriso->info_text,"============================\n"); + Xorriso_info(xorriso,0); + xorriso->bar_is_fresh= 1; + } + Xorriso_reset_counters(xorriso,0); +ex:; + Sfile_make_argv("", "", &argc, &argv, 2); /* release memory */ + return(ret); +} + + +int Xorriso_dialog(struct XorrisO *xorriso, int flag) +{ + int ret,first_round; + char line[2*SfileadrL]; + + xorriso->is_dialog= 1; + for(first_round= 1;1;first_round= 0) { + if(xorriso->pending_option[0]!=0) { + Xorriso_mark(xorriso,0); + strcpy(line,xorriso->pending_option); + xorriso->pending_option[0]= 0; + } else { + if(!xorriso->bar_is_fresh) { + sprintf(xorriso->info_text,"============================\n"); + Xorriso_info(xorriso,0); + xorriso->bar_is_fresh= 1; + } + sprintf(xorriso->info_text,"enter option and arguments :\n"); + Xorriso_info(xorriso,0); + Xorriso_mark(xorriso,0); + ret= Xorriso_dialog_input(xorriso,line,sizeof(line),4); + if(ret<=0) + break; + } + sprintf(xorriso->info_text, + "==============================================================\n"); + Xorriso_info(xorriso,0); + + ret= Xorriso_execute_option(xorriso,line,1<<17); + if(ret<0) + goto ex; + if(ret==3) + break; + xorriso->did_something_useful= 1; + xorriso->no_volset_present= 0; /* Re-enable "No ISO image present." */ + } + ret= 1; +ex:; + xorriso->is_dialog= 0; + return(ret); +} + + +int Xorriso_protect_stdout(struct XorrisO *xorriso, int flag) +{ + if(xorriso->dev_fd_1>=0) + return(2); + xorriso->dev_fd_1= dup(1); + close(1); + dup2(2,1); + return(1); +} + + +int Xorriso_prescan_args(struct XorrisO *xorriso, int argc, char **argv, + int flag) +/* + bit0= do not interpret argv[1] +*/ +/* + return: + <0 error + 0 end program + 1 ok, go on +*/ +{ + int i, ret, was_dashed, num2, arg_count; + int was_report_about= 0, was_abort_on= 0, was_return_with= 0; + char *cmd, *original_cmd, cmd_data[5*SfileadrL], *arg1, *arg2; + char mem_list_delimiter[81]; + + strcpy(mem_list_delimiter, xorriso->list_delimiter); + for(i=1+(flag&1);i<argc;i++) { + original_cmd= cmd= argv[i]; + was_dashed= 0; + + was_dashed= Xorriso_normalize_command(xorriso, original_cmd, i, + cmd_data, sizeof(cmd_data), &cmd, 0); + if(was_dashed<0) + {ret= -1; goto ex;} + + arg1= ""; + if(i+1<argc) + arg1= argv[i+1]; + arg2= ""; + if(i+2<argc) + arg2= argv[2+1]; + if(i>1) + xorriso->did_something_useful= 1; + if(i==1 && argc==2) { + if(strcmp(cmd,"prog_help")==0) { + i++; + Xorriso_option_prog_help(xorriso,arg1,0); + xorriso->did_something_useful= 1; + {ret= 0; goto ex;} + } else if(strcmp(cmd,"help")==0) { + Xorriso_option_help(xorriso,0); + xorriso->did_something_useful= 1; + {ret= 0; goto ex;} + } + } else if(i==1 && strcmp(cmd,"no_rc")==0) { + ret= Xorriso_option_no_rc(xorriso, 0); + if(ret<=0) + goto ex; + + } else if((strcmp(cmd,"dev")==0 || strcmp(cmd,"outdev")==0 || + strcmp(cmd,"indev")==0) && + (strcmp(arg1,"stdio:/dev/fd/1")==0 || strcmp(arg1,"-")==0) && + xorriso->dev_fd_1<0) { + /* Detach fd 1 from externally perceived stdout and attach it to stderr. + Keep dev_fd_1 connected to external stdout. dev_fd_1 is to be used when + "stdio:/dev/fd/1" is interpreted as drive address. + */ +protect_stdout:; + Xorriso_protect_stdout(xorriso, 0); + sprintf(xorriso->info_text, + "Encountered - or stdio:/dev/fd/1 as possible write target."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + sprintf(xorriso->info_text, + "Redirecting nearly all text message output to stderr."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + sprintf(xorriso->info_text, "Disabling use of libreadline."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + + } else if(strcmp(cmd,"abort_on")==0 && was_dashed) { + i++; + if(!was_abort_on) + Xorriso_option_abort_on(xorriso, arg1, 0); + was_abort_on= 1; + + } else if(strcmp(cmd,"report_about")==0 && was_dashed) { + i++; + if(!was_report_about) + Xorriso_option_report_about(xorriso, arg1, 0); + was_report_about= 1; + + } else if(strcmp(cmd,"return_with")==0 && was_dashed) { + i+= 2; + num2= 0; + sscanf(arg2,"%d",&num2); + if(!was_return_with) + Xorriso_option_return_with(xorriso, arg1, num2, 0); + was_return_with= 1; + + } else if(strcmp(cmd,"as")==0 && was_dashed) { + if(strcmp(arg1, "mkisofs")==0 || strcmp(arg1, "genisoimage")==0 || + strcmp(arg1, "genisofs")==0 || strcmp(arg1, "xorrisofs")==0) + goto protect_stdout; + + } else if(strcmp(cmd, "list_delimiter") == 0) { + /* Needed for interpreting other args. Gets reset after prescan. */ + i++; + ret= Xorriso_option_list_delimiter(xorriso, arg1, 0); + if(ret <= 0) + goto ex; + + } else { + ret= Xorriso_count_args(xorriso, argc-i, argv+i, &arg_count, 1); + if(ret==1) + i+= arg_count; + } + } + ret= 1; +ex:; + strcpy(xorriso->list_delimiter, mem_list_delimiter); + return(ret); +} + + +/** Load content startup files into preskin cache */ +int Xorriso_read_rc(struct XorrisO *xorriso, int flag) +{ + int ret,i,was_failure= 0,fret; + + i= xorriso->rc_filename_count-1; + Sfile_home_adr_s(".xorrisorc", xorriso->rc_filenames[i], + sizeof(xorriso->rc_filenames[i]),0); + for(i=0;i<xorriso->rc_filename_count;i++) { + ret= Sfile_type(xorriso->rc_filenames[i],1|8); + if(ret!=1) + continue; + ret= Xorriso_option_options_from_file(xorriso,xorriso->rc_filenames[i],0); + if(ret>1) + return(ret); + if(ret==1) + continue; /* regular bottom of loop */ + was_failure= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1); + if(fret>=0) + continue; + return(ret); + } + return(!was_failure); +} + + +int Xorriso_make_return_value(struct XorrisO *xorriso, int flag) +{ + int exit_value= 0; + + if(xorriso->eternal_problem_status >= xorriso->return_with_severity) + exit_value= xorriso->return_with_value; + if(exit_value) { + sprintf(xorriso->info_text, + "-return_with %s %d triggered by problem severity %s", + xorriso->return_with_text, exit_value, + xorriso->eternal_problem_status_text); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + } + return(exit_value); +} + + +#ifdef Xorriso_with_maiN + +int main(int argc, char **argv) +{ + +#else + +int Xorriso_main(int argc, char **argv) +{ + +#endif /* Xorriso_with_maiN */ + + int ret,i; + struct XorrisO *xorriso= NULL; + + if(argc<2) { + fprintf(stderr, + "xorriso %s : RockRidge filesystem manipulator, libburnia project.\n\n", + Xorriso_program_versioN); + fprintf(stderr,"usage : %s [options]\n", + argv[0]); + fprintf(stderr," More is told by option -help\n"); + exit(2); + } + setlocale(LC_CTYPE, ""); + ret= Xorriso_new(&xorriso,argv[0],0); + if(ret<=0) { + fprintf(stderr,"Creation of XorrisO object failed. (not enough memory ?)\n"); + exit(3); + } + + /* The prescan of arguments performs actions which have to happen before + the normal processing of startup files and arguments. + */ + ret= Xorriso_prescan_args(xorriso,argc,argv,0); + if(ret==0) + goto end_sucessfully; + if(ret<0) + exit(5); + + fprintf(stderr, + "xorriso %s : RockRidge filesystem manipulator, libburnia project.\n\n", + Xorriso_program_versioN); + ret= Xorriso_startup_libraries(xorriso, 0); + if(ret<=0) + exit(4); + Xorriso_process_msg_queues(xorriso, 0); + + /* Interpret startup file */ + if(!xorriso->no_rc) { + ret= Xorriso_read_rc(xorriso, 0); + if(ret==3) + goto end_sucessfully; + if(ret<=0) + exit(5); + } + + /* Interpret program arguments */ + if(xorriso->bsl_interpretation & 16) + Sfile_argv_bsl(argc, &argv, 0); /* apply Sfile_bsl_interpreter() to args */ + i= 1; + ret= Xorriso_interpreter(xorriso,argc,argv,&i,2); + if(ret==3) + goto end_sucessfully; + if(ret<=0) + exit(5); + + if(xorriso->dialog) { + ret= Xorriso_dialog(xorriso,0); + if(ret<=0) + exit(6); + } +end_sucessfully:; + Xorriso_process_msg_queues(xorriso, 0); + if(xorriso->volset_change_pending) + Xorriso_option_end(xorriso, 2); + Xorriso_process_msg_queues(xorriso, 0); + ret= Xorriso_make_return_value(xorriso, 0); + Xorriso_process_errfile(xorriso, 0, "xorriso end", 0, 1); + Xorriso_destroy(&xorriso,1); + exit(ret); +} + diff --git a/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso.h b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso.h new file mode 100644 index 00000000..5c3a0242 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso.h @@ -0,0 +1,709 @@ + +/* Command line oriented batch and dialog tool which creates, loads, + manipulates and burns ISO 9660 filesystem images. + + Copyright 2007-2008 Thomas Schmitt, <scdbackup@gmx.net> + + Provided under GPL version 2. + + This file contains the public option interface of xorriso. +*/ + +#ifndef Xorriso_includeD +#define Xorriso_includeD yes + +/** Opaque handle of the xorriso runtime context */ +struct XorrisO; + + +/* --------------------- Fundamental Management ------------------- */ + +/* Create a new xorriso object and tell it the program name to be used + with messages and for decision of special behavior. + @param xorriso returns the newly created XorrisO object + @param progname typically argv[0] of main(). Some leafnames of the progname + path have special meaning and trigger special behavior: + "osirrox" allows image-to-disk copying: -osirrox "on" + "xorrisofs" activates permanent mkisofs emulation + "genisofs" alias of "xorrisofs" + "mkisofs" alias of "xorrisofs" + "genisoimage" alias of "xorrisofs" + @parm flag unused yet, submit 0 + @return >0 success , <=0 failure, no object created +*/ +int Xorriso_new(struct XorrisO ** xorriso, char *progname, int flag); + + +/* Make global library initializations. + This must be done with the first xorriso object that gets created and + with the first xorriso object that gets created after Xorriso_destroy(,1). +*/ +int Xorriso_startup_libraries(struct XorrisO *xorriso, int flag); + + +/* Destroy xorriso object when it is no longer needed. + @param flag bit0= Make global librariy shutdown. + Use only with last xorriso object to be destroyed. + +*/ +int Xorriso_destroy(struct XorrisO **xorriso, int flag); + + +/* --------------------- Problem Status and Message API ------------------- */ + + +/** Submit a problem message to the xorriso problem reporting and handling + system. This will eventually increase problem status rank, which may + at certain stages in the program be pardoned and reset to 0. + The pardon is governed by Xorriso_option_abort_on() and by the anger + of the affected program part. If no pardon has been given, then the problem + status reaches the caller of option functions. + Problem status should be inquired by Xorriso_eval_problem_status() and be + reset before next option execution by Xorriso_set_problem_status(). + The problem status itself does not cause the failure of option functions. + But in case of failures for other reasons, a remnant overly severe problem + status can cause overly harsh program reactions. + @param xorriso The environment handle + @param error_code The unique error code of your message. + Submit 0 if you do not have reserved error codes within + the libburnia project. + @param msg_text Not more than 8196 characters of message text. + A final newline character gets appended automatically. + @param os_errno Eventual errno related to the message. Submit 0 if + the message is not related to a operating system error. + @param severity One of "ABORT", "FATAL", "SORRY", "WARNING", "HINT", + "NOTE", "UPDATE", "DEBUG". Defaults to "FATAL". + @param flag Bitfield for control purposes + bit0= use pager (as with result) + bit1= permission to suppress output + @return 1 if message was delivered, <=0 if failure +*/ +int Xorriso_msgs_submit(struct XorrisO *xorriso, + int error_code, char msg_text[], int os_errno, + char severity[], int flag); + +/** Alternative call interface of Xorriso_msgs_submit with void* instead + of struct XorrisO* +*/ +int Xorriso_msgs_submit_void(void *xorriso, + int error_code, char msg_text[], int os_errno, + char severity[], int flag); + + +/** Evaluate an advise whether to abort or whether to go on with option + processing. This should be called after any option function was processed. + It updates the problem status by processing the library message queues + and then it uses this status and the submitted return value ot the + option function to evaluate the situation. + @param xorriso The environment handle + @param ret The return value of the previously called option function + @param flag bit0= do not issue own event messages + bit1= take xorriso->request_to_abort as reason for abort + @return Gives the advice: + 2= pardon was given, go on + 1= no problem, go on + 0= function failed but xorriso would not abort, go on + <0= do abort + -1 = due to xorriso->problem_status + or due to ret<0 + -2 = due to xorriso->request_to_abort +*/ +int Xorriso_eval_problem_status(struct XorrisO *xorriso, int ret, int flag); + + +/** Set the current problem status of the xorriso handle. + @param xorriso The environment handle + @param severity A severity text. Empty text resets to "No Problem". + @param flag Unused yet. Submit 0. + @return <=0 failure (e.g. wrong severity text), 1 success. +*/ +int Xorriso_set_problem_status(struct XorrisO *xorriso, char *severity, + int flag); + + +/* The next two functions are part of Xorriso_eval_problem_status(). + You may use them to build an own advisor function or to drain the + library message queues more frequently. +*/ + +/** Obtain the current problem status of the xorriso handle. + @param xorriso The environment handle + @param severity The severity text matching the current problem status + @param flag Unused yet. Submit 0. + @return The severity rank number. 0= no problem occured. +*/ +int Xorriso_get_problem_status(struct XorrisO *xorriso, char severity[80], + int flag); + + +/** Forward any pending messages from the library message queues to the + xorriso message system which puts out on info channel. This registers + the severity of the library events like the severity of a message submitted + via Xorriso_msgs_submit(). + xorriso sets the message queues of the libraries to queuing "ALL". + So it is essential that they get drained regularly. + @param xorriso The environment handle + @param flag Unused yet. Submit 0. + @return 1 on success, <=0 if failure +*/ +int Xorriso_process_msg_queues(struct XorrisO *xorriso, int flag); + + + +/* The outlist stack allows to redirect the info and result messages from + their normal channels into a pair of string lists which can at some + later time be retrieved by the application. + These redirection caches can be stacked to allow stacked applications. + xorriso itself uses them for internal purposes. +*/ + +/* A list item able of forming double chained lists */ +struct Xorriso_lsT; + +/** Maximum number of stacked redirections */ +#define Xorriso_max_outlist_stacK 32 + +/** Enable a new redirection of info and/or result channel. The normal message + output and eventual older redirections will not see new messages until + the redirection is ended by a call to Xorriso_pull_outlists() with the + stack_handle value returned by this call. + Redirected output is not written to the files of Xorriso_option_logfile() + and the Xorriso_option_pkt_output() protocol will not be applied. + @param xorriso The environment handle + @param stack_handle returns an id number which is unique as long as + its redirection is stacked. It may be re-used after + its redirection was pulled from the stack. + @param flag Bitfield for control purposes + bit0= redirect result channel + bit1= redirect info channel + If bit0 and bit1 are 0, both channels get redirected. + @return 1 on success, <=0 if failure +*/ +int Xorriso_push_outlists(struct XorrisO *xorriso, int *stack_handle, + int flag); + + +/** Disable the redirection given by stack_handle. If it was the current + receiver of messages then switch output to the next older redirection + resp. to the normal channels if no redirections are stacked any more. + The messages collected by the disabled redirection are handed out as + two lists. Both lists have to be disposed via Xorriso_lst_destroy_all() + when they are no longer needed. + The message lists are either NULL or represented by their first + Xorriso_lsT item. + @param xorriso The environment handle + @param stack_handle The id number returned by Xorriso_push_outlists() + @param result_list Result and mark messages (usually directed to stdout) + @param info_list Info and mark messages (usually directed to stderr) + @param flag unused yet, submit 0 + @return 1 on success, <=0 if failure +*/ +int Xorriso_pull_outlists(struct XorrisO *xorriso, int stack_handle, + struct Xorriso_lsT **result_list, + struct Xorriso_lsT **info_list, int flag); + + +/** Obtain the text message from the current list item. + @param entry The current list item + @param flag unused yet, submit 0 + @return Pointer to the text content of the list item. + This pointer does not have to be freed. +*/ +char *Xorriso_lst_get_text(struct Xorriso_lsT *entry, int flag); + + +/** Obtain the address of the next item in the chain of messages. + An iteration over the output of Xorriso_pull_outlists() starts at the + returned result_list resp. info_list and ends when this function returns + NULL. + @param entry The current list item + @param flag unused yet, submit 0 + @return Pointer to the next list item or NULL if end of list. + This pointer does not have to be freed. +*/ +struct Xorriso_lsT *Xorriso_lst_get_next(struct Xorriso_lsT *entry, int flag); + + +/** Obtain the address of the previous item in the chain of messages. + @param entry The current list item + @param flag unused yet, submit 0 + @return Pointer to the previous list item or NULL if start of list. + This pointer does not have to be freed. +*/ +struct Xorriso_lsT *Xorriso_lst_get_prev(struct Xorriso_lsT *entry, int flag); + + +/** Destroy all list items which are directly or indirectly connected to + the given link item. + Apply this to each of the two list handles obtained by + Xorriso_pull_outlists() when the lists are no longer needed. + @param lstring *lstring will be freed and set to NULL. + It is not dangerous to submit a pointer to a NULL-pointer. + @param flag unused yet, submit 0 + @return -1= lstring was NULL (i.e. wrong use of this call), + 0= *lstring was already NULL, + 1= item actually disposed +*/ +int Xorriso_lst_destroy_all(struct Xorriso_lsT **lstring, int flag); + + + +/* ---------------------------- Options API ------------------------ */ +/* See man 1 xorriso for explanation of the particular options */ +/* + Before each call to an option function, there should happen: + Xorriso_set_problem_status() with empty severity text. + + After each call to an option function, there should happen: + Xorriso_eval_problem_status() + One should follow its eventual advice to abort. +*/ + + +/* Option -abort_on */ +int Xorriso_option_abort_on(struct XorrisO *xorriso, char *severity, int flag); + +/* Option -add */ +/* @param flag bit0=do not report the added item + bit1=do not reset pacifier, no final pacifier message +*/ +int Xorriso_option_add(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag); + +/* Option -add_plainly "on"|"off" */ +int Xorriso_option_add_plainly(struct XorrisO *xorriso, char *mode, + int flag); + + +/* Option -alter_date, alter_date_r */ +/* @param flag bit0=recursive (-alter_date_r) +*/ +int Xorriso_option_alter_date(struct XorrisO *xorriso, + char *time_type, char *timestring, + int argc, char **argv, int *idx, int flag); + +/* Option -application_id */ +int Xorriso_option_application_id(struct XorrisO *xorriso, char *name, + int flag); + +/* Option -as */ +/* @param flag bit0=do not report the added item + bit1=do not reset pacifier, no final pacifier message +*/ +int Xorriso_option_as(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag); + +/* Option -assert_volid */ +int Xorriso_option_assert_volid(struct XorrisO *xorriso, char *pattern, + char *severity, int flag); + +/* Option -backslash_codes */ +int Xorriso_option_backslash_codes(struct XorrisO *xorriso, char *mode, + int flag); + +/* Option -ban_stdio_write */ +int Xorriso_option_ban_stdio_write(struct XorrisO *xorriso, int flag); + +/* Option -blank and -format */ +/* @param flag bit0= format rather than blank + @return <=0 error , 1 success, 2 revoked by -reassure +*/ +int Xorriso_option_blank(struct XorrisO *xorriso, char *mode, int flag); + +/* Option -boot_image */ +int Xorriso_option_boot_image(struct XorrisO *xorriso, char *form, + char *treatment, int flag); + +/* Option -cd alias -cdi */ +int Xorriso_option_cdi(struct XorrisO *xorriso, char *iso_rr_path, int flag); + +/* Option -cdx */ +int Xorriso_option_cdx(struct XorrisO *xorriso, char *disk_path, int flag); + +/* Option -charset */ +/* @param flag bit0= set in_charset + bit1= set out_charset +*/ +int Xorriso_option_charset(struct XorrisO *xorriso, char *name, int flag); + +/* Option -check_media */ +int Xorriso_option_check_media(struct XorrisO *xorriso, + int argc, char **argv, int *idx, int flag); + +/* Option -check_media_defaults */ +int Xorriso_option_check_media_defaults(struct XorrisO *xorriso, + int argc, char **argv, int *idx, int flag); + +/* Option -chgrp alias -chgrpi , chgrp_r alias chgrpi */ +/* @param flag bit0=recursive (-chgrp_r) +*/ +int Xorriso_option_chgrpi(struct XorrisO *xorriso, char *gid, + int argc, char **argv, int *idx, int flag); + +/* Option -chmod alias -chmodi , -chmod_r alias chmod_ri */ +/* @param flag bit0=recursive (-chmod_r) +*/ +int Xorriso_option_chmodi(struct XorrisO *xorriso, char *mode, + int argc, char **argv, int *idx, int flag); + +/* Option -chown alias -chowni , chown_r alias chown_ri */ +/* @param flag bit0=recursive (-chown_r) +*/ +int Xorriso_option_chowni(struct XorrisO *xorriso, char *uid, + int argc, char **argv, int *idx, int flag); + +/* Option -close "on"|"off" */ +int Xorriso_option_close(struct XorrisO *xorriso, char *mode, int flag); + +/* Option -commit */ +/* @param flag bit0= leave indrive and outdrive aquired as they were, + i.e. do not aquire outdrive as new in-out-drive + bit1= do not perform eventual -reassure + @return <=0 error , 1 success, 2 revoked by -reassure +*/ +int Xorriso_option_commit(struct XorrisO *xorriso, int flag); + +/* Option -commit_eject */ +/* @return <=0 error , 1 success, 2 revoked by -reassure +*/ +int Xorriso_option_commit_eject(struct XorrisO *xorriso, char *which, int flag); + +/* Option -compare and -compare_r + @param flag bit0= issue summary message + bit1= do not reset pacifier, no final pacifier message + bit2= do not issue pacifier messages at all + bit3= recursive: -compare_r +*/ +int Xorriso_option_compare(struct XorrisO *xorriso, char *disk_path, + char *iso_path, int flag); + +/* Option -cpr alias -cpri */ +int Xorriso_option_cpri( struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag); + +/* Options -cpx , -cpax, -cp_rx , -cp_rax */ +/* @param flag bit0= recursive (-cp_rx, -cp_rax) + bit1= full property restore (-cpax, -cp_rax) +*/ +int Xorriso_option_cpx(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag); + +/* Option -cut_out */ +int Xorriso_option_cut_out(struct XorrisO *xorriso, char *disk_path, + char *start, char *count, char *iso_rr_path, int flag); + +/* Options -dev , -indev, -outdev */ +/* @param flag bit0=use as indev , bit1= use as outdev + @return <=0 error , 1 success, 2 revoked by -reassure +*/ +int Xorriso_option_dev(struct XorrisO *xorriso, char *adr, int flag); + +/* Option -devices */ +/* @return <=0 error , 1 success, 2 revoked by -reassure +*/ +int Xorriso_option_devices(struct XorrisO *xorriso, int flag); + +/* Option -dialog "on"|"off" */ +int Xorriso_option_dialog(struct XorrisO *xorriso, char *mode, int flag); + +/* Option -disk_pattern "on"|"ls"|"off" */ +int Xorriso_option_disk_pattern(struct XorrisO *xorriso, char *mode, int flag); + +/* Option -dummy "on"|"off" */ +int Xorriso_option_dummy(struct XorrisO *xorriso, char *mode, int flag); + +/* Option -eject */ +/* @param flag bit0=do not report toc of eventually remaining drives +*/ +int Xorriso_option_eject(struct XorrisO *xorriso, char *which, int flag); + +/* Options -end , and -rollback_end */ +/* @param flag bit0= discard pending changes + @return <=0 error , 1 success, 2 revoked by -reassure +*/ +int Xorriso_option_end(struct XorrisO *xorriso, int flag); + +/* Option -errfile_log marked|plain path|-|"" */ +int Xorriso_option_errfile_log(struct XorrisO *xorriso, + char *mode, char *path, int flag); + +/* Option -error_behavior */ +int Xorriso_option_error_behavior(struct XorrisO *xorriso, + char *occasion, char *behavior, int flag); + +/* Options -extract , -extract_single */ +/* @param flag bit0=do not report the restored item + bit1=do not reset pacifier, no final pacifier message + bit5= -extract_single: eventually do not insert directory tree +*/ +int Xorriso_option_extract(struct XorrisO *xorriso, char *disk_path, + char *iso_path, int flag); + +/* Option -extract_cut */ +int Xorriso_option_extract_cut(struct XorrisO *xorriso, char *iso_rr_path, + char *start, char *count, char *disk_path, int flag); + +/* Option -follow */ +int Xorriso_option_follow(struct XorrisO *xorriso, char *mode, int flag); + +/* Option -find alias -findi, and -findx */ +/* @param flag bit0= -findx rather than -findi + bit1= do not reset pacifier, no final pacifier message + do not reset find_compare_result +*/ +int Xorriso_option_find(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag); + +/* Option -fs */ +int Xorriso_option_fs(struct XorrisO *xorriso, char *size, int flag); + +/* Option -gid */ +int Xorriso_option_gid(struct XorrisO *xorriso, char *gid, int flag); + +/* Option -grow_blindly */ +int Xorriso_option_grow_blindly(struct XorrisO *xorriso, char *msc2, int flag); + +/* Option -help and part of -prog_help */ +int Xorriso_option_help(struct XorrisO *xorriso, int flag); + +/* Option -history */ +int Xorriso_option_history(struct XorrisO *xorriso, char *line, int flag); + +/* Option -iso_rr_pattern "on"|"ls"|"off" */ +int Xorriso_option_iso_rr_pattern(struct XorrisO *xorriso, char *mode, + int flag); + +/* Option -joliet "on"|"off" */ +int Xorriso_option_joliet(struct XorrisO *xorriso, char *mode, int flag); + +/* Option -list_delimiter */ +int Xorriso_option_list_delimiter(struct XorrisO *xorriso, char *text, + int flag); + +/* Option -list_formats */ +int Xorriso_option_list_formats(struct XorrisO *xorriso, int flag); + +/* Option -load session|track|sbsector value */ +/* @param flag bit0= with adr_mode sbsector: adr_value is possibly 16 too high + @return <=0 error , 1 success, 2 revoked by -reassure +*/ +int Xorriso_option_load(struct XorrisO *xorriso, char *adr_mode, + char *adr_value, int flag); + +/* Option -logfile */ +int Xorriso_option_logfile(struct XorrisO *xorriso, char *channel, + char *fileadr, int flag); + +/* Options -ls alias -lsi and -lsl alias -lsli + and -lsd alias -lsdi and -lsdl alias -lsdli + and -du alias -dui and -dus alias -dusi + @param flag bit0= long format (-lsl , -du) + bit1= do not expand patterns but use literally + bit2= du rather than ls + bit3= list directories as themselves (ls -d) +*/ +int Xorriso_option_lsi(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag); + +/* Options -lsx, -lslx, -lsdx , -lsdlx , -dux , -dusx + @param flag bit0= long format (-lslx , -dux) + bit1= do not expand patterns but use literally + bit2= du rather than ls + bit3= list directories as themselves (ls -d) +*/ +int Xorriso_option_lsx(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag); + +/* Option -map */ +/* @param flag bit0=do not report the added item + bit1=do not reset pacifier, no final pacifier message +*/ +int Xorriso_option_map(struct XorrisO *xorriso, char *disk_path, + char *iso_path, int flag); + +/* Options -map_l , -compare_l , -update_l , -extract_l */ +/* @param flag bit8-11= mode 0= -map_l + 1= -compare_l + 2= -update_l + 3= -extract_l +*/ +int Xorriso_option_map_l(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag); + +/* Option -mark */ +int Xorriso_option_mark(struct XorrisO *xorriso, char *mark, int flag); + +/* Option -mkdir alias -mkdiri */ +int Xorriso_option_mkdiri(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag); + +/* Option -mount */ +/* @param bit0= print mount command to result channel rather than performing it +*/ +int Xorriso_option_mount(struct XorrisO *xorriso, char *dev, char *adr_mode, + char *adr, char *cmd, int flag); + + +/* Option -mv alias -mvi */ +int Xorriso_option_mvi(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag); + +/* Option -no_rc */ +int Xorriso_option_no_rc(struct XorrisO *xorriso, int flag); + +/* Option -not_leaf */ +int Xorriso_option_not_leaf(struct XorrisO *xorriso, char *pattern, int flag); + +/* Option -not_list , -quoted_not_list */ +/* @param flag bit0= -quoted_not_list */ +int Xorriso_option_not_list(struct XorrisO *xorriso, char *adr, int flag); + +/* Option -not_paths */ +int Xorriso_option_not_paths(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag); + +/* Option -options_from_file */ +/* @return <=0 error , 1 = success , 3 = request to end program run */ +int Xorriso_option_options_from_file(struct XorrisO *xorriso, char *adr, + int flag); + +/* Option -osirrox "on"|"off" */ +int Xorriso_option_osirrox(struct XorrisO *xorriso, char *mode, int flag); + +/* Option -overwrite "on"|"nondir"|"off" */ +int Xorriso_option_overwrite(struct XorrisO *xorriso, char *mode, int flag); + +/* Option -pacifier */ +int Xorriso_option_pacifier(struct XorrisO *xorriso, char *style, int flag); + +/* Option -padding */ +int Xorriso_option_padding(struct XorrisO *xorriso, char *size, int flag); + +/* Option -page */ +int Xorriso_option_page(struct XorrisO *xorriso, int len, int width, int flag); + +/* Option -paste_in */ +int Xorriso_option_paste_in(struct XorrisO *xorriso, char *iso_rr_path, + char *disk_path, char *start, char *count, int flag); + +/* Option -path_list , -quoted_path_list */ +/* @param flag bit0= -quoted_path_list */ +int Xorriso_option_path_list(struct XorrisO *xorriso, char *adr, int flag); + +/* Option -pathspecs */ +int Xorriso_option_pathspecs(struct XorrisO *xorriso, char *mode, int flag); + +/* Option -pkt_output */ +int Xorriso_option_pkt_output(struct XorrisO *xorriso, char *mode, int flag); + +/* Option -print */ +int Xorriso_option_print(struct XorrisO *xorriso, char *text, int flag); + +/* Option -print_size + @param flag bit0= report in mkisofs compatible form on real stdout +*/ +int Xorriso_option_print_size(struct XorrisO *xorriso, int flag); + +/* Option -prog */ +int Xorriso_option_prog(struct XorrisO *xorriso, char *name, int flag); + +/* Option -prog_help */ +int Xorriso_option_prog_help(struct XorrisO *xorriso, char *name, int flag); + +/* Option -publisher */ +int Xorriso_option_publisher(struct XorrisO *xorriso, char *name, int flag); + +/* Option -pwd alias -pwdi */ +int Xorriso_option_pwdi(struct XorrisO *xorriso, int flag); + +/* Option -pwdx */ +int Xorriso_option_pwdx(struct XorrisO *xorriso, int flag); + +/* Option -reassure "on"|"tree"|"off" */ +int Xorriso_option_reassure(struct XorrisO *xorriso, char *mode, int flag); + +/* Option -relax_compliance */ +int Xorriso_option_relax_compliance(struct XorrisO *xorriso, char *mode, + int flag); + +/* Option -report_about */ +int Xorriso_option_report_about(struct XorrisO *xorriso, char *severity, + int flag); + +/* Option -return_with */ +int Xorriso_option_return_with(struct XorrisO *xorriso, char *severity, + int exit_value, int flag); + +/* Option -revoke_exclusions */ +int Xorriso_option_revoke_exclusions(struct XorrisO *xorriso, int flag); + +/* Options -rm alias -rmi , -rm_r alias -rm_ri , -rmdir alias -rmdiri */ +/* @param flag bit0=recursive , bit2= remove empty directory: rmdir */ +int Xorriso_option_rmi(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag); + +/* Option -rollback */ +/* @param flag bit0= do not -reassure + @return <=0 error , 1 success, 2 revoked by -reassure +*/ +int Xorriso_option_rollback(struct XorrisO *xorriso, int flag); + +/* Option -rom_toc_scan */ +int Xorriso_option_rom_toc_scan(struct XorrisO *xorriso, char *mode, + int flag); + +/* Option -session_log */ +int Xorriso_option_session_log(struct XorrisO *xorriso, char *path, int flag); + +/* Option -speed */ +int Xorriso_option_speed(struct XorrisO *xorriso, char *speed, int flag); + +/* Option -split_size */ +int Xorriso_option_split_size(struct XorrisO *xorriso, char *s, int flag); + +/* Option -status */ +int Xorriso_option_status(struct XorrisO *xorriso, char *mode, int flag); + +/* Option -status_history_max */ +int Xorriso_option_status_history_max(struct XorrisO *xorriso, int num1, + int flag); + +/* Option -stream_recording */ +int Xorriso_option_stream_recording(struct XorrisO *xorriso, char *mode, + int flag); + +/* Option -tell_media_space */ +int Xorriso_option_tell_media_space(struct XorrisO *xorriso, int flag); + +/* Option -temp_mem_limit */ +int Xorriso_option_temp_mem_limit(struct XorrisO *xorriso, char *size, + int flag); + +/* Option -toc */ +int Xorriso_option_toc(struct XorrisO *xorriso, int flag); + +/* Option -uid */ +int Xorriso_option_uid(struct XorrisO *xorriso, char *uid, int flag); + +/* Options -update and -update_r + @param flag bit0= issue summary message + bit1= do not reset pacifier, no final pacifier message + bit2= do not issue pacifier messages at all + bit3= recursive: -update_r +*/ +int Xorriso_option_update(struct XorrisO *xorriso, char *disk_path, + char *iso_path, int flag); + +/* Option -use_readline */ +int Xorriso_option_use_readline(struct XorrisO *xorriso, char *mode, int flag); + +/* Option -version */ +int Xorriso_option_version(struct XorrisO *xorriso, int flag); + +/* Option -volid */ +int Xorriso_option_volid(struct XorrisO *xorriso, char *volid, int flag); + + +#endif /* Xorriso_includeD */ + + diff --git a/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_buildstamp.h b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_buildstamp.h new file mode 100644 index 00000000..f2d17a20 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_buildstamp.h @@ -0,0 +1,3 @@ +#ifndef Xorriso_build_timestamP +#define Xorriso_build_timestamP "-none-given-" +#endif diff --git a/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_buildstamp_none.h b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_buildstamp_none.h new file mode 100644 index 00000000..f2d17a20 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_buildstamp_none.h @@ -0,0 +1,3 @@ +#ifndef Xorriso_build_timestamP +#define Xorriso_build_timestamP "-none-given-" +#endif diff --git a/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_eng.html b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_eng.html new file mode 100644 index 00000000..cbeaba34 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_eng.html @@ -0,0 +1,543 @@ +<HTML> + +<HEAD> +<META NAME="description" CONTENT="xorriso, creates, loads, manipulates and writes ISO 9660 filesystem images with Rock Ridge extensions"> +<META NAME="keywords" CONTENT="xorriso, libburn, libburnia, burn, CD, DVD, ISO, ISO 9660, RockRidge, Rock Ridge, Linux, FreeBSD, recording, burning, CD-R, CD-RW, DVD-R, DVD-RW, DVD+RW, DVD+R, DVD+R DL, BD-RE, BD-R, scdbackup"> +<META NAME="robots" CONTENT="follow"> +<TITLE>xorriso homepage english + + + + + +
+

Homepage of

+

xorriso

+ +

ISO 9660 Rock Ridge Filesystem Manipulator for Linux and FreeBSD

+
+ +

+

Purpose:

+xorriso copies file objects from POSIX compliant filesystems +into Rock Ridge enhanced ISO 9660 filesystems and allows +session-wise manipulation of such filesystems. It can load the management +information of existing ISO images and it writes the session results to +optical media or to filesystem objects. +
+Vice versa xorriso is able to restore file objects from ISO 9660 filesystems. +

+

+ +


+ +Direct hop to download links -> + +

+

Hardware requirements:

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

+ +

+

Software requirements :

+
+
Linux with kernel 2.4 or higher (and libc, of course) :
+
With kernel 2.4 an ATA drive has to be under ide-scsi emulation.
+
With kernel 2.6 the drive should not be under ide-scsi.
+
or FreeBSD (with libc, of course) :
+
ATAPI/CAM support has to be enabled in the kernel, see atapicam(4).
+
libpthread
+
is supposed to be a standard system component.
+
libreadline and libreadline-dev
+
are optional and eventually make dialog more convenient.
+
+

+ +

+

+GPL software included:
+

+
+
libburn-0.5.7
+
reads and writes data from and to CD, DVD, BD-RE.
+
(founded by Derek Foreman and Ben Jansens, +developed and maintained since August 2006 by +Thomas Schmitt from team of libburnia-project.org)
+
libisofs-0.6.12
+
operates on ISO 9660 filesystem images.
+
(By Vreixo Formoso and Mario Danic from team of libburnia-project.org)
+
libisoburn-0.3.0
+
coordinates libburn and libisofs, emulates multi-session where needed.
+
(By Vreixo Formoso and Thomas Schmitt +from team of libburnia-project.org)
+
+
The source code of this software is independent of +cdrecord and mkisofs. +
+

+ +

+This program has been tested on Intel/AMD Linux +and on FreeBSD systems.
+For ports to other usable systems contact us. +

+ +
+ +

+

Special features:

+
    +
  • +ISO 9660 formatter and burner for CD, DVD, BD-RE are fixely integrated. +
  • +
  • +Operates on an existing ISO image or creates a new one. +
  • +
  • +Copies files from filesystem into the ISO image. +
  • +
  • +Changes file properties, renames or deletes file objects in the ISO image. +
  • +
  • +Updates ISO subtrees incrementally to match given disk subtrees. +
  • +
  • +Writes result as completely new image or as add-on session +to optical media or filesystem objects. +
  • +
  • +Can activate ISOLINUX boot images by El Torito boot record and by MBR. +
  • +
  • +Can perform multi-session tasks as emulation of mkisofs and cdrecord. +
  • +
  • +Can restore single files and whole trees from ISO image to disk filesystem. +
  • + +
  • +Can check media for damages and copy readable blocks to disk. +
  • +
  • +Scans for optical drives, blanks re-useable optical media, formats media. +
  • +
  • +Suitable for: +CD-R, CD-RW, DVD-R, DVD-RW, DVD+R, DVD+R DL, DVD+RW, DVD-RAM, BD-RE. +
  • +
  • +Reads its instructions from command line arguments, dialog, and batch files. +
  • +
  • +Provides navigation commands for interactive ISO image manipulation. +
  • + +
+

+ +

+

Command Examples:

+
+
Get an overview of drives and their addresses
+
# xorriso -devices
+
...
+
0 -dev '/dev/sr0' rwrw-- : 'TSSTcorp' 'CDDVDW SH-S203B'
+
1 -dev '/dev/scd1' rwrw-- : 'PHILIPS ' 'SPD3300L'
+
2 -dev '/dev/hda' rwrw-- : 'HL-DT-ST' 'DVD-ROM GDR8162B'
+
...
+
Being superuser avoids permission problems with /dev/srN resp. /dev/hdX . +
+
Ordinary users should then get granted rw access to the /dev files +as listed by option -devices.
+
 
+ +
Options are either performed as program arguments or as dialog input. +Some options have a parameter list of variable length. This list has to +be terminated by word '--' or by the end of the input line. Option -add +may accept pathspecs of form target=source as known from program mkisofs.
+ +
+ +
Get info about a particular drive and loaded media:
+
$ xorriso -indev /dev/sr0 -du / -- -toc 2>&1 | less
+ +
Make re-usable media writable again, delete any ISO 9660 image, +eventually prepare yet unused BD-RE:
+
$ xorriso -outdev /dev/sr0 -blank as_needed -eject all
+ +
+
+
+ +
Write some directories into a new or existing ISO 9660 image:
+
$ xorriso -dev /dev/sr0 -add /home/me/sounds /home/me/pictures +
+ +
Have a look at the result:
+
$ xorriso -indev /dev/sr0 -du / -- -toc 2>&1 | less
+ +
+
+
+ +
Create new ISO-9660 filesystem image, compose content, +adjust permissions to make it publicly read-only, +write it to media and immediately eject media without +previously reloading the written image. +
+
$ cd /home/me
+
$ xorriso -outdev /dev/sr0 -blank as_needed \
+
  -map /home/me/sounds /sounds \
+
  -map /home/me/pictures /pictures \
+
  -rm_r /sounds/indecent '/pictures/*private*' -- \
+
  -cd / \
+
  -add pictures/private/horses* -- \
+
  -chmod_r a+r,a-w / -- \
+
  -find / -type d -exec chmod a+x -- \
+
  -volid SOUNDS_PICS_2008_01_16 \
+
  -commit_eject all
+
+
+
+ +
Load the previous session from media, +remove (i.e. hide) directory /sounds, +rename /pictures/private/horses, +add new directory trees /sounds and /movies, +disallow any access for group and others. +Finally write as additional session to media and eject:
+
$ xorriso -dev /dev/sr0 \
+
  -rm_r /sounds -- \
+
  -mv /pictures/private/horses /horse_show -- \
+
  -map /home/me/prepared_for_dvd/sounds_dummy /sounds \
+
  -map /home/me/prepared_for_dvd/movies /movies \
+
  -chmod_r go-rwx / -- \
+
  -volid SOUNDS_PICS_2008_01_17 \
+
  -commit_eject all
+
+
+
+ +
Merge the various sessions from old readable media into a single session +on new writeable media, +cleaning out all invalidated files and session overhead. +Touch / in order to mark the image as worth to be written. +
+Important: -indev and -outdev have to be different drives. +
+
$ xorriso -indev /dev/dvd \
+
  -alter_date a +0 / -- \
+
  -outdev /dev/sr0 -blank fast \
+
  -commit_eject all
+ +
+
+
+ +
Dialog mode accepts one or more options per line. An option and all its +arguments have to be given in one single line. Command -end stops the program +run. It will write eventually pending changes to media, if that has not +already been done by a previous -commit.
+
$ xorriso -dialog on
+
enter option and arguments :
+
-dev /dev/sr0
+
enter option and arguments :
+
-map /home/me/prepared_for_dvd/sounds_dummy /sounds
+
enter option and arguments :
+
-map /home/me/prepared_for_dvd/movies /movies
+
Available navigation commands: -cd, -ls, -du, -find
+
enter option and arguments :
+
-commit
+
... perform further commands and finally do:
+
enter option and arguments :
+
-end
+ +
+
+
+ +
The following command can be run on blank media to create a +copy of the mentioned disk directory trees, and it can be run on appendable +media to perform a minimal set of change operations which update the +old ISO copies to match the new disk trees. +Older states can be retrieved by help of mount option "session=" from CD-R[W], +by help of "sbsector=" from other media. +So this constitutes true incremental backup. +
+The copies will be complete, except all file names ending +with ".o" or ".swp" which are excluded by options -not_leaf. +
+
$ xorriso -dev /dev/sr0 \
+
   -volid PROJECTS_MAIL_"$(date '+%Y_%m_%d_%H%M%S')" \
+
   -not_leaf '*.o' -not_leaf '*.swp' \
+
   -update_r /home/thomas/open_source_projects /open_source_projects \
+
   -update_r /home/thomas/personal_mail /personal_mail \
+
   -commit -toc -eject all
+ +
+
+
+ +
+After the user has already created a suitable file tree on disk +and copied the ISOLINUX files into subdirectory ./boot/isolinux of +that tree, xorriso can burn an El Torito bootable media: +
+
$ xorriso -outdev /dev/sr0 -blank as_needed \
+
   -map /home/me/ISOLINUX_prepared_tree / \
+
   -boot_image isolinux dir=/boot/isolinux
+
+An additional MBR is generated if the file isolinux.bin is modern enough +(syslinux version 3.72) and ready for "isohybrid". An MBR enables booting +from hard disk or USB stick. +
+
+ +
ISO images may not only be stored on optical media but also in +regular disk files or block devices for full multi-session operation. +The prefix "stdio:" indicates that normal file operations are +desired rather than MMC drive commands: +
+
$ xorriso -dev stdio:/tmp/regular_file ...other.options...
+ +
Other file types are suitable only for writing but not for reading:
+
$ xorriso -outdev stdio:/tmp/named_pipe ...other.options...
+ +
In batch mode it is possible to operate xorriso in a pipeline +with an external consumer of the generated ISO image. Any message +output will be redirected to stderr in this case.
+
$ xorriso -outdev - ...other.options... | consumer
+ + +
+
+
+ +
+Let xorriso serve underneath growisofs via its alias name "xorrisofs" +which enables mkisofs emulation: +
+
$ export MKISOFS="xorrisofs"
+
$ growisofs -Z /dev/dvd /some/files
+
$ growisofs -M /dev/dvd /more/files
+
+One may switch from mkisofs emulation to xorriso's own command mode: +
+
$ growisofs -M /dev/dvd -- outdev - -update_r /my/files /files +
+ +
+
+
+ +
If for any reason the reading operating system mishandles the ISO image +or some files in it, one may enable reverse operation of xorriso and copy +files or trees to disk: +
$ xorriso -indev /dev/sr0 \
+
   -osirrox on \
+
   -cpx '/pictures/private/horses*/*buttercup*' \
+
       /home/her/buttercup_dir -- \ +
   -extract /sounds /home/her/sounds_from_me
+ +
Consider to enter dialog mode and use commands like +-cd , -du , -lsl , -find. +
+
+
+ + +
Get overview of the options:
+
$ xorriso -help
+ +
Read the detailed manual page:
+
$ man xorriso
+
+ +

+ +
+ +

+

+

Download as source code (see README):

+
xorriso-0.3.0.pl00.tar.gz +(1080 KB). +
+
+ + +
Documentation:
+
README about installation and drive setup
+
xorriso -help gives an overview of options
+
man xorriso is the manual page
+
+ +
Contact:
+
Thomas Schmitt, scdbackup@gmx.net
+
libburn development mailing list, +libburn-hackers@pykix.org
+
+
License:
+
GPL version 2, +an Open Source approved license
+
 
+
+

+ +
+ +

+Bug fixes towards xorriso-0.2.8.pl01: +

    +
  • Forgot exit value registration to -return_with. Thanks to Steve Dodd.
  • +
  • -format "as_needed" did not recognize unformatted BD-RE
  • +
  • disk patterns with relative addresses were not properly resolved
  • + + +
+ +

+ +

+Enhancements towards previous stable version xorriso-0.2.8.pl01: +

    + +
  • Suitable ISOLINUX boot images are made alternatively bootable via MBR
  • +
  • New options -quoted_path_list, -quoted_not_list
  • +
  • New option -backslash_codes for terminal safety with weird file names
  • +
  • New options -charset, -in_charset, -out_charset
  • +
  • New option -application_id
  • +
  • New option -compliance
  • + +
+

+ +
+ +

+

+

Development snapshot, version 0.3.1 :

+
Bug fixes towards xorriso-0.3.0.pl00: +
    + +
  • Options -extract and -extract_single were not disabled with -osirrox off +
  • + +
+
+
Enhancements towards stable version 0.3.0.pl00: +
    +
  • New options -mount, -mount_cmd, -session_string
  • +
  • By using libburn-0.5.9: support for BD-R media
  • +
  • New -format modes by_size_ and fast_by_size_
  • +
  • New option -assert_volid
  • +
  • New option -drive_class for safety management of pseudo-drive access
  • + +
+
+
 
+
README 0.3.1 +
xorriso_0.3.1 -help
+
man xorriso (as of 0.3.1)
+
 
+
If you want to distribute development versions of xorriso, then use +this tarball which produces static linking between xorriso and the +libburnia libraries. +
+
Source (./bootstrap is already applied, build tested, +installation see README) +
+
+xorriso-0.3.1.tar.gz +(1080 KB). +
+
A dynamically linked development version of xorriso can be obtained +from repositories of + libburnia-project.org. +xorriso is part of libisoburn/trunk and will get built by its "make". +
+
Be warned that the libraries in SVN and bzr are development versions with +possibly unstable API/ABI enhancements. Do not distribute development +versions for dynamic linking. Only release versions are safe for that. +
+
Download: svn co http://svn.libburnia-project.org/libburn/trunk libburn +
+
Install: cd libburn ; ./bootstrap ; ./configure --prefix /usr ; make ; make install +
+
Download: bzr branch lp:libisofs
+
Install: cd libisofs ; ./bootstrap ; ./configure --prefix /usr ; make ; make install +
+
Download: svn co http://svn.libburnia-project.org/libisoburn/trunk libisoburn +
+
Install: cd libisoburn ; ./bootstrap ; ./configure --prefix /usr ; make ; make install +
+
Build of SVN versions needs +autotools of at least version 1.7 installed. +But after the run of ./bootstrap, only +vanilla tools like make and gcc are needed. +
+
 
+
+

+ +
+ +

+Many thanks to Derek Foreman and Ben Jansens for starting libburn. +
+Very special thanks to Andy Polyakov whose +dvd+rw-tools +provide the libburnia project with invaluable examples on how to deal +with DVD media and how to emulate multi-session on overwriteable media. +

+ +
+ + +
+ +

+Enjoying free Open Source hosting by www.webframe.org
+ +100 % Microsoft free
+and by sourceforge.net
+ +SourceForge Logo + +
+
+
+
Links to my other published software projects :
+
+cdrskin, a cdrecord emulator
+
+scdbackup, multi volume CD backup
+
+(a second source of above)
+
Some Tools for Image Collectors
+
+pppoem, a DSL throughput monitor (mainly for Linux kernel 2.4)
+
+

+Legal statement: This website does not serve any commercial purpose.
+

+
+ + diff --git a/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_makefile_am.txt b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_makefile_am.txt new file mode 100644 index 00000000..2c3b2072 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_makefile_am.txt @@ -0,0 +1,230 @@ +pkgconfigdir=$(libdir)/pkgconfig +libincludedir= + +lib_LTLIBRARIES = + +## ========================================================================= ## + +libinclude_HEADERS = + +## ========================================================================= ## + +bin_PROGRAMS = \ + xorriso/xorriso + +xorriso_xorriso_CPPFLAGS = -I./libburn -I./libisofs -I./libisoburn -I./xorriso + +# No readline in the vanilla version because the necessary headers +# are in a separate readline-development package. +xorriso_xorriso_CFLAGS = -DXorriso_standalonE -DXorriso_with_maiN $(READLINE_DEF) + +xorriso_xorriso_LDADD = $(THREAD_LIBS) + + +# This looks quite ugly with make install: xorriso.c is compiled twice again +# +# Trying to create a build timestamp file +# +# BUILT_SOURCES = xorriso/xorriso_buildstamp.h +# phony targets get rebuilt every time +# .PHONY: xorriso/xorriso_buildstamp.h +# xorriso/xorriso_buildstamp.h: +# date -u '+#define Xorriso_build_timestamP "%Y.%m.%d.%H%M%S"' >xorriso/xorriso_buildstamp.h +# cat xorriso/xorriso_buildstamp.h + + +xorriso_xorriso_SOURCES = \ + \ + xorriso/xorriso.h \ + xorriso/xorriso_private.h \ + xorriso/xorriso.c \ + xorriso/xorrisoburn.h \ + xorriso/xorrisoburn.c \ + xorriso/xorriso_timestamp.h \ + xorriso/xorriso_buildstamp.h \ + \ + libisoburn/libisoburn.h \ + libisoburn/isoburn.h \ + libisoburn/isoburn.c \ + libisoburn/isofs_wrap.c \ + libisoburn/burn_wrap.c \ + libisoburn/data_source.c \ + \ + libisofs/builder.h \ + libisofs/builder.c \ + libisofs/error.h \ + libisofs/node.h \ + libisofs/node.c \ + libisofs/tree.h \ + libisofs/tree.c \ + libisofs/image.h \ + libisofs/image.c \ + libisofs/iso1999.h \ + libisofs/iso1999.c \ + libisofs/fsource.h \ + libisofs/fsource.c \ + libisofs/fs_local.c \ + libisofs/fs_image.h \ + libisofs/fs_image.c \ + libisofs/messages.h \ + libisofs/messages.c \ + libisofs/libiso_msgs.h \ + libisofs/libiso_msgs.c \ + libisofs/stream.h \ + libisofs/stream.c \ + libisofs/util.h \ + libisofs/util.c \ + libisofs/util_rbtree.c \ + libisofs/util_htable.c \ + libisofs/filesrc.h \ + libisofs/filesrc.c \ + libisofs/ecma119.h \ + libisofs/ecma119.c \ + libisofs/ecma119_tree.h \ + libisofs/ecma119_tree.c \ + libisofs/writer.h \ + libisofs/buffer.c \ + libisofs/rockridge.h \ + libisofs/rockridge.c \ + libisofs/rockridge_read.c \ + libisofs/joliet.h \ + libisofs/joliet.c \ + libisofs/eltorito.h \ + libisofs/eltorito.c \ + libisofs/data_source.c \ + libisofs/find.c \ + libisofs/filter.h \ + libisofs/filter.c \ + libisofs/filters/xor_encrypt.c \ + libisofs/system_area.h \ + libisofs/system_area.c \ + libisofs/make_isohybrid_mbr.c \ + \ + libburn/async.c \ + libburn/async.h \ + libburn/back_hacks.h \ + libburn/cleanup.c \ + libburn/cleanup.h \ + libburn/crc.c \ + libburn/crc.h \ + libburn/debug.c \ + libburn/debug.h \ + libburn/drive.c \ + libburn/drive.h \ + libburn/error.h \ + libburn/file.c \ + libburn/file.h \ + libburn/init.c \ + libburn/init.h \ + libburn/lec.c \ + libburn/lec.h \ + libburn/libburn.h \ + libburn/libdax_audioxtr.h \ + libburn/libdax_audioxtr.c \ + libburn/libdax_msgs.h \ + libburn/libdax_msgs.c \ + libburn/mmc.c \ + libburn/mmc.h \ + libburn/null.c \ + libburn/null.h \ + libburn/options.c \ + libburn/options.h \ + libburn/os.h \ + libburn/read.c \ + libburn/read.h \ + libburn/sbc.c \ + libburn/sbc.h \ + libburn/sector.c \ + libburn/sector.h \ + libburn/sg.c \ + libburn/sg.h \ + libburn/source.h \ + libburn/source.c \ + libburn/spc.c \ + libburn/spc.h \ + libburn/structure.c \ + libburn/structure.h \ + libburn/toc.c \ + libburn/toc.h \ + libburn/transport.h \ + libburn/util.c \ + libburn/util.h \ + libburn/write.c \ + libburn/write.h \ + \ + version.h + +noinst_PROGRAMS = \ + test/compare_file + +# A program to compare two trees of files in mounted filesystems +# To compare tree /media/dvd and /original/dir : +# find /media/dvd -exec test/compare_file '{}' /media/dvd /original/dir ';' +# +test_compare_file_CPPFLAGS = +test_compare_file_CFLAGS = +test_compare_file_LDADD = +test_compare_file_SOURCES = test/compare_file.c + + +# Install symbolic links to the xorriso binary +# +install-exec-hook: + if test -e "$(DESTDIR)$(bindir)"/xorrisofs ; then rm "$(DESTDIR)$(bindir)"/xorrisofs ; else echo ; fi + ln -s xorriso "$(DESTDIR)$(bindir)"/xorrisofs + if test -e "$(DESTDIR)$(bindir)"/osirrox ; then rm "$(DESTDIR)$(bindir)"/osirrox ; else echo ; fi + ln -s xorriso "$(DESTDIR)$(bindir)"/osirrox + if test -e "$(DESTDIR)$(bindir)"/xorrecord ; then rm "$(DESTDIR)$(bindir)"/xorrecord ; else echo ; fi + ln -s xorriso "$(DESTDIR)$(bindir)"/xorrecord + + + +# Alternative to the disabled .PHONY above. +# Trying to create a build timestamp file semi-manually: make buildstamped +# +buildstamp: + date -u '+#define Xorriso_build_timestamP "%Y.%m.%d.%H%M%S"' >xorriso/xorriso_buildstamp.h + cat xorriso/xorriso_buildstamp.h + +# For now make buildstamped has to be performed manually. +buildstamped: buildstamp + make + + +## ========================================================================= ## + +# Indent source files +indent_files = + + +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 = \ + xorriso.pc + +man_MANS = xorriso/xorriso.1 + +EXTRA_DIST = \ + xorriso.pc.in \ + version.h.in \ + README \ + AUTHORS \ + CONTRIBUTORS \ + COPYRIGHT \ + COPYING \ + INSTALL \ + xorriso/changelog.txt \ + xorriso/xorriso_buildstamp_none.h \ + $(man_MANS) + + diff --git a/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_pc_in.txt b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_pc_in.txt new file mode 100644 index 00000000..5e35e873 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_pc_in.txt @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: xorriso +Description: ISO 9660 filesystem image manipulator +Version: @VERSION@ +Requires: +Libs: -L${libdir} -lpthread +Cflags: + diff --git a/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_private.h b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_private.h new file mode 100644 index 00000000..36984045 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_private.h @@ -0,0 +1,840 @@ + +/* Command line oriented batch and dialog tool which creates, loads, + manipulates and burns ISO 9660 filesystem images. + + Copyright 2007-2008 Thomas Schmitt, + + Provided under GPL version 2. + + This file contains inner declarations of xorriso. + The public interface is in xorriso.h +*/ + + +/* For now, #ifdef Xorriso_is_xorriso_selF has no meaning. + But it is already now to be set only by the xorriso.c module. +*/ + +#ifndef Xorriso_private_includeD +#define Xorriso_private_includeD yes + +#define Xorriso_program_versioN "0.3.1" + +/** The source code release timestamp */ +#include "xorriso_timestamp.h" +#ifndef Xorriso_timestamP +#define Xorriso_timestamP "-none-given-" +#endif + +/** The binary build timestamp is to be set externally by the compiler + or by a macro definition in xorriso_buildstamp.h. +*/ +#include "xorriso_buildstamp.h" +#ifndef Xorriso_build_timestamP +#define Xorriso_build_timestamP "-none-given-" +#endif + +#include + + +#define Smem_malloC malloc +#define Smem_freE free +#define SfileadrL 4096 + +struct LinkiteM; /* Trace of hops during symbolic link resolution */ +struct ExclusionS; /* List of -not_* conditions */ +struct PermiteM; /* Stack of temporarily altered access permissions */ +struct SpotlisT; /* List of intervals with different read qualities */ +struct CheckmediajoB; /* Parameters for Xorriso_check_media() */ +struct SectorbitmaP; /* Distiniction between valid and invalid sectors */ + + +/* maximum number of history lines to be reported with -status:long_history */ +#define Xorriso_status_history_maX 100 + +/* <<< ??? */ +/* try to catch signals and ignore them during abort handling */ +#define Xorriso_abort_handler_defaulT (1|(2<<4)) + + +/** The list of startup file names */ +#define Xorriso_rc_nuM 4 + + +/* Default setting for the size limit of single data files: + 100 extents with 4 GB - 2 kB each = 400 GB - 200 kB +*/ +#define Xorriso_default_file_size_limiT \ + (((off_t) 400) * ((off_t) 1024*1024*1024) - (off_t) 204800) + + +struct XorrisO { /* the global context of xorriso */ + + int libs_are_started; + + /* source */ + char progname[SfileadrL]; + char initial_wdx[SfileadrL]; + int no_rc; + + /* Command line argument emulations: + 0=xorriso mode + 1=mkisofs mode + 2=cdrecord mode + */ + int argument_emulation; + + /** List of startupfiles */ + char rc_filenames[Xorriso_rc_nuM][SfileadrL]; + int rc_filename_count; + + char wdi[SfileadrL]; + char wdx[SfileadrL]; + int did_something_useful; + + int add_plainly; + off_t split_size; + + char list_delimiter[81]; + + /* >>> put libisofs aspects here <<< */ + + int do_joliet; + int relax_compliance; /* opaque bitfield to be set by xorrisoburn */ + int do_follow_pattern; + int do_follow_param; + int do_follow_links; + int follow_link_limit; + int do_follow_mount; + int do_global_uid; + uid_t global_uid; + int do_global_gid; + gid_t global_gid; + int do_global_mode; + mode_t global_dir_mode; + mode_t global_file_mode; + + int do_overwrite; /* 0=off, 1=on, 2=nondir */ + int do_reassure; /* 0=off, 1=on, 2=tree */ + + char volid[33]; + int volid_default; + char loaded_volid[33]; + char assert_volid[SfileadrL]; + char assert_volid_sev[80]; + + char publisher[129]; + char application_id[129]; + + char session_logfile[SfileadrL]; + int session_lba; + int session_blocks; + + /* >>> put libburn/isoburn aspects here */ + + struct Xorriso_lsT *drive_blacklist; + struct Xorriso_lsT *drive_greylist; + struct Xorriso_lsT *drive_whitelist; + + int toc_emulation_flag; /* bit0= bit3 for isoburn_drive_aquire() + scan -ROM profiles for ISO sessions + bit1= bit4 for isoburn_drive_aquire() + do not emulate TOC on overwriteable media + */ + + int image_start_mode; /* From what address to load the ISO image + bit0-15= addressing mode + 0= automatic lba as deduced from media + 1= value is session number + 2= value is track number + 3= value is lba + bit16= with mode 3 : value is possibly 16 too high. + Let isoburn_set_msc1() adjust it. + bit30= interference with normal msc1 processing + is enabled. Without this bit, + isoburn_set_msc1() will not be called. + bit31= image loading has happened, + setting is kept for rollback only. + Always apply as 0=auto. + */ + char image_start_value[81]; /* value according image_start_mode */ + + char indev[SfileadrL]; + void *in_drive_handle; /* interpreted only by xorrisoburn.c */ + void *in_volset_handle; /* interpreted only by xorrisoburn.c */ + char *in_charset; /* The charset to interpret the filename bytes */ + + int volset_change_pending; /* whether -commit would make sense */ + int no_volset_present; /* set to 1 on first failure */ + + struct CheckmediajoB *check_media_default; + struct SectorbitmaP *in_sector_map; /* eventual sector validity bitmap */ + + + char outdev[SfileadrL]; + void *out_drive_handle; /* interpreted only by xorrisoburn.c */ + char *out_charset; /* The charset to produce the filename bytes for */ + int dev_fd_1; /* The fd which substitutes for /dev/fd/1 and is + connected to externaly perveived stdout. + */ + + int grow_blindly_msc2; /* if >= 0 this causes growing from drive to drive. + The value is used as block address offset for + image generation. Like in: mkisofs -C msc1,msc2 + */ + + int ban_stdio_write; + int do_dummy; + int do_close; + int speed; /* in libburn units : 1000 bytes/second , 0 = Max, -1 = Min */ + int fs; /* fifo size in 2048 byte chunks : at most 1 GB */ + int padding; /* number of bytes to add after ISO 9660 image */ + + int alignment; /* if > 0 : image size alignment in 2048 byt blocks */ + /* <<< not sure whether to keep this after libisofs will have + learned to pad up MBR images to full MB */ + + int do_stream_recording; + + int keep_boot_image; + int patch_isolinux_image; + char boot_image_bin_path[SfileadrL]; + int boot_image_emul; /* 0=no emulation + (1=emulation as hard disk) + (2=emulation as floppy) + */ + char boot_image_cat_path[SfileadrL]; + off_t boot_image_load_size; + int boot_image_isohybrid; /* 0=off , 1=auto , 2=on , 3=force */ + + /* LBA of boot image after image loading */ + int loaded_boot_bin_lba; + /* Path of the catalog node after image loading */ + char loaded_boot_cat_path[SfileadrL]; + + /* XORRISO options */ + int allow_graft_points; + + int allow_restore; /* 0= disallowed, 1=allowed, 2=device files allowed */ + int do_concat_split; /* 1= restore complete split file directories as + regular files + */ + int do_auto_chmod; /* 1= eventually temporarily open access permissions + of self-owned directories during restore + */ + + int dialog; /* 0=off , 1=single-line , 2=multi-line */ + + int bsl_interpretation; + /* whether to run input through Sfile_bsl_interpreter(): + bit0-1= dialog and quoted file reading + 0= no interpretation, leave unchanged + 1= only inside double quotes + 2= outside single quotes + 3= everywhere + bit2-3= reserved as future expansion of bit0-1 + bit4= interpretation within program start arguments + bit5= perform backslash encoding with results + bit6= perform backslash encoding with info texts + */ + + /* Pattern matching facility. It still carries legacy from scdbackup/askme.c + but is fully functional for xorriso. + */ + int search_mode; + /* 0= start text + 1= fgrep , + 2= regular expression + 3= (eventually structured) shell parser expression + 4= shell parser expression for leaf name + */ + + int structured_search; + /* 0= flat text search + 1= '/' is a significant separator that cannot be matched by wildcards + ( 2= like 1 : but report only occurence in tree, no payload, no location ) + ( 3= like 2 : but report first content level of matching directories ) + 4= actually not structured but unique find mode (with search_mode 4) + */ + + int do_iso_rr_pattern; /* 0=off, 1=on, 2=ls */ + int do_disk_pattern; /* 0=off, 1=on, 2=ls */ + + int temp_mem_limit; + + off_t file_size_limit; + + struct ExclusionS *disk_exclusions; + int disk_excl_mode; /* bit0= on (else off) + bit1= parameter too (else rekursion only) + bit2= whole subtree banned (else only exact path) + bit3= when comparing ignore excluded files rather + than to treat them as truely missing on disk + */ + + int use_stdin; /* use raw stdin even if readline support is compiled */ + int result_page_length; + int result_page_width; + char mark_text[SfileadrL]; /* ( stdout+stderr, M: ) */ + int packet_output; + char logfile[4][SfileadrL]; + FILE *logfile_fp[4]; + FILE *pktlog_fp; + struct Xorriso_lsT *result_msglists[Xorriso_max_outlist_stacK]; + struct Xorriso_lsT *info_msglists[Xorriso_max_outlist_stacK]; + int msglist_flags[Xorriso_max_outlist_stacK]; /* bit0= result is redirected + bit1= info is redirected + */ + int msglist_stackfill; + + int status_history_max; /* for -status long_history */ + + + char report_about_text[20]; + int report_about_severity; + int library_msg_direct_print; + char abort_on_text[20]; + int abort_on_severity; /* A severity rank number as threshold */ + int problem_status; /* Severity rank number. 0= no abort condition present */ + char problem_status_text[20]; + + char errfile_log[SfileadrL]; /* for -errfile_log */ + int errfile_mode; /* bit0= marked */ + FILE *errfile_fp; + + int img_read_error_mode; /* 0=best_effort , 1=failure , 2=fatal */ + int extract_error_mode; /* 0=best_effort , 1=keep , 2=delete */ + + char return_with_text[20]; + int return_with_severity; + int return_with_value; + int eternal_problem_status; + char eternal_problem_status_text[20]; + + /* temporary search facilities */ + regex_t *re; + regmatch_t match[1]; + char **re_constants; + int re_count; + int re_fill; + char reg_expr[2*SfileadrL]; + + /* run state */ + int run_state; /* 0=preparing , 1=writing image */ + int is_dialog; + int bar_is_fresh; + char pending_option[SfileadrL]; /* eventual option entered at page prompt */ + int request_to_abort; /* abort a single operation like -ls, not the program */ + int request_not_to_ask; /* suppress reassure and pager */ + double idle_time; + int re_failed_at; /* mismatch position with structured_search */ + int prepended_wd; + double insert_count; + double insert_bytes; + double error_count; /* double will not roll over */ + + /* pacifiers */ + int pacifier_style; /* 0= xorriso, 1=mkisofs 2=cdrecord */ + double pacifier_interval; + double start_time; + double last_update_time; + /* optional global counters for brain reduced callback functions */ + off_t pacifier_count; + off_t pacifier_total; + off_t pacifier_byte_count; /* auxiliary counter for data bytes */ + + void *pacifier_fifo; + + int find_compare_result; /* 1=everything matches , 0=mismatch , -1=error */ + + struct PermiteM *perm_stack; /* Temporarily altered dir access permissions */ + + /* result (stdout, R: ) */ + char result_line[10*SfileadrL]; + int result_line_counter; + int result_page_counter; + int result_open_line_len; + + + /* info (stderr, I:) */ + char info_text[10*SfileadrL]; + +}; + + +int Xorriso_prepare_regex(struct XorrisO *xorriso, char *adr, int flag); + +int Xorriso_result(struct XorrisO *xorriso, int flag); + +int Xorriso_info(struct XorrisO *xorriso, int flag); + +int Xorriso_request_confirmation(struct XorrisO *xorriso, int flag); + +int Xorriso_prescan_args(struct XorrisO *xorriso, int argc, char **argv, + int flag); + +int Xorriso_execute_option(struct XorrisO *xorriso, char *line, int flag); + +/* @return 0=match , else no match +*/ +int Xorriso_regexec(struct XorrisO *xorriso, char *to_match, int *failed_at, + int flag); + +int Xorriso_prepare_expansion_pattern(struct XorrisO *xorriso, char *pattern, + int flag); + +int Xorriso__mode_to_perms(mode_t st_mode, char perms[10], int flag); + +int Xorriso_much_too_long(struct XorrisO *xorriso, int len, int flag); + +int Xorriso_check_temp_mem_limit(struct XorrisO *xorriso, off_t mem, int flag); + +int Xorriso_eval_nonmatch(struct XorrisO *xorriso, char *pattern, + int *nonconst_mismatches, off_t *mem, int flag); + +/* @param flag bit0= a match count !=1 is a SORRY event +*/ +int Xorriso_check_matchcount(struct XorrisO *xorriso, + int count, int nonconst_mismatches, int num_patterns, + char **patterns, int flag); + +int Xorriso_no_pattern_memory(struct XorrisO *xorriso, off_t mem, int flag); + +int Xorriso_alloc_pattern_mem(struct XorrisO *xorriso, off_t mem, + int count, char ***filev, int flag); + +/* @param flag bit0= count results rather than storing them + @return <=0 error , 1 is root (end processing) , + 2 is not root (go on processing) +*/ +int Xorriso_check_for_root_pattern(struct XorrisO *xorriso, + int *filec, char **filev, int count_limit, off_t *mem, int flag); + +/* @param flag bit0= prepend wd only if name does not begin by '/' + bit2= prepend wd (automatically done if wd[0]!=0) +*/ +int Xorriso_make_abs_adr(struct XorrisO *xorriso, char *wd, char *name, + char adr[], int flag); + +/* @param flag bit0= count result rather than storing it + bit1= unexpected change of number is a FATAL event +*/ +int Xorriso_register_matched_adr(struct XorrisO *xorriso, + char *adr, int count_limit, + int *filec, char **filev, off_t *mem, int flag); + +int Xorriso_format_ls_l(struct XorrisO *xorriso, struct stat *stbuf, int flag); + +/* @param flag bit0= simple readlink(): no normalization, no multi-hop +*/ +int Xorriso_resolve_link(struct XorrisO *xorriso, + char *link_path, char result_path[SfileadrL], int flag); + +/* @param flag bit0= for Xorriso_msgs_submit: use pager +*/ +int Xorriso_hop_link(struct XorrisO *xorriso, char *link_path, + struct LinkiteM **link_stack, struct stat *stbuf, int flag); + +/* reg_expr should be twice as large as bourne_expr ( + 2 to be exact) */ +/* return: 2= bourne_expr is surely a constant */ +int Xorriso__bourne_to_reg(char bourne_expr[], char reg_expr[], int flag); + +int Xorriso_no_malloc_memory(struct XorrisO *xorriso, char **to_free, + int flag); + +int Xorriso_pacifier_reset(struct XorrisO *xorriso, int flag); + +/* This call is to be issued by long running workers in short intervals. + It will check whether enough time has elapsed since the last pacifier + message and eventually issue an update message. + @param what_done A sparse description of the action, preferrably in past + tense. E.g. "done" , "files added". + @param count The number of objects processed so far. + Is ignored if <=0. + @param todo The number of objects to be done in total. + Is ignored if <=0. + @param current_object A string telling the object currently processed. + Ignored if "". + @param flag bit0= report unconditionally, no time check +*/ +int Xorriso_pacifier_callback(struct XorrisO *xorriso, char *what_done, + off_t count, off_t todo, char *current_object, + int flag); + +/* @param boss_iter Opaque handle to be forwarded to actions in ISO image + Set to NULL if calling this function from outside ISO world + @param flag bit0= update rather than compare +*/ +int Xorriso_find_compare(struct XorrisO *xorriso, void *boss_iter, + char *iso_path, char *iso_prefix, char *disk_prefix, + int flag); + +/* @param boss_iter Opaque handle to be forwarded to actions in ISO image + Set to NULL if calling this function from outside ISO world +*/ +int Xorriso_update_interpreter(struct XorrisO *xorriso, void *boss_iter, + int compare_result, char *disk_path, + char *iso_rr_path, int flag); + +int Xorriso_path_is_excluded(struct XorrisO *xorriso, char *path, int flag); + +/* @param flag bit0= long format + bit1= do not print count of nodes + bit2= du format + bit3= print directories as themselves (ls -d) +*/ +int Xorriso_lsx_filev(struct XorrisO *xorriso, char *wd, + int filec, char **filev, off_t boss_mem, int flag); + +/* + @param flag >>> bit0= remove whole sub tree: rm -r + bit1= remove empty directory: rmdir + bit2= recursion: do not reassure in mode 2 "tree" + bit3= this is for overwriting and not for plain removal + bit4= count deleted files in xorriso->pacifier_count + bit5= with bit0 only remove directory content, not the directory + @return <=0 = error + 1 = removed leaf file object + 2 = removed directory or tree + 3 = did not remove on user revocation +*/ +int Xorriso_rmx(struct XorrisO *xorriso, off_t boss_mem, char *path, int flag); + + +int Xorriso_make_tmp_path(struct XorrisO *xorriso, char *orig_path, + char *tmp_path, int *fd, int flag); + +/* @param flag bit0= path is a directory + bit2= recursion: do not reassure in mode 2 "tree" + bit3= this is for overwriting and not for plain removal +*/ +int Xorriso_reassure_restore(struct XorrisO *xorriso, char *path, int flag); + + +int Xorriso_auto_chmod(struct XorrisO *xorriso, char *disk_path, int flag); + +int Xorriso_protect_stdout(struct XorrisO *xorriso, int flag); + + +/* @param flag bit0= mark untested areas as valid +*/ +int Xorriso_spotlist_to_sectormap(struct XorrisO *xorriso, + struct SpotlisT *spotlist, + int read_chunk, + struct SectorbitmaP **map, + int flag); + +int Xorriso_toc_to_string(struct XorrisO *xorriso, char **toc_text, int flag); + + +/* @param flag bit0+1= what to aquire after giving up outdev + 0=none, 1=indev, 2=outdev, 3=both +*/ +int Xorriso_reaquire_outdev(struct XorrisO *xorriso, int flag); + + +struct Xorriso_lsT { + char *text; + struct Xorriso_lsT *prev,*next; +}; + +/** Create a new list item with arbitrary byte content. + @param lstring The newly created object or NULL on failure + @param data An array of bytes to be copied into the new object + @param data_len Number of bytes to be copied + @param link Xorriso_lsT object to which the new object shall be linked + @param flag Bitfield for control purposes + bit0= insert before link rather than after it + bit1= do not copy data (e.g. because *data is invalid) + @return <=0 error, 1 ok +*/ +int Xorriso_lst_new_binary(struct Xorriso_lsT **lstring, char *data, + int data_len, struct Xorriso_lsT *link, int flag); + + +/** Create a new list item with a 0-terminated text as content. + @param lstring The newly created object or NULL on failure + @param text A 0-terminated array of bytes + @param link Xorriso_lsT object to which the new object shall be linked + @param flag Bitfield for control purposes + bit0= insert before link rather than after it + @return <=0 error, 1 ok +*/ +int Xorriso_lst_new(struct Xorriso_lsT **lstring, char *text, + struct Xorriso_lsT *link, int flag); + + +/** Create a new list item at the end of a given list. + @param lstring Contains as input a pointer to a pointer to any existing + list item. As output this list item pointer will be + changed to the address of the new list item. + @param data An array of bytes to be copied into the new object + @param data_len Number of bytes to be copied + @param flag unused yet, submit 0 + @return <=0 error, 1 ok +*/ +int Xorriso_lst_append_binary(struct Xorriso_lsT **entry, + char *data, int data_len, int flag); + + +/** Destroy a single list item and connect its eventual list neighbors. + @param lstring pointer to the pointer to be freed and set to NULL + @param flag unused yet, submit 0 + @return 0= *lstring was alredy NULL, 1= ok +*/ +int Xorriso_lst_destroy(struct Xorriso_lsT **lstring, int flag); + + +/* Opens the -check_media data copy in for reading and writing +*/ +int Xorriso_open_job_data_to(struct XorrisO *xorriso, + struct CheckmediajoB *job, int flag); + +int Xorriso_no_findjob(struct XorrisO *xorriso, char *cmd, int flag); + + +int Xorriso_make_mount_cmd(struct XorrisO *xorriso, char *cmd, + int lba, int track, int session, char *volid, + char *devadr, char result[SfileadrL], int flag); + + +/* @param flag bit0= use env_path to find the desired program +*/ +int Xorriso_execv(struct XorrisO *xorriso, char *cmd, char *env_path, + int *status, int flag); + +int Xorriso_is_in_patternlist(struct XorrisO *xorriso, + struct Xorriso_lsT *patternlist, char *path, int flag); + +char *Xorriso_get_pattern(struct XorrisO *xorriso, + struct Xorriso_lsT *patternlist, int index, int flag); + + +int Sfile_str(char target[SfileadrL], char *source, int flag); + +double Sfile_microtime(int flag); + +int Sfile_add_to_path(char path[SfileadrL], char *addon, int flag); + +int Sfile_scale(double value, char *result, int siz, double thresh, int flag); + +int Sfile_destroy_argv(int *argc, char ***argv, int flag); + +/* + bit0= do not ignore trailing slash + bit1= do not ignore empty components (other than the empty root name) +*/ +int Sfile_count_components(char *path, int flag); + +/* + @param flag + bit0= return -1 if file is missing + bit1= return a hardlink with siblings as type 5 + bit2= evaluate eventual link target rather than the link object itself + bit3= return a socket or a char device as types 7 or 8 rather than 0 + @return + 0=unknown + 1=regular + 2=directory + 3=symbolic link + 4=named pipe + 5=multiple hardlink (with bit1) + 6=block device + 7=socket (with bit3) + 8=character device (with bit3) +*/ +int Sfile_type(char *filename, int flag); + + + +char *Text_shellsafe(char *in_text, char *out_text, int flag); + +int Sort_argv(int argc, char **argv, int flag); + +/* @param flag bit0= single letters */ +char *Ftypetxt(mode_t st_mode, int flag); + +/* @param flag bit0=with year and seconds + bit1=timestamp format YYYY.MM.DD.hhmmss +*/ +char *Ftimetxt(time_t t, char timetext[40], int flag); + +int System_uname(char **sysname, char **release, char **version, + char **machine, int flag); + + +struct DirseQ; + +int Dirseq_new(struct DirseQ **o, char *adr, int flag); + +int Dirseq_destroy(struct DirseQ **o, int flag); + +int Dirseq_next_adr(struct DirseQ *o, char reply[SfileadrL], int flag); + + +int Linkitem_reset_stack(struct LinkiteM **o, struct LinkiteM *to, int flag); + + +struct FindjoB; + + +int Findjob_new(struct FindjoB **o, char *start_path, int flag); + +int Findjob_destroy(struct FindjoB **job, int flag); + + +/* @return 0=no match , 1=match , <0 = error +*/ +int Findjob_test(struct FindjoB *job, char *name, + struct stat *boss_stbuf, struct stat *stbuf, + int depth, int flag); + +/* @return <0 error, >=0 see xorriso.c struct FindjoB.action +*/ +int Findjob_get_action(struct FindjoB *o, int flag); + +/* @return <0 error, >=0 see xorriso.c struct FindjoB.action +*/ +int Findjob_get_action_parms(struct FindjoB *o, char **target, + uid_t *user, gid_t *group, + mode_t *mode_and, mode_t *mode_or, + int *type, time_t *date, struct FindjoB **subjob, + int flag); + +/* @param flag bit0= recursive +*/ +int Findjob_set_action_target(struct FindjoB *o, int action, char *target, + int flag); + +/* @param flag bit0= recursive +*/ +int Findjob_set_action_chgrp(struct FindjoB *o, gid_t group, int flag); + +/* @param flag bit0= recursive +*/ +int Findjob_set_action_chmod(struct FindjoB *o, + mode_t mode_and, mode_t mode_or, int flag); + +/* @param flag bit0= recursive +*/ +int Findjob_set_action_ad(struct FindjoB *o, int type, time_t date, int flag); + +int Findjob_set_start_path(struct FindjoB *o, char *start_path, int flag); + +int Findjob_set_action_found_path(struct FindjoB *o, int flag); + +int Findjob_get_start_path(struct FindjoB *o, char **start_path, int flag); + +int Findjob_set_lba_range(struct FindjoB *o, int start_lba, int count, + int flag); + +int Findjob_get_lba_damage_filter(struct FindjoB *o, int *start_lba, + int *end_lba, int *damage_filter, int flag); + +int Findjob_get_commit_filter(struct FindjoB *o, int *commit_filter, int flag); + +int Findjob_set_wanted_node(struct FindjoB *o, void *wanted_node, int flag); + +int Findjob_get_wanted_node(struct FindjoB *o, void **wanted_node, int flag); + +int Findjob_set_found_path(struct FindjoB *o, char *path, int flag); + +int Findjob_get_found_path(struct FindjoB *o, char **path, int flag); + + +struct SplitparT; + +int Splitparts_new(struct SplitparT **o, int count, int flag); + +int Splitparts_destroy(struct SplitparT **o, int count, int flag); + +int Splitparts_set(struct SplitparT *o, int idx, + char *name, int partno, int total_parts, + off_t offset, off_t bytes, off_t total_bytes, int flag); + +int Splitparts_get(struct SplitparT *o, int idx, char **name, int *partno, + int *total_parts, off_t *offset, off_t *bytes, + off_t *total_bytes, int flag); + +int Splitpart__parse(char *name, int *partno, int *total_parts, + off_t *offset, off_t *bytes, off_t *total_bytes, int flag); + +int Splitpart__compose(char *adr, int partno, int total_parts, + off_t offset, off_t bytes, off_t total_bytes, int flag); + +int Splitparts_sort(struct SplitparT *o, int count, int flag); + + +int Permstack_push(struct PermiteM **o, char *disk_path, struct stat *stbuf, + int flag); + +int Permstack_pop(struct PermiteM **o, struct PermiteM *stopper, + struct XorrisO *xorriso, int flag); + + +int Spotlist_new(struct SpotlisT **o, int flag); + +int Spotlist_destroy(struct SpotlisT **o, int flag); + +int Spotlist_add_item(struct SpotlisT *o, int start_lba, int blocks, + int quality, int flag); + +int Spotlist_count(struct SpotlisT *o, int flag); + +int Spotlist_block_count(struct SpotlisT *o, int flag); + +int Spotlist_sector_size(struct SpotlisT *o, int read_chunk, int flag); + +int Spotlist_get_item(struct SpotlisT *o, int idx, + int *start_lba, int *blocks, int *quality, int flag); + +char *Spotlist__quality_name(int quality, char name[80], int flag); + + +#define Xorriso_read_quality_gooD 0x7fffffff +#define Xorriso_read_quality_sloW 0x60000000 +#define Xorriso_read_quality_partiaL 0x50000000 +#define Xorriso_read_quality_valiD 0x40000000 +#define Xorriso_read_quality_untesteD 0x3fffffff +#define Xorriso_read_quality_invaliD 0x3ffffffe +#define Xorriso_read_quality_tao_enD 0x28000000 +#define Xorriso_read_quality_off_tracK 0x20000000 +#define Xorriso_read_quality_unreadablE 0x00000000 + + +int Checkmediajob_new(struct CheckmediajoB **o, int flag); + +int Checkmediajob_destroy(struct CheckmediajoB **o, int flag); + +int Checkmediajob_copy(struct CheckmediajoB *from, struct CheckmediajoB *to, + int flag); + +int Sectorbitmap_new(struct SectorbitmaP **o, int sectors, int sector_size, + int flag); +int Sectorbitmap_destroy(struct SectorbitmaP **o, int flag); +int Sectorbitmap_from_file(struct SectorbitmaP **o, char *path, char *msg, + int *os_errno, int flag); +int Sectorbitmap_to_file(struct SectorbitmaP *o, char *path, char *info, + char *msg, int *os_errno, int flag); +int Sectorbitmap_set(struct SectorbitmaP *o, int sector, int flag); +int Sectorbitmap_set_range(struct SectorbitmaP *o, + int start_sector, int sectors, int flag); +int Sectorbitmap_is_set(struct SectorbitmaP *o, int sector, int flag); +int Sectorbitmap_bytes_are_set(struct SectorbitmaP *o, + off_t start_byte, off_t end_byte, int flag); + +int Sectorbitmap_get_layout(struct SectorbitmaP *o, + int *sectors, int *sector_size, int flag); + +int Sectorbitmap_copy(struct SectorbitmaP *from, struct SectorbitmaP *to, + int flag); + +/* bit0= append (text!=NULL) */ +int Sregex_string(char **handle, char *text, int flag); + +/* @param flag bit0= only test expression whether compilable +*/ +int Sregex_match(char *pattern, char *text, int flag); + +#endif /* Xorriso_private_includeD */ + diff --git a/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_timestamp.h b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_timestamp.h new file mode 100644 index 00000000..254e07cc --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/xorriso/xorriso_timestamp.h @@ -0,0 +1 @@ +#define Xorriso_timestamP "2008.12.21.101705" diff --git a/libisoburn/branches/ZeroThreeTwo/xorriso/xorrisoburn.c b/libisoburn/branches/ZeroThreeTwo/xorriso/xorrisoburn.c new file mode 100644 index 00000000..1dd08f3d --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/xorriso/xorrisoburn.c @@ -0,0 +1,8723 @@ + + +/* Adapter to libisoburn, libisofs and libburn for xorriso, + a command line oriented batch and dialog tool which creates, loads, + manipulates and burns ISO 9660 filesystem images. + + Copyright 2007-2008 Thomas Schmitt, + + Provided under GPL version 2. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* for -charset */ +#include +#include + + +/* ------------------------------------------------------------------------ */ + +#ifndef Xorriso_standalonE + +/* The library which does the ISO 9660 / RockRidge manipulations */ +#include + +/* The library which does MMC optical drive operations */ +#include + +/* The library which enhances overwriteable media with ISO 9660 multi-session + capabilities via the method invented by Andy Polyakov for growisofs */ +#include + +/* The official xorriso options API. "No shortcuts" */ +#include "xorriso.h" + +/* The inner description of XorrisO */ +#include "xorriso_private.h" + +/* The inner isofs- and burn-library interface */ +#include "xorrisoburn.h" + +#else /* ! Xorriso_standalonE */ + +#include "../libisofs/libisofs.h" +#include "../libburn/libburn.h" +#include "../libisoburn/libisoburn.h" +#include "xorriso.h" +#include "xorriso_private.h" +#include "xorrisoburn.h" + +#endif /* Xorriso_standalonE */ + +/* Some private in advance declarations */ +int Xorriso_pacifier_loop(struct XorrisO *xorriso, struct burn_drive *drive, + int flag); + +int Xorriso__read_pacifier(IsoImage *image, IsoFileSource *filesource); + +int Xorriso_tree_graft_node(struct XorrisO *xorriso, IsoImage *volume, + IsoDir *dir, char *disk_path, char *img_name, + char *nominal_source, char *nominal_target, + off_t offset, off_t cut_size, + IsoNode **node, int flag); + +int Xorriso_findi_iter(struct XorrisO *xorriso, IsoDir *dir_node, off_t *mem, + IsoDirIter **iter, + IsoNode ***node_array, int *node_count, int *node_idx, + IsoNode **iterated_node, int flag); + +int Xorriso__file_start_lba(IsoNode *node, int *lba, int flag); + +int Xorriso_read_file_data(struct XorrisO *xorriso, IsoNode *node, + char *img_path, char *disk_path, + off_t img_offset, off_t disk_offset, + off_t bytes, int flag); + +int Xorriso_node_from_path(struct XorrisO *xorriso, IsoImage *volume, + char *path, IsoNode **node, int flag); + +int Xorriso_path_from_node(struct XorrisO *xorriso, IsoNode *node, int lba, + char path[SfileadrL], int flag); + + +#define LIBISO_ISDIR(node) (iso_node_get_type(node) == LIBISO_DIR) +#define LIBISO_ISREG(node) (iso_node_get_type(node) == LIBISO_FILE) +#define LIBISO_ISLNK(node) (iso_node_get_type(node) == LIBISO_SYMLINK) +#define LIBISO_ISCHR(node) (iso_node_get_type(node) == LIBISO_SPECIAL && \ + S_ISCHR(iso_node_get_mode(node))) +#define LIBISO_ISBLK(node) (iso_node_get_type(node) == LIBISO_SPECIAL && \ + S_ISBLK(iso_node_get_mode(node))) +#define LIBISO_ISFIFO(node) (iso_node_get_type(node) == LIBISO_SPECIAL && \ + S_ISFIFO(iso_node_get_mode(node))) +#define LIBISO_ISSOCK(node) (iso_node_get_type(node) == LIBISO_SPECIAL && \ + S_ISSOCK(iso_node_get_mode(node))) +#define LIBISO_ISBOOT(node) (iso_node_get_type(node) == LIBISO_BOOT) + + +/* CD specs say one shall not write tracks < 600 kiB */ +#define Xorriso_cd_min_track_sizE 300 + + +/* Default setting for -relax_compliance */ +#define Xorriso_relax_compliance_defaulT \ + (isoburn_igopt_allow_deep_paths | isoburn_igopt_allow_longer_paths | \ + isoburn_igopt_always_gmt) + + +/* ------------------------------------------------------------------------ */ + + +int Xorriso_startup_libraries(struct XorrisO *xorriso, int flag) +{ + int ret, major, minor, micro; + char *handler_prefix= NULL; + char *queue_sev, *print_sev, reason[1024]; + + +/* First an ugly compile time check for header version compatibility. + If everthing matches, then no C code is produced. In case of mismatch, + intentionally faulty C code will be inserted. +*/ + +/* The minimum requirement of xorriso towards the libisoburn header + at compile time is defined in xorriso/xorrisoburn.h + xorriso_libisoburn_req_major + xorriso_libisoburn_req_minor + xorriso_libisoburn_req_micro + It gets compared against the version macros in libburn/libburn.h : + isoburn_header_version_major + isoburn_header_version_minor + isoburn_header_version_micro + If the header is too old then the following code shall cause failure of + cdrskin compilation rather than to allow production of a program with + unpredictable bugs or memory corruption. + The compiler messages supposed to appear in this case are: + error: 'LIBISOBURN_MISCONFIGURATION' undeclared (first use in this function) + error: 'INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libisoburn_dot_h_TOO_OLD__SEE_xorrisoburn_dot_c' undeclared (first use in this function) + error: 'LIBISOBURN_MISCONFIGURATION_' undeclared (first use in this function) +*/ +/* The indendation is an advise of man gcc to help old compilers ignoring */ + #if xorriso_libisoburn_req_major > isoburn_header_version_major + #define Isoburn_libisoburn_dot_h_too_olD 1 + #endif + #if xorriso_libisoburn_req_major == isoburn_header_version_major && xorriso_libisoburn_req_minor > isoburn_header_version_minor + #define Isoburn_libisoburn_dot_h_too_olD 1 + #endif + #if xorriso_libisoburn_req_minor == isoburn_header_version_minor && xorriso_libisoburn_req_micro > isoburn_header_version_micro + #define Isoburn_libisoburn_dot_h_too_olD 1 + #endif + +#ifdef Isoburn_libisoburn_dot_h_too_olD +LIBISOBURN_MISCONFIGURATION = 0; +INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libisoburn_dot_h_TOO_OLD__SEE_xorrisoburn_dot_c = 0; +LIBISOBURN_MISCONFIGURATION_ = 0; +#endif + +/* End of ugly compile time test (scroll up for explanation) */ + +#ifdef NIX + sprintf(xorriso->info_text, "Starting up libraries ...\n"); + Xorriso_info(xorriso, 0); +#endif + + handler_prefix= calloc(strlen(xorriso->progname)+3+1, 1); + if(handler_prefix==NULL) { + sprintf(xorriso->info_text, + "Cannot allocate memory for initializing libraries"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(-1); + } + reason[0]= 0; + ret= isoburn_initialize(reason, 0); + if(ret==0) { + sprintf(xorriso->info_text, "Cannot initialize libraries"); + if(reason[0]) + sprintf(xorriso->info_text+strlen(xorriso->info_text), + ". Reason given:\n%s", reason); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + free(handler_prefix); + return(0); + } + ret= isoburn_is_compatible(isoburn_header_version_major, + isoburn_header_version_minor, + isoburn_header_version_micro, 0); + if(ret<=0) { + isoburn_version(&major, &minor, µ); + sprintf(xorriso->info_text, + "libisoburn version too old: %d.%d.%d . Need at least: %d.%d.%d .\n", + major, minor, micro, + isoburn_header_version_major, isoburn_header_version_minor, + isoburn_header_version_micro); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(-1); + } + + xorriso->libs_are_started= 1; + + queue_sev= "ALL"; + if(xorriso->library_msg_direct_print) { + + /* >>> need option for controlling this in XorrisO. + See also Xorriso_msgs_submit */; + + print_sev= xorriso->report_about_text; + } else + print_sev= "NEVER"; + + iso_set_msgs_severities(queue_sev, print_sev, "libsofs : "); + burn_msgs_set_severities(queue_sev, print_sev, "libburn : "); + + /* ??? >>> do we want united queues ? */ + /* burn_set_messenger(iso_get_messenger()); */ + + sprintf(handler_prefix, "%s : ", xorriso->progname); + burn_set_signal_handling(handler_prefix, NULL, 0); + + Xorriso_process_msg_queues(xorriso,0); + if(reason[0]) { + sprintf(xorriso->info_text, "%s", reason); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + } + +#ifdef NIX + sprintf(xorriso->info_text, "Library startup done.\n"); + Xorriso_info(xorriso, 0); +#endif + + free(handler_prefix); + return(1); +} + + +/* @param flag bit0= global shutdown of libraries */ +int Xorriso_detach_libraries(struct XorrisO *xorriso, int flag) +{ + Xorriso_give_up_drive(xorriso, 3); + if(xorriso->in_volset_handle!=NULL) { /* standalone image */ + iso_image_unref((IsoImage *) xorriso->in_volset_handle); + xorriso->in_volset_handle= NULL; + Sectorbitmap_destroy(&(xorriso->in_sector_map), 0); + } + if(flag&1) { + if(xorriso->libs_are_started==0) + return(0); + isoburn_finish(); + } + return(1); +} + + +/* @param flag bit1= obtain outdrive, else indrive */ +int Xorriso_get_drive_handles(struct XorrisO *xorriso, + struct burn_drive_info **dinfo, + struct burn_drive **drive, + char *attempt, int flag) +{ + if(flag&2) + *dinfo= (struct burn_drive_info *) xorriso->out_drive_handle; + else + *dinfo= (struct burn_drive_info *) xorriso->in_drive_handle; + if(*dinfo==NULL) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, "No %s drive aquired %s", + (flag&2 ? "output" : "input"), attempt); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + *drive= (*dinfo)[0].drive; + return((*drive)!=NULL); +} + + +int Xorriso__sev_to_text(int severity, char **severity_name, + int flag) +{ + int ret; + + ret= iso_sev_to_text(severity, severity_name); + if(ret>0) + return(ret); + ret= burn_sev_to_text(severity, severity_name, 0); + if(ret>0) + return(ret); + *severity_name= ""; + return(0); +} + + +int Xorriso__text_to_sev(char *severity_name, int *severity_number, int flag) +{ + int ret= 1; + + ret= iso_text_to_sev(severity_name, severity_number); + if(ret>0) + return(ret); + ret= burn_text_to_sev(severity_name, severity_number, 0); + return(ret); +} + + +/* @param flag bit0= report libisofs error text + bit1= victim is disk_path + bit2= do not inquire libisofs, report msg_text and min_severity +*/ +int Xorriso_report_iso_error(struct XorrisO *xorriso, char *victim, + int iso_error_code, char msg_text[], int os_errno, + char min_severity[], int flag) +{ + int error_code, iso_sev, min_sev, ret; + char *sev_text_pt, *msg_text_pt= NULL; + char sfe[6*SfileadrL]; + static int sorry_sev= -1; + + if(sorry_sev<0) + Xorriso__text_to_sev("SORRY", &sorry_sev, 0); + + if(flag&4) { + error_code= 0x00050000; + Xorriso__text_to_sev(min_severity, &iso_sev, 0); + } else { + error_code= iso_error_get_code(iso_error_code); + if(error_code < 0x00030000 || error_code >= 0x00040000) + error_code= (error_code & 0xffff) | 0x00050000; + if(flag&1) + msg_text_pt= (char *) iso_error_to_msg(iso_error_code); + iso_sev= iso_error_get_severity(iso_error_code); + } + if(msg_text_pt==NULL) + msg_text_pt= msg_text; + + if(iso_sev >= sorry_sev && (flag & 2) && victim[0]) + Xorriso_msgs_submit(xorriso, 0, victim, 0, "ERRFILE", 0); + sev_text_pt= min_severity; + Xorriso__text_to_sev(min_severity, &min_sev, 0); + if(min_sev < iso_sev && !(flag&4)) + Xorriso__sev_to_text(iso_sev, &sev_text_pt, 0); + strcpy(sfe, msg_text_pt); + if(victim[0]) { + strcat(sfe, ": "); + Text_shellsafe(victim, sfe+strlen(sfe), 0); + } + ret= Xorriso_msgs_submit(xorriso, error_code, sfe, os_errno, sev_text_pt, 4); + return(ret); +} + + +/* @param flag bit0= suppress messages below UPDATE + bit1= suppress messages below FAILURE +*/ +int Xorriso_set_image_severities(struct XorrisO *xorriso, int flag) +{ + char *queue_sev, *print_sev; + + if(flag&2) + queue_sev= "FAILURE"; + else if(flag&1) + queue_sev= "UPDATE"; + else + queue_sev= "ALL"; + if(xorriso->library_msg_direct_print) + print_sev= xorriso->report_about_text; + else + print_sev= "NEVER"; + iso_set_msgs_severities(queue_sev, print_sev, "libisofs : "); + return(1); +} + + +int Xorriso_update_volid(struct XorrisO *xorriso, int flag) +{ + int gret, sret= 1; + + gret= Xorriso_get_volid(xorriso, xorriso->loaded_volid, 0); + if(gret<=0 || (!xorriso->volid_default) || xorriso->loaded_volid[0]==0) + sret= Xorriso_set_volid(xorriso, xorriso->volid, 1); + return(gret>0 && sret>0); +} + + +int Xorriso_create_empty_iso(struct XorrisO *xorriso, int flag) +{ + int ret; + IsoImage *volset; + struct isoburn_read_opts *ropts; + struct burn_drive_info *dinfo= NULL; + struct burn_drive *drive= NULL; + + if(xorriso->out_drive_handle != NULL) { + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to attach volset to drive", 2); + if(ret<=0) + return(ret); + } + if(xorriso->in_volset_handle!=NULL) { + iso_image_unref((IsoImage *) xorriso->in_volset_handle); + xorriso->in_volset_handle= NULL; + Sectorbitmap_destroy(&(xorriso->in_sector_map), 0); + xorriso->loaded_volid[0]= 0; + xorriso->volset_change_pending= 0; + xorriso->no_volset_present= 0; + } + + ret= isoburn_ropt_new(&ropts, 0); + if(ret<=0) + return(ret); + /* Note: no return before isoburn_ropt_destroy() */ + isoburn_ropt_set_extensions(ropts, isoburn_ropt_pretend_blank); + isoburn_ropt_set_input_charset(ropts, xorriso->in_charset); + isoburn_set_read_pacifier(drive, NULL, NULL); + ret= isoburn_read_image(drive, ropts, &volset); + Xorriso_process_msg_queues(xorriso,0); + isoburn_ropt_destroy(&ropts, 0); + if(ret<=0) { + sprintf(xorriso->info_text, "Failed to create new empty ISO image object"); + Xorriso_report_iso_error(xorriso, "", ret, xorriso->info_text, 0, "FATAL", + 0); + return(-1); + } + xorriso->in_volset_handle= (void *) volset; + xorriso->in_sector_map= NULL; + Xorriso_update_volid(xorriso, 0); + xorriso->volset_change_pending= 0; + xorriso->no_volset_present= 0; + return(1); +} + + +int Xorriso_record_boot_info(struct XorrisO *xorriso, int flag) +{ + int ret; + struct burn_drive_info *dinfo; + struct burn_drive *drive; + IsoImage *image; + ElToritoBootImage *bootimg; + IsoFile *bootimg_node; + IsoBoot *bootcat_node; + + xorriso->loaded_boot_bin_lba= -1; + xorriso->loaded_boot_cat_path[0]= 0; + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to record boot LBAs", 0); + if(ret<=0) + return(0); + image= isoburn_get_attached_image(drive); + if(image == NULL) + return(0); + ret= iso_image_get_boot_image(image, &bootimg, + &bootimg_node, &bootcat_node); + if(ret != 1) + return(0); + if(bootimg_node != NULL) + Xorriso__file_start_lba((IsoNode *) bootimg_node, + &(xorriso->loaded_boot_bin_lba), 0); + if(bootcat_node != NULL) + Xorriso_path_from_node(xorriso, (IsoNode *) bootcat_node, 0, + xorriso->loaded_boot_cat_path, 0); + return(1); +} + + +int Xorriso_assert_volid(struct XorrisO *xorriso, int msc1, int flag) +{ + int ret, image_blocks; + char volid[33]; + struct burn_drive_info *dinfo; + struct burn_drive *drive; + + if(xorriso->assert_volid[0] == 0) + return(1); + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to perform -assert_volid", 0); + if(ret<=0) + return(0); + ret= isoburn_read_iso_head(drive, msc1, &image_blocks, volid, 1); + Xorriso_process_msg_queues(xorriso,0); + if(ret <= 0) { + sprintf(xorriso->info_text, + "-assert_volid: Cannot determine Volume Id at LBA %d.", msc1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, + xorriso->assert_volid_sev, 0); + } + ret= Sregex_match(xorriso->assert_volid, volid, 0); + if(ret < 0) + return(2); + if(ret == 0) { + strcpy(xorriso->info_text, + "-assert_volid: Volume id does not match pattern: "); + Text_shellsafe(xorriso->assert_volid, xorriso->info_text, 1); + strcat(xorriso->info_text, " <> "); + Text_shellsafe(xorriso->loaded_volid, xorriso->info_text, 1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, + xorriso->assert_volid_sev, 0); + return(0); + } + return(ret); +} + + +/* @param flag bit0= aquire as isoburn input drive + bit1= aquire as libburn output drive (as isoburn drive if bit0) + bit2= regard overwriteable media as blank + bit3= if the drive is a regular disk file: truncate it to + the write start address + bit5= do not print toc + @return <=0 failure , 1= ok + 2=success, but not writeable with bit1 + 3=success, but not blank and not ISO with bit0 +*/ +int Xorriso_aquire_drive(struct XorrisO *xorriso, char *adr, int flag) +{ + int ret, hret, not_writeable= 0, has_what, aquire_flag, load_lba; + uint32_t size; + struct burn_drive_info *dinfo= NULL, *out_dinfo, *in_dinfo; + struct burn_drive *drive, *out_drive, *in_drive; + enum burn_disc_status state; + IsoImage *volset = NULL; + struct isoburn_read_opts *ropts= NULL; + char libburn_adr[SfileadrL], *boot_fate, *sev; + + static int no_rr_or_joliet= 0; + + if((flag&3)==0) { + sprintf(xorriso->info_text, + "XORRISOBURN program error : Xorriso_aquire_drive bit0+bit1 not set"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(-1); + } + ret= Xorriso_give_up_drive(xorriso, (flag&3)|8); + if(ret<=0) + return(ret); + + ret= Xorriso_auto_driveadr(xorriso, adr, libburn_adr, 0); + if(ret <= 0) + return(ret); + if(strcmp(libburn_adr,"stdio:/dev/fd/1")==0) { + if(xorriso->dev_fd_1<0) { + sprintf(xorriso->info_text, + "-*dev \"stdio:/dev/fd/1\" was not a start argument. Cannot use it now."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } else { + sprintf(libburn_adr, "stdio:/dev/fd/%d", xorriso->dev_fd_1); + } + } + + if((flag&3)==1 && xorriso->out_drive_handle!=NULL) { + ret= Xorriso_get_drive_handles(xorriso, &out_dinfo, &out_drive, + "on attempt to compare new indev with outdev", 2); + if(ret<=0) + goto ex; + ret= burn_drive_equals_adr(out_drive, libburn_adr, 1); + if(ret==1) + dinfo= out_dinfo; + } else if((flag&3)==2 && xorriso->in_drive_handle!=NULL) { + ret= Xorriso_get_drive_handles(xorriso, &in_dinfo, &in_drive, + "on attempt to compare new outdev with indev", 0); + if(ret<=0) + goto ex; + ret= burn_drive_equals_adr(in_drive, libburn_adr, 1); + if(ret==1) + dinfo= in_dinfo; + } + + if(dinfo==NULL) { + isoburn_set_msgs_submit(Xorriso_msgs_submit_void, (void *) xorriso, + (3<<2) | 128 , 0); + aquire_flag= 1 | ((flag&(8|4))>>1) | ((xorriso->toc_emulation_flag & 3)<<3); + ret= isoburn_drive_aquire(&dinfo, libburn_adr, aquire_flag); + Xorriso_process_msg_queues(xorriso,0); + if(ret<=0) { + sprintf(xorriso->info_text,"Cannot aquire drive '%s'", adr); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + if(flag&1) + if(xorriso->image_start_mode&(1<<31)) /* used up setting */ + xorriso->image_start_mode= 0; /* no need to perform auto setting */ + } + drive= dinfo[0].drive; + if(flag&1) { + if(xorriso->image_start_mode&(1<<31)) /* used up setting */ + xorriso->image_start_mode&= ~0xffff; /* perform auto setting */ + if((xorriso->image_start_mode&(1<<30))) { /* if enabled at all */ + ret= isoburn_set_msc1(drive, xorriso->image_start_mode & 0xffff, + xorriso->image_start_value, + !!(xorriso->image_start_mode & (1<<16))); + if(ret<=0) + goto ex; + if(xorriso->image_start_mode&(1<<31)) + xorriso->image_start_mode= 0; /* disable msc1 setting completely */ + else + xorriso->image_start_mode|= (1<<31); /* mark as used up */ + } + } + state= isoburn_disc_get_status(drive); + Xorriso_process_msg_queues(xorriso,0); + if(flag&1) { + volset= isoburn_get_attached_image(drive); + if(volset != NULL) { /* The image object is already created */ + iso_image_unref(volset); + } + } + + if(flag&2) { + xorriso->out_drive_handle= dinfo; + if(Sfile_str(xorriso->outdev, adr, 0)<=0) + {ret= -1; goto ex;} + if(state != BURN_DISC_BLANK && state != BURN_DISC_APPENDABLE) { + sprintf(xorriso->info_text, "Disc status unsuitable for writing"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + not_writeable= 1; + } + } + if(flag&1) { + xorriso->in_drive_handle= dinfo; + if(Sfile_str(xorriso->indev, adr, 0)<=0) + {ret= -1; goto ex;} + } else if(flag&2) { + if(xorriso->in_volset_handle==NULL) { + /* No volume loaded: create empty one */ + ret= Xorriso_create_empty_iso(xorriso, 0); + if(ret<=0) + goto ex; + } else { + iso_image_ref((IsoImage *) xorriso->in_volset_handle); + ret= isoburn_attach_image(drive, (IsoImage *) xorriso->in_volset_handle); + if(ret<=0) { + sprintf(xorriso->info_text, + "Failed to attach ISO image object to outdev"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + {ret= -1; goto ex;} + } + } + if(!(flag&32)) + Xorriso_toc(xorriso, 1 | 2 | 8); + {ret= 1+not_writeable; goto ex;} + } + + if(xorriso->in_volset_handle!=NULL) + iso_image_unref((IsoImage *) xorriso->in_volset_handle); + xorriso->in_volset_handle= NULL; + Sectorbitmap_destroy(&(xorriso->in_sector_map), 0); + + /* check for invalid state */ + if(state != BURN_DISC_BLANK && state != BURN_DISC_APPENDABLE && + state != BURN_DISC_FULL) { + sprintf(xorriso->info_text, + "Disc status not blank and unsuitable for reading"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + {ret= 0; goto ex;} + } + /* fill read opts */ + ret= isoburn_ropt_new(&ropts, 0); + if(ret<=0) + goto ex; + isoburn_ropt_set_extensions(ropts, isoburn_ropt_noiso1999); + isoburn_ropt_set_default_perms(ropts, (uid_t) 0, (gid_t) 0, (mode_t) 0555); + isoburn_ropt_set_input_charset(ropts, xorriso->in_charset); + + Xorriso_set_image_severities(xorriso, 1); /* No DEBUG messages */ + Xorriso_pacifier_reset(xorriso, 0); + isoburn_set_read_pacifier(drive, Xorriso__read_pacifier, (void *) xorriso); + + /* <<< Trying to work around too much tolerance on bad image trees. + Better would be a chance to instruct libisofs what to do in + case of image read errors. There is a risk to mistake other SORRYs. + */ + if(xorriso->img_read_error_mode>0) + iso_set_abort_severity("SORRY"); + + if(state != BURN_DISC_BLANK) { + ret= isoburn_disc_get_msc1(drive, &load_lba); + if(ret > 0) { + sprintf(xorriso->info_text, + "Loading ISO image tree from LBA %d", load_lba); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + } + ret= Xorriso_assert_volid(xorriso, load_lba, 0); + if(ret <= 0) + goto ex; + } + + /* <<< */ + if(no_rr_or_joliet) { + isoburn_ropt_set_extensions(ropts, + isoburn_ropt_noiso1999 | isoburn_ropt_norock | isoburn_ropt_nojoliet); + } + + ret= isoburn_read_image(drive, ropts, &volset); + + /* <<< Resetting to normal thresholds */ + if(xorriso->img_read_error_mode>0) + Xorriso_set_abort_severity(xorriso, 0); + + if(ret<=0) { + Xorriso_process_msg_queues(xorriso,0); + Xorriso_set_image_severities(xorriso, 0); + Xorriso_give_up_drive(xorriso, 1|((flag&32)>>2)); + sprintf(xorriso->info_text,"Cannot read ISO image tree"); + sev= "FAILURE"; + if(xorriso->img_read_error_mode==2) + sev= "FATAL"; + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, sev, 0); + if(xorriso->img_read_error_mode!=0) + Xorriso_msgs_submit(xorriso, 0, "You might get a partial or altered ISO image tree by option -error_behavior 'image_loading' 'best_effort'", + 0, "HINT", 0); + ret= 3; goto ex; + } + Xorriso_pacifier_callback(xorriso, "nodes read", xorriso->pacifier_count, 0, + "", 1); /* report end count */ + xorriso->in_volset_handle= (void *) volset; + xorriso->in_sector_map= NULL; + Xorriso_set_image_severities(xorriso, 0); + Xorriso_update_volid(xorriso, 0); + + if(xorriso->out_drive_handle != NULL && + xorriso->out_drive_handle != xorriso->in_drive_handle) { + ret= Xorriso_get_drive_handles(xorriso, &out_dinfo, &out_drive, + "on attempt to attach ISO image volset to outdev", 2); + if(ret<=0) + goto ex; + iso_image_ref((IsoImage *) xorriso->in_volset_handle); + isoburn_attach_image(out_drive, xorriso->in_volset_handle); + } + Xorriso_process_msg_queues(xorriso,0); + isoburn_ropt_get_size_what(ropts, &size, &has_what); + if(has_what & isoburn_ropt_has_el_torito) { + if(xorriso->boot_image_bin_path[0]) + boot_fate= "replaced by an isolinux image"; + else if(xorriso->patch_isolinux_image) + boot_fate= "patched as isolinux image"; + else if(xorriso->keep_boot_image) + boot_fate= "kept unchanged"; + else + boot_fate= "discarded"; + sprintf(xorriso->info_text, + "Detected El-Torito boot information which currently is set to be %s", + boot_fate); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + Xorriso_record_boot_info(xorriso, 0); + } + if(!(flag&32)) { + Xorriso_toc(xorriso, 1 | 8); + if(xorriso->loaded_volid[0]!=0) { + sprintf(xorriso->info_text,"Volume id : '%s'\n", + xorriso->loaded_volid); + Xorriso_info(xorriso, 0); + if(strcmp(xorriso->loaded_volid, xorriso->volid) != 0 && + !xorriso->volid_default) { + sprintf(xorriso->info_text, "New volume id: '%s'\n", xorriso->volid); + Xorriso_info(xorriso, 0); + } + } + } + ret= 1+not_writeable; +ex: + Xorriso_process_msg_queues(xorriso,0); + if(ret<=0) { + hret= Xorriso_give_up_drive(xorriso, (flag&3)|((flag&32)>>2)); + if(hretin_drive_handle == xorriso->out_drive_handle); + if((flag&4) && in_is_out_too && (flag&(1|2))) { + if((flag&3)!=3) { + sprintf(xorriso->info_text,"Giving up for -eject whole -dev %s", + Text_shellsafe(xorriso->indev, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + } + flag|= 3; /* give up in/out drive to eject it */ + } + + if((flag&1) && xorriso->in_drive_handle != NULL) { + Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to give up drive", 0); + + if(!in_is_out_too) { + if(drive!=NULL && !in_is_out_too) + isoburn_drive_release(drive,!!(flag&4)); + if(dinfo!=NULL && !in_is_out_too) + burn_drive_info_free(dinfo); + } + xorriso->in_drive_handle= NULL; + xorriso->indev[0]= 0; + + if(xorriso->in_volset_handle!=NULL) + iso_image_unref((IsoImage *) xorriso->in_volset_handle); + xorriso->in_volset_handle= NULL; + Sectorbitmap_destroy(&(xorriso->in_sector_map), 0); + xorriso->loaded_volid[0]= 0; + xorriso->volset_change_pending= 0; + xorriso->no_volset_present= 0; + xorriso->loaded_boot_bin_lba= 0; + xorriso->loaded_boot_cat_path[0]= 0; + in_is_out_too= 0; + } + if((flag&2) && xorriso->out_drive_handle!=NULL) { + Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to give up drive", 2); + if(!in_is_out_too) { + if(drive!=NULL) + isoburn_drive_release(drive,!!(flag&4)); + if(dinfo!=NULL) + burn_drive_info_free(dinfo); + } + xorriso->out_drive_handle= NULL; + xorriso->outdev[0]= 0; + } else if((flag&1) && xorriso->out_drive_handle!=NULL) { + ret= Xorriso_create_empty_iso(xorriso, 0); + if(ret<=0) + return(ret); + if(!(flag&8)) { + sprintf(xorriso->info_text, + "Only the output drive remains. Created empty ISO image.\n"); + Xorriso_info(xorriso, 0); + Xorriso_toc(xorriso, 1 | 2 | 8); + } + } + Xorriso_process_msg_queues(xorriso,0); + return(1); +} + + +int Xorriso_make_write_options( + struct XorrisO *xorriso, struct burn_drive *drive, + struct burn_write_opts **burn_options, int flag) +{ + int drive_role; + + *burn_options= burn_write_opts_new(drive); + if(*burn_options==NULL) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text,"Cannot allocate option set"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + burn_write_opts_set_simulate(*burn_options, !!xorriso->do_dummy); + drive_role= burn_drive_get_drive_role(drive); + burn_write_opts_set_multi(*burn_options, + !(xorriso->do_close || drive_role==0 || drive_role==3)); + burn_drive_set_speed(drive, xorriso->speed, xorriso->speed); + burn_write_opts_set_stream_recording(*burn_options, + !! xorriso->do_stream_recording); + burn_write_opts_set_underrun_proof(*burn_options, 1); + return(1); +} + + +/* @param flag bit0= do not write but only prepare and return size in sectors + bit1= do not use isoburn wrappers +*/ +int Xorriso_sanitize_image_size(struct XorrisO *xorriso, + struct burn_drive *drive, struct burn_disc *disc, + struct burn_write_opts *burn_options, int flag) +{ + int ret, img_sectors, num_sessions= 0, num_tracks= 0, padding= 0, profile; + int media_space, lba, nwa; + char profile_name[80]; + struct burn_session **sessions; + struct burn_track **tracks; + + img_sectors= burn_disc_get_sectors(disc); + + sessions= burn_disc_get_sessions(disc, &num_sessions); + if(sessions==NULL || num_sessions < 1) { +no_track:; + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text,"Program error : no track in prepared disc"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + {ret= -1; goto ex;} + } + tracks= burn_session_get_tracks(sessions[0], &num_tracks); + if(tracks==NULL || num_tracks < 1) + goto no_track; + + padding= 0; + ret= burn_disc_get_profile(drive, &profile, profile_name); + padding= xorriso->padding / 2048; + if(xorriso->padding > padding * 2048) + padding++; + if(img_sectors>0 && ret>0 && + (profile==0x09 || profile==0x0a)) { /* CD-R , CD-RW */ + if(img_sectors + padding < Xorriso_cd_min_track_sizE) { + padding= Xorriso_cd_min_track_sizE - img_sectors; + sprintf(xorriso->info_text, + "Expanded track to minimum size of %d sectors", + Xorriso_cd_min_track_sizE); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + } + } + if(xorriso->alignment > 0) { + if(img_sectors > 0) { + ret= isoburn_disc_track_lba_nwa(drive, burn_options, 0, &lba, &nwa); + if(ret <= 0) + nwa= 0; + lba= (nwa + img_sectors + padding) % xorriso->alignment; + if(lba > 0) + padding+= xorriso->alignment - lba; + } else if(padding < xorriso->alignment) + padding= xorriso->alignment; + } + burn_track_define_data(tracks[0], 0, padding * 2048, 0, BURN_MODE1); + Xorriso_process_msg_queues(xorriso,0); + + if(flag&2) + media_space= burn_disc_available_space(drive, burn_options) / + (off_t) 2048; + else + media_space= isoburn_disc_available_space(drive, burn_options) / + (off_t) 2048; + if(media_space < img_sectors + padding) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text,"Image size %ds exceeds free space on media %ds", + img_sectors + padding, media_space); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + if(flag&1) { + ret= img_sectors+padding; + } else + ret= 1; +ex:; + return(ret); +} + + +/* @return <0 yes , 0 no , <0 error */ +int Xorriso_is_isohybrid(struct XorrisO *xorriso, IsoFile *bootimg_node, + int flag) +{ + int ret; + unsigned char buf[68]; + void *data_stream= NULL; + + ret= Xorriso_iso_file_open(xorriso, "", (void *) bootimg_node, + &data_stream, 1); + if(ret <= 0) + return(-1); + ret= Xorriso_iso_file_read(xorriso, data_stream, (char *) buf, 68, 0); + Xorriso_iso_file_close(xorriso, &data_stream, 0); + if(ret <= 0) + return(0); + if(buf[64] == 0xfb && buf[65] == 0xc0 && buf[66] == 0x78 && buf[67] == 0x70) + return(1); + return(0); +} + + +int Xorriso_set_isolinux_options(struct XorrisO *xorriso, + IsoImage *image, int flag) +{ + int make_isohybrid_mbr= 0, ret; + ElToritoBootImage *bootimg; + IsoFile *bootimg_node; + + ret= iso_image_get_boot_image(image, &bootimg, &bootimg_node, NULL); + if(ret != 1) { + sprintf(xorriso->info_text, "Programming error: No boot image available in Xorriso_set_isolinux_options()"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(-1); + } + + if(xorriso->boot_image_isohybrid == 0) { + ret= el_torito_set_isolinux_options(bootimg, 1, 0); + return(ret == 1); + } + if(xorriso->boot_image_isohybrid == 3) { + make_isohybrid_mbr= 1; + } else { + ret= Xorriso_is_isohybrid(xorriso, bootimg_node, 0); + if(ret < 0) + return(0); + if(ret > 0) + make_isohybrid_mbr= 1; + } + + if(xorriso->boot_image_isohybrid == 2 && !make_isohybrid_mbr) { + sprintf(xorriso->info_text, + "Isohybrid signature is demanded but not found in boot image file."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + if(make_isohybrid_mbr) { + sprintf(xorriso->info_text, "Will write isohybrid MBR."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + xorriso->alignment= 512; + } + + ret= el_torito_set_isolinux_options(bootimg, 1 | (make_isohybrid_mbr << 1),0); + return(ret == 1); +} + + +int Xorriso_auto_format(struct XorrisO *xorriso, int flag) +{ + int ret, profile, status, num_formats; + char profile_name[80]; + struct burn_drive_info *dinfo; + struct burn_drive *drive; + off_t size; + unsigned dummy; + + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to autoformat", 2); + if(ret<=0) + return(0); + ret= burn_disc_get_profile(drive, &profile, profile_name); + if(ret>0 && (profile==0x12 || profile==0x43)) { /* DVD-RAM or BD-RE */ + ret= burn_disc_get_formats(drive, &status, &size, &dummy, &num_formats); + if(ret>0 && status==BURN_FORMAT_IS_UNFORMATTED) { + sprintf(xorriso->info_text, + "Unformatted %s media detected. Trying -format fast.", + profile_name); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + ret= Xorriso_format_media(xorriso, (off_t) 0, 1 | 4); + if(ret<=0) { + sprintf(xorriso->info_text, "Automatic formatting of %s failed", + profile_name); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(ret); + } + } + } + return(1); +} + + +#define Xorriso_with_make_isohybrid_mbR 1 + + +/* @param flag bit0= do not write but only prepare and return size in sectors +*/ +int Xorriso_write_session(struct XorrisO *xorriso, int flag) +{ + int ret, relax= 0, i, pacifier_speed= 0; + int major, minor, micro; + char xorriso_id[256], *img_id, sfe[5*SfileadrL], *cpt; + struct isoburn_imgen_opts *sopts= NULL; + struct burn_drive_info *dinfo, *source_dinfo; + struct burn_drive *drive, *source_drive; + struct burn_disc *disc= NULL; + struct burn_write_opts *burn_options; + off_t readcounter= 0,writecounter= 0; + int num_sessions= 0, num_tracks= 0; + struct burn_session **sessions; + struct burn_track **tracks; + enum burn_disc_status s; + IsoImage *image= NULL; + IsoNode *node; + ElToritoBootImage *bootimg; + enum eltorito_boot_media_type emul_type= ELTORITO_NO_EMUL; + int profile_number; + char profile_name[80]; + + if(!(flag & 1)) { + ret= Xorriso_auto_format(xorriso, 0); + if(ret <=0 ) + return(0); + } + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to write", 2); + if(ret<=0) + return(0); + if(xorriso->out_drive_handle == xorriso->in_drive_handle) { + source_drive= drive; + } else { + if(xorriso->in_drive_handle == NULL) { + source_drive= drive; + } else { + ret= Xorriso_get_drive_handles(xorriso, &source_dinfo, &source_drive, + "on attempt to get source for write", 0); + if(ret<=0) + goto ex; + } + s= isoburn_disc_get_status(drive); + if(s!=BURN_DISC_BLANK) { + s= burn_disc_get_status(drive); + if(s!=BURN_DISC_BLANK) + sprintf(xorriso->info_text, + "-indev differs from -outdev and -outdev media is not blank"); + else + sprintf(xorriso->info_text, + "-indev differs from -outdev and -outdev media holds non-zero data"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + } + ret= Xorriso_get_profile(xorriso, &profile_number, profile_name, 2); + if(ret == 2) + pacifier_speed= 1; + else if(ret == 3) + pacifier_speed= 2; + + ret= isoburn_igopt_new(&sopts, 0); + if(ret<=0) { + Xorriso_process_msg_queues(xorriso, 0); + return(ret); + } +#ifdef NIX + relax= isoburn_igopt_allow_deep_paths; +#else + relax= xorriso->relax_compliance; +#endif + + xorriso->alignment= 0; + image= isoburn_get_attached_image(source_drive); + if(image != NULL) { + iso_image_set_application_id(image, xorriso->application_id); + iso_image_set_publisher_id(image, xorriso->publisher); + } + + /* Activate, adjust or discard boot image */ + /* >>> ??? move down to libisoburn ? */ + if(image!=NULL && !(flag&1)) { + ret= iso_image_get_boot_image(image, &bootimg, NULL, NULL); + + if(xorriso->boot_image_bin_path[0]) { + /* discard old boot image, set new one */ + if(ret == 1) + iso_image_remove_boot_image(image); + if(xorriso->boot_image_emul == 1) + emul_type= ELTORITO_HARD_DISC_EMUL; + else if(xorriso->boot_image_emul == 2) + emul_type= ELTORITO_FLOPPY_EMUL; + if(xorriso->boot_image_cat_path[0] == 0) { + strcpy(xorriso->boot_image_cat_path, xorriso->boot_image_bin_path); + cpt= strrchr(xorriso->boot_image_cat_path, '/'); + if(cpt == NULL) + cpt= xorriso->boot_image_cat_path; + else + cpt++; + strcpy(cpt, "boot.cat"); + } + sprintf(xorriso->info_text, "Activating alleged isolinux boot image %s", + Text_shellsafe(xorriso->boot_image_bin_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + sprintf(xorriso->info_text, "Creating El Torito boot catalog file %s", + Text_shellsafe(xorriso->boot_image_cat_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + + ret= Xorriso_node_from_path(xorriso, image, xorriso->boot_image_bin_path, + &node, 1); + if(ret <= 0) { + sprintf(xorriso->info_text, + "Cannot find in ISO image: -boot_image ... bin_path=%s", + Text_shellsafe(xorriso->boot_image_bin_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + +#ifdef NIX +#ifdef Xorriso_with_make_isohybrid_mbR + + /* ??? must the boot image have a low LBA to boot from MBR ? */ + /* A81110: Does not look so. The proplems were caused by wrong + self-LBA in isolinux.bin at byte 12 to 15 */ + isoburn_igopt_set_sort_files(sopts, isoburn_igopt_sort_files_by_weight); + iso_node_set_sort_weight(node, 0x7fffffff); + +#endif +#endif /* NIX */ + + ret= Xorriso_node_from_path(xorriso, image, xorriso->boot_image_cat_path, + &node, 1); + if(ret > 0) { + if(!xorriso->do_overwrite) { + sprintf(xorriso->info_text, + "May not overwite existing -boot_image ... cat_path=%s", + Text_shellsafe(xorriso->boot_image_cat_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, xorriso->boot_image_cat_path, + 8 | (xorriso->do_overwrite == 1)); + if(ret != 1) { + sprintf(xorriso->info_text, + "Could not remove existing -boot_image cat_path=%s", + Text_shellsafe(xorriso->boot_image_cat_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + } + + ret= iso_image_set_boot_image(image, xorriso->boot_image_bin_path, + emul_type, xorriso->boot_image_cat_path, + &bootimg); + if(ret < 0) { + Xorriso_process_msg_queues(xorriso,0); + Xorriso_report_iso_error(xorriso, "", ret, + "Error when attaching El-Torito boot image to ISO 9660 image", + 0, "FAILURE", 1); + sprintf(xorriso->info_text, + "Could not attach El-Torito boot image to ISO 9660 image"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + el_torito_set_load_size(bootimg, xorriso->boot_image_load_size / 512); + +#ifdef Xorriso_with_make_isohybrid_mbR + + ret= Xorriso_set_isolinux_options(xorriso, image, 0); + if(ret <= 0) + goto ex; + +#else + el_torito_patch_isolinux_image(bootimg); +#endif + + } else if(xorriso->patch_isolinux_image) { + if(ret==1) { + relax|= isoburn_igopt_allow_full_ascii; + sprintf(xorriso->info_text, "Patching alleged isolinux boot image"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + + ret= Xorriso_path_from_node(xorriso, NULL, xorriso->loaded_boot_bin_lba, + sfe, 1); + if(ret < 0) + goto ex; + if(ret == 0) { + sprintf(xorriso->info_text, + "Cannot patch boot image: no file found for its LBA."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + sprintf(xorriso->info_text, + "Probably the loaded boot image file was deleted in this session."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + sprintf(xorriso->info_text, + "Use -boot_image \"any\" \"discard\" or set new boot image"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0); + goto ex; + } + +#ifdef Xorriso_with_make_isohybrid_mbR + + ret= Xorriso_set_isolinux_options(xorriso, image, 0); + if(ret <= 0) + goto ex; + +#else + el_torito_patch_isolinux_image(bootimg); +#endif + + } else { + sprintf(xorriso->info_text, + "Could not find any boot image for -boot_image isolinux patch"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); + } + } else if(xorriso->keep_boot_image && ret==1) { + relax|= isoburn_igopt_allow_full_ascii; + sprintf(xorriso->info_text, "Keeping boot image unchanged"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + } else if(ret==1) { + iso_image_remove_boot_image(image); + sprintf(xorriso->info_text, "Discarded boot image from old session"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + } + } + isoburn_igopt_set_level(sopts, 3); + isoburn_igopt_set_extensions(sopts, 1|((!!xorriso->do_joliet)<<1)); + +#ifdef NIX + isoburn_igopt_set_relaxed(sopts, isoburn_igopt_allow_deep_paths | + (xorriso->do_always_gmt * isoburn_igopt_always_gmt) | + isoburn_igopt_rrip_version_1_10); +#else + isoburn_igopt_set_relaxed(sopts, relax); +#endif + + isoburn_igopt_set_sort_files(sopts, 1); + isoburn_igopt_set_over_mode(sopts, 0, 0, (mode_t) 0, (mode_t) 0); + isoburn_igopt_set_over_ugid(sopts, 0, 0, (uid_t) 0, (gid_t) 0); + isoburn_igopt_set_out_charset(sopts, xorriso->out_charset); + isoburn_igopt_set_fifo_size(sopts, xorriso->fs * 2048); + + if(image!=NULL && + strlen(Xorriso_program_versioN)+strlen(Xorriso_timestamP)<80) { + sprintf(xorriso_id, "XORRISO-%s %s", + Xorriso_program_versioN, Xorriso_timestamP); + isoburn_version(&major, &minor, µ); + if(strlen(xorriso_id)<80) + sprintf(xorriso_id+strlen(xorriso_id), + ", LIBISOBURN-%d.%d.%d", major, minor, micro); + iso_lib_version(&major, &minor, µ); + if(strlen(xorriso_id)<80) + sprintf(xorriso_id+strlen(xorriso_id), + ", LIBISOFS-%d.%d.%d", major, minor, micro); + burn_version(&major, &minor, µ); + if(strlen(xorriso_id)<80) + sprintf(xorriso_id+strlen(xorriso_id), + ", LIBBURN-%d.%d.%d", major, minor, micro); + xorriso_id[128]= 0; + img_id= (char *) iso_image_get_data_preparer_id(image); + if(img_id!=NULL) { + for(i= strlen(img_id)-1; i>=0 && img_id[i]==' '; i--); + if(i>0) { + sprintf(xorriso->info_text, "Overwrote previous preparer id '%s'", + img_id); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + } + } + iso_image_set_data_preparer_id(image, xorriso_id); + } + + /* Make final abort check before starting expensive activities */ + ret= Xorriso_eval_problem_status(xorriso, 1, 0); + if(ret<0) + {ret= 0; goto ex;} + + /* >>> omit iso_image_update_sizes if the image was filled up very quickly */; + + ret= iso_image_update_sizes(image); + if(ret < 0) { + Xorriso_process_msg_queues(xorriso, 0); + ret= Xorriso_eval_problem_status(xorriso, 1, 0); + if(ret<0) + {ret= 0; goto ex;} + } + + Xorriso_set_abort_severity(xorriso, 1); + if (xorriso->grow_blindly_msc2 >= 0 && + xorriso->out_drive_handle != xorriso->in_drive_handle) { + ret= isoburn_prepare_blind_grow(source_drive, &disc, sopts, drive, + xorriso->grow_blindly_msc2); + if(ret>0) { + /* Allow the consumer of output to access the input drive */ + source_drive= NULL; + ret= Xorriso_give_up_drive(xorriso, 1|8); + if(ret<=0) + goto ex; + } + } else if(xorriso->out_drive_handle == xorriso->in_drive_handle || + xorriso->in_drive_handle == NULL) { + ret= isoburn_prepare_disc(source_drive, &disc, sopts); + } else { + ret= isoburn_prepare_new_image(source_drive, &disc, sopts, drive); + } + if(ret <= 0) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text,"Failed to prepare session write run"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + isoburn_igopt_get_effective_lba(sopts, &(xorriso->session_lba)); + + ret= Xorriso_make_write_options(xorriso, drive, &burn_options, 0); + if(ret<=0) + goto ex; + + ret= Xorriso_sanitize_image_size(xorriso, drive, disc, burn_options, flag&1); + if(ret<=0 || (flag&1)) { + Xorriso_process_msg_queues(xorriso,0); + if(flag&1) /* set queue severity to FAILURE */ + Xorriso_set_image_severities(xorriso, 2); + isoburn_cancel_prepared_write(source_drive, drive, 0); + if(flag&1) /* reset queue severity */ + Xorriso_set_image_severities(xorriso, 0); + goto ex; + } + + xorriso->run_state= 1; /* Indicate that burning has started */ + isoburn_disc_write(burn_options, disc); + burn_write_opts_free(burn_options); + + ret= Xorriso_pacifier_loop(xorriso, drive, pacifier_speed << 4); + if(ret<=0) + goto ex; + if(!isoburn_drive_wrote_well(drive)) { + isoburn_cancel_prepared_write(source_drive, drive, 0); + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "libburn indicates failure with writing."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + + sessions= burn_disc_get_sessions(disc, &num_sessions); + if(num_sessions>0) { + tracks= burn_session_get_tracks(sessions[0], &num_tracks); + if(tracks!=NULL && num_tracks>0) { + burn_track_get_counters(tracks[0],&readcounter,&writecounter); + xorriso->session_blocks= (int) (writecounter/ (off_t) 2048); + sprintf(xorriso->info_text, + "ISO image produced: %d sectors\nWritten to media : %d sectors at LBA %d\n", + (int) (readcounter/ (off_t) 2048), + xorriso->session_blocks, xorriso->session_lba); + Xorriso_info(xorriso, 0); + } + } + ret= isoburn_activate_session(drive); + Xorriso_process_msg_queues(xorriso,0); + if(ret<=0) { + sprintf(xorriso->info_text, + "Could not write new set of volume descriptors"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + goto ex; + } + /* Done early to free any reference to the libisofs resources via disc */ + if(disc!=NULL) + burn_disc_free(disc); + disc= NULL; + /* To wait for the end of the libisofs threads and their messages. */ + isoburn_sync_after_write(source_drive, drive, 0); + Xorriso_process_msg_queues(xorriso,0); + + sprintf(xorriso->info_text, "Writing to %s completed sucessfully.\n\n", + Text_shellsafe(xorriso->outdev,sfe,0)); + Xorriso_info(xorriso, 0); + ret= 1; +ex:; + xorriso->run_state= 0; /* Indicate that burning has ended */ + Xorriso_set_abort_severity(xorriso, 0); + + if(ret<=0) { + /* >>> ??? revive discarded boot image */; + +#ifdef NIX + /* <<< this was probably not a good idea */ + } else if(xorriso->boot_image_bin_path[0]) { + xorriso->keep_boot_image= 1; + xorriso->patch_isolinux_image= 1; + xorriso->boot_image_bin_path[0]= 0; + sprintf(xorriso->info_text, "Switched to -boot_image isolinux patch"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); +#endif /* NIX */ + + } + if(disc!=NULL) + burn_disc_free(disc); + isoburn_igopt_destroy(&sopts, 0); + Xorriso_process_msg_queues(xorriso,0); + return(ret); +} + + +int Xorriso_check_burn_abort(struct XorrisO *xorriso, int flag) +{ + int ret; + struct burn_drive_info *dinfo; + struct burn_drive *drive; + + if(xorriso->run_state!=1) + return(0); + ret= Xorriso_eval_problem_status(xorriso, 1, 1); + if(ret>=0) + return(0); + sprintf(xorriso->info_text, + "-abort_on '%s' encountered '%s' during image writing", + xorriso->abort_on_text, xorriso->problem_status_text); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, + xorriso->problem_status_text, 0); + + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to abort burn run", 2); + if(ret<=0) + return(0); + + burn_drive_cancel(drive); + sprintf(xorriso->info_text, + "libburn has now been urged to cancel its operation"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(1); +} + + +/* This loop watches burn runs until they end. + It issues pacifying update messages to the user. + @param flag bit0-3 = emulation mode + 0= xorriso + 1= mkisofs + 2= cdrecord + bit4= report speed in CD units + bit5= report speed in BD units +*/ +int Xorriso_pacifier_loop(struct XorrisO *xorriso, struct burn_drive *drive, + int flag) +{ + int ret, size, free_bytes, i, aborting= 0, emul, buffer_fill= 50, last_sector; + struct burn_progress progress; + char *status_text, date_text[80], *speed_unit, mem_text[8]; + enum burn_drive_status drive_status; + double start_time, current_time, last_time, base_time= 0.0, base_count= 0.0; + double next_base_time= 0.0, next_base_count= 0.0, first_base_time= 0.0; + double first_base_count= 0.0, norm= 0.0, now_time, fract_offset= 0.0; + double measured_speed, speed_factor= 1385000, quot; + time_t time_prediction; + + start_time= Sfile_microtime(0); + while(burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING) + usleep(100002); + + emul= flag&15; + fract_offset= 0.2 * (double) emul - ((int) (0.2 * (double) emul)); + if(emul==0) + emul= xorriso->pacifier_style; + speed_unit= "D"; + if(flag&16) { + speed_factor= 150.0*1024; + speed_unit= "C"; + } else if(flag & 32) { + speed_factor= 4495625; + speed_unit= "B"; + } + progress.sector= 0; + current_time= Sfile_microtime(0); + measured_speed= 0.0; + while(1) { + last_time= current_time; + last_sector= progress.sector; + drive_status= burn_drive_get_status(drive, &progress); + if(drive_status == BURN_DRIVE_IDLE) + break; + current_time= Sfile_microtime(0); + if(drive_status == BURN_DRIVE_WRITING && progress.sectors > 0) { + if(current_time-last_time>0.2) + measured_speed= (progress.sector - last_sector) * 2048.0 / + (current_time - last_time); + buffer_fill= 50; + if(progress.buffer_capacity>0) + buffer_fill= (double) (progress.buffer_capacity + - progress.buffer_available) * 100.0 + / (double) progress.buffer_capacity; + if(emul==2) { + if(progress.sector<=progress.sectors) + sprintf(xorriso->info_text, "%4d of %4d MB written", + progress.sector / 512, progress.sectors / 512); + else + sprintf(xorriso->info_text, "%4d MB written", + progress.sector / 512); + + if(xorriso->pacifier_fifo!=NULL) + ret= burn_fifo_inquire_status(xorriso->pacifier_fifo, + &size, &free_bytes, &status_text); + else + ret= isoburn_get_fifo_status(drive, &size, &free_bytes, &status_text); + if(ret>0 ) + sprintf(xorriso->info_text+strlen(xorriso->info_text), + " (fifo %2d%%)", + (int) (100.0-100.0*((double) free_bytes)/(double) size)); + + sprintf(xorriso->info_text+strlen(xorriso->info_text), " [buf %3d%%]", + buffer_fill); + + if(current_time-last_time>0.2) + sprintf(xorriso->info_text+strlen(xorriso->info_text), " %4.1fx.", + measured_speed/speed_factor); + + } else if(emul == 1 && + progress.sectors > 0 && progress.sector <= progress.sectors) { + /* "37.87% done, estimate finish Tue Jul 15 18:55:07 2008" */ + + quot= ((double) progress.sector) / ((double) progress.sectors); + sprintf(xorriso->info_text, " %2.2f%% done", quot*100.0); + if(current_time - start_time >= 2 && quot > 0.0 && + (quot >= 0.02 || progress.sector >= 5*1024)) { + if(base_time == 0.0 && progress.sector >= 16*1024) { + first_base_time= base_time= next_base_time= current_time; + first_base_count= next_base_count= progress.sector; + } else if(next_base_time > 0 && current_time - next_base_time >= 10) { + base_time= next_base_time; + base_count= next_base_count; + next_base_time= current_time; + next_base_count= progress.sector; + } + if(first_base_time > 0 && + current_time - first_base_time >= 10 && + progress.sectors > first_base_count) { + norm= (1.0 - quot); + if(norm < 0.0001) + norm= 0.0001; + quot= ((double) progress.sector - first_base_count) + / ((double) progress.sectors - first_base_count); + time_prediction= norm * (1.0 - quot) / quot + * (current_time - first_base_time); + } else { + time_prediction= (1.0 - quot) / quot * (current_time - start_time); + norm= 1.0; + } + if(base_time > 0 && + current_time - base_time >= 10 && progress.sectors > base_count) { + quot= ((double) progress.sector - base_count) + / ((double) progress.sectors - base_count); + time_prediction+= (1.0 - quot) / quot * (current_time - base_time); + norm+= 1.0; + } + time_prediction/= norm; + if(time_prediction < 30*86400) { + time_prediction+= current_time + 1; + Ftimetxt(time_prediction, date_text, 4); + sprintf(xorriso->info_text+strlen(xorriso->info_text), + ", estimate finish %s", date_text); + } + } + } else { + if(progress.sector<=progress.sectors) { + if(progress.sectors <= 0) + strcpy(mem_text, "99.9"); + else + sprintf(mem_text, "%4.1f", + 100.0 * ((double) progress.sector) / ((double) progress.sectors)); + mem_text[4]= 0; + sprintf(xorriso->info_text, "Writing: %10ds %s%% ", + progress.sector, mem_text); + } else { + Sfile_scale(2048.0 * (double) progress.sector, mem_text, 5, 1e4, 1); + sprintf(xorriso->info_text, "Writing: %10ds %s ", + progress.sector, mem_text); + } + ret= isoburn_get_fifo_status(drive, &size, &free_bytes, &status_text); + if(ret>0 ) + sprintf(xorriso->info_text+strlen(xorriso->info_text), + " fifo %3d%% buf %3d%%", + (int) (100.0-100.0*((double) free_bytes)/(double) size), + buffer_fill); + if(current_time-last_time>0.2) + sprintf(xorriso->info_text+strlen(xorriso->info_text), " %5.1fx%s ", + measured_speed/speed_factor, speed_unit); + } + } else if(drive_status == BURN_DRIVE_CLOSING_SESSION || + drive_status == BURN_DRIVE_CLOSING_TRACK) + sprintf(xorriso->info_text, + "Closing track/session. Working since %.f seconds", + current_time-start_time); + else if(drive_status == BURN_DRIVE_FORMATTING) + sprintf(xorriso->info_text, "Formatting. Working since %.f seconds", + current_time-start_time); + else + sprintf(xorriso->info_text, + "Thank you for being patient for %.f seconds", + current_time-start_time); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0); + + for(i= 0; i<12; i++) { /* 2 usleeps more than supposed to be needed */ + Xorriso_process_msg_queues(xorriso, 0); + if(aborting<=0) + aborting= Xorriso_check_burn_abort(xorriso, 0); + usleep(100000); + now_time= Sfile_microtime(0); + if(((time_t) now_time) - ((time_t) current_time) >= 1 && + now_time - ((time_t) now_time) >= fract_offset) + break; + } + } + return(1); +} + + +int Xorriso__read_pacifier(IsoImage *image, IsoFileSource *filesource) +{ + struct XorrisO *xorriso; + + xorriso= (struct XorrisO *) iso_image_get_attached_data(image); + if(xorriso==NULL) + return(1); + xorriso->pacifier_count++; + if(xorriso->pacifier_count%10) + return(1); + Xorriso_pacifier_callback(xorriso, "nodes read", xorriso->pacifier_count, 0, + "", 0); + return(1); +} + + +int Xorriso_get_volume(struct XorrisO *xorriso, IsoImage **volume, + int flag) +{ + if(xorriso->in_volset_handle==NULL) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text,"No ISO image present."); + if(xorriso->indev[0]==0 && xorriso->outdev[0]==0) + sprintf(xorriso->info_text+strlen(xorriso->info_text), + " No -dev, -indev, or -outdev selected."); + else + sprintf(xorriso->info_text+strlen(xorriso->info_text), + " Possible program error with drive '%s'.", xorriso->indev); + + if(!xorriso->no_volset_present) + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + xorriso->no_volset_present= 1; + return(0); + } + *volume= (IsoImage *) xorriso->in_volset_handle; + xorriso->no_volset_present= 0; + return(*volume != NULL); +} + + +/* @param flag bit0=do not complain about non existent node */ +int Xorriso_node_from_path(struct XorrisO *xorriso, IsoImage *volume, + char *path, IsoNode **node, int flag) +{ + int ret; + char sfe[5*SfileadrL], *path_pt; + + path_pt= path; + if(path[0]==0) + path_pt= "/"; + *node= NULL; + ret= iso_tree_path_to_node(volume, path_pt, node); + Xorriso_process_msg_queues(xorriso,0); + if(ret<=0 || (*node)==NULL) { + if(!(flag&1)) { + sprintf(xorriso->info_text, "Cannot find path %s in loaded ISO image", + Text_shellsafe(path_pt, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + } + return(0); + } + return(1); +} + + +/* @param eff_path returns resulting effective path. + Must provide at least SfileadrL bytes of storage. + @param flag bit0= do not produce problem events (unless faulty path format) + bit1= work purely literally, do not use libisofs + bit2= (with bit1) this is an address in the disk world + bit3= return root directory as "/" and not as "" + bit4= (with bit2) determine type of disk file eff_path + and return 0 if not existing + bit5= (with bit3) this is not a parameter + bit6= insist in having an ISO image, even with bits1+2 + @return -1 = faulty path format, 0 = not found , + 1 = found simple node , 2 = found directory +*/ +int Xorriso_normalize_img_path(struct XorrisO *xorriso, char *wd, + char *img_path, char eff_path[], int flag) +{ + int ret, is_dir= 0, done= 0; + IsoImage *volume; + IsoDir *dir= NULL; + IsoNode *node= NULL; + char path[SfileadrL], *apt, *npt, sfe[5*SfileadrL], *cpt; + + if((flag&64) || !(flag&2)) { + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(ret); + } + + eff_path[0]= 0; + if(img_path[0]==0) { + if(flag&8) + strcpy(eff_path, "/"); + return(2); /* root directory */ + } + + apt= npt= path; + if(img_path[0]!='/') { + strcpy(path, wd); + ret= Sfile_add_to_path(path, img_path, 0); + if(ret<=0) + goto much_too_long; + } else + if(Sfile_str(path, img_path, 0)<=0) + return(-1); + + if(path[0]!='/') { + sprintf(xorriso->info_text, + "Internal error: Unresolvable relative addressing in iso_rr_path '%s'", + img_path); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FATAL", 0); + return(-1); + } else if(path[1]==0) { + if(flag&8) + strcpy(eff_path, "/"); + return(2); /* root directory */ + } + + for(npt= apt; !done; apt= npt+1) { + npt= strchr(apt, '/'); + if(npt==NULL) { + npt= apt+strlen(apt); + done= 1; + } else + *npt= 0; + if(*apt==0) { + *apt= '/'; + apt++; + if(done) + break; + continue; + } + if(strcmp(apt,".")==0) { + is_dir= 1; + continue; + } + if(strcmp(apt,"..")==0) { + if(!(flag&2)) { + node= (IsoNode *) dir; + if(node==NULL) { +bonked_root:; + sprintf(xorriso->info_text, + "Relative addressing in path exceeds root directory: %s", + Text_shellsafe(img_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(-1); + } + dir= iso_node_get_parent(node); + } + /* truncate eff_path */; + cpt= strrchr(eff_path, '/'); + if(cpt==NULL) /* ??? if not flag&2 then this is a bug */ + goto bonked_root; + *cpt= 0; + is_dir= 1; + continue; + } + ret= Sfile_add_to_path(eff_path, apt, 0); + if(ret<=0) { +much_too_long:; + sprintf(xorriso->info_text, "Effective path gets much too long (%d)", + (int) (strlen(eff_path)+strlen(apt)+1)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(-1); + } + if(!(flag&2)) { + dir= (IsoDir *) node; + ret= Xorriso_node_from_path(xorriso, volume, eff_path, &node, flag&1); + if(ret<=0) + return(0); + if(dir==NULL) /* could be false with "/dir/.." */ + dir= iso_node_get_parent(node); + is_dir= LIBISO_ISDIR(node); + } + } + if(flag&16) { + ret= Sfile_type(eff_path, + 1|(4*(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&32))) + )); + if(ret<0) + return(0); + if(ret==2) + is_dir= 1; + } + return(1+!!is_dir); +} + + +int Xorriso_get_node_by_path(struct XorrisO *xorriso, + char *in_path, char *eff_path, + IsoNode **node, int flag) +{ + int ret; + char path[SfileadrL]; + IsoImage *volume; + + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, in_path, path, 0); + if(ret<=0) + return(ret); + if(eff_path!=NULL) + strcpy(eff_path, path); + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(ret); + ret= Xorriso_node_from_path(xorriso, volume, path, node, 0); + if(ret<=0) + return(0); + return(1); +} + + +/* @param flag +*/ +int Xorriso_node_get_dev(struct XorrisO *xorriso, IsoNode *node, + char *path, dev_t *dev, int flag) +{ + *dev= iso_special_get_dev((IsoSpecial *) node); + return(1); +} + + +/* @param flag bit0= *node is already valid + bit1= add extra block for size estimation + bit2= complain loudely if path is missing in image +*/ +int Xorriso_fake_stbuf(struct XorrisO *xorriso, char *path, struct stat *stbuf, + IsoNode **node, int flag) +{ + int ret; + IsoImage *volume; + + memset((char *) stbuf, 0, sizeof(struct stat)); + if(!(flag&1)) { + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(-1); + ret= Xorriso_node_from_path(xorriso, volume, path, node, !(flag&4)); + if(ret<=0) + *node= NULL; + } + if(*node==NULL) + return(0); + + /* >>> stbuf->st_dev */ + /* >>> stbuf->st_ino */ + + stbuf->st_mode= iso_node_get_permissions(*node) & 07777; + if(LIBISO_ISDIR(*node)) + stbuf->st_mode|= S_IFDIR; + else if(LIBISO_ISREG(*node)) + stbuf->st_mode|= S_IFREG; + else if(LIBISO_ISLNK(*node)) + stbuf->st_mode|= S_IFLNK; + else if(LIBISO_ISCHR(*node)) { + stbuf->st_mode|= S_IFCHR; + Xorriso_node_get_dev(xorriso, *node, path, &(stbuf->st_rdev), 0); + } else if(LIBISO_ISBLK(*node)) { + stbuf->st_mode|= S_IFBLK; + Xorriso_node_get_dev(xorriso, *node, path, &(stbuf->st_rdev), 0); + } else if(LIBISO_ISFIFO(*node)) + stbuf->st_mode|= S_IFIFO; + else if(LIBISO_ISSOCK(*node)) + stbuf->st_mode|= S_IFSOCK; + else if(LIBISO_ISBOOT(*node)) + stbuf->st_mode|= Xorriso_IFBOOT; + + /* >>> With directories this should be : number of subdirs + 2 */ + /* >>> ??? How to obtain RR hardlink number for other types ? */ + stbuf->st_nlink= 1; + + stbuf->st_uid= iso_node_get_uid(*node); + stbuf->st_gid= iso_node_get_gid(*node); + + if(LIBISO_ISREG(*node)) + stbuf->st_size= iso_file_get_size((IsoFile *) *node)+ (2048 * !!(flag&2)); + else + stbuf->st_size= 0; + + stbuf->st_blksize= 2048; + stbuf->st_blocks= stbuf->st_size / (off_t) 2048; + if(stbuf->st_blocks * (off_t) 2048 != stbuf->st_size) + stbuf->st_blocks++; + + stbuf->st_atime= iso_node_get_atime(*node); + stbuf->st_mtime= iso_node_get_mtime(*node); + stbuf->st_ctime= iso_node_get_ctime(*node); + return(1); +} + + +/* @param flag >>> bit0= follow links (i.e. stat() rather than lstat() + bit1= do not return -2 on severe errors + bit2= complain loudely if path is missing in image +*/ +int Xorriso_iso_lstat(struct XorrisO *xorriso, char *path, struct stat *stbuf, + int flag) +{ + int ret; + IsoNode *node; + + if(flag&1) { + + /* >>> follow link in ISO image */; + + } + + ret= Xorriso_fake_stbuf(xorriso, path, stbuf, &node, flag&4); + if(ret>0) + return(0); + if(ret<0 && !(flag&2)) + return(-2); + return(-1); +} + + +/* @param flag bit0= give directory x-permission where is r-permission +*/ +int Xorriso_transfer_properties(struct XorrisO *xorriso, struct stat *stbuf, + IsoNode *node, int flag) +{ + mode_t mode; + + mode= stbuf->st_mode; + if((flag&1) && S_ISDIR(mode)) { + if(mode&S_IRUSR) + mode|= S_IXUSR; + if(mode&S_IRGRP) + mode|= S_IXGRP; + if(mode&S_IROTH) + mode|= S_IXOTH; + } + iso_node_set_permissions(node, mode & 07777); + iso_node_set_uid(node, stbuf->st_uid); + iso_node_set_gid(node, stbuf->st_gid); + iso_node_set_atime(node, stbuf->st_atime); + iso_node_set_mtime(node, stbuf->st_mtime); + iso_node_set_ctime(node, stbuf->st_ctime); + return(1); +} + + +int Xorriso_graft_split(struct XorrisO *xorriso, IsoImage *volume, + IsoDir *dir, char *disk_path, char *img_name, + char *nominal_source, char *nominal_target, + off_t size, IsoNode **node, int flag) +{ + int ret; + IsoDir *new_dir= NULL; + IsoNode *part_node; + int partno, total_parts; + off_t offset; + char part_name[SfileadrL], sfe[5*SfileadrL]; + + ret= iso_tree_add_new_dir(dir, img_name, &new_dir); + if(ret<0) + return(ret); + *node= (IsoNode *) new_dir; + + total_parts= size / xorriso->split_size; + if(size % xorriso->split_size) + total_parts++; + for(partno= 1; partno<=total_parts; partno++) { + offset = xorriso->split_size * (off_t) (partno-1); + Splitpart__compose(part_name, partno, total_parts, offset, + xorriso->split_size, size, 0); + ret= Xorriso_tree_graft_node(xorriso, volume, + new_dir, disk_path, part_name, + nominal_source, nominal_target, + offset, xorriso->split_size, + &part_node, 8); + if(ret<=0) + return(0); + } + sprintf(xorriso->info_text, "Split into %d parts: %s", + total_parts, Text_shellsafe(nominal_target, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(1); +} + + +/* + @param flag bit3= cut_out_node: offset and size are valid +*/ +int Xorriso_tree_graft_node(struct XorrisO *xorriso, IsoImage *volume, + IsoDir *dir, char *disk_path, char *img_name, + char *nominal_source, char *nominal_target, + off_t offset, off_t cut_size, + IsoNode **node, int flag) +{ + int ret; + struct stat stbuf; + char sfe[5*SfileadrL]; + off_t size= 0; + + if(flag&8) { + if(cut_size > xorriso->file_size_limit && xorriso->file_size_limit > 0) { + sprintf(xorriso->info_text, + "File piece exceeds size limit of %.f bytes: %.f from %s\n", + (double) xorriso->file_size_limit, (double) cut_size, + Text_shellsafe(disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + ret= iso_tree_add_new_cut_out_node(volume, dir, img_name, disk_path, + offset, cut_size, node); + if(ret<0) + goto ex; + } else { + + if(stat(disk_path, &stbuf)!=-1) + if(S_ISREG(stbuf.st_mode)) + size= stbuf.st_size; + if(xorriso->split_size > 0 && size > xorriso->split_size) { + ret= Xorriso_graft_split(xorriso, volume, dir, disk_path, img_name, + nominal_source, nominal_target, size, + node, 0); + if(ret<=0) + goto ex; + return(1); + } else if(size > xorriso->file_size_limit && xorriso->file_size_limit > 0) { + sprintf(xorriso->info_text, + "File exceeds size limit of %.f bytes: %s\n", + (double) xorriso->file_size_limit, + Text_shellsafe(disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + ret= iso_tree_add_new_node(volume, dir, img_name, disk_path, node); + if(ret<0) + goto ex; + } +ex:; + if(ret<0) { + Xorriso_process_msg_queues(xorriso,0); + Xorriso_report_iso_error(xorriso, nominal_source, ret, + "Cannot add node to tree", 0, "FAILURE", 1|2); + return(ret); + } + if(LIBISO_ISREG(*node)) + xorriso->pacifier_byte_count+= iso_file_get_size((IsoFile *) *node); + return(1); +} + + +/* @param flag bit0= recursion is active + bit1= do not report added files +*/ +int Xorriso_add_tree(struct XorrisO *xorriso, IsoDir *dir, + char *img_dir_path, char *disk_dir_path, + struct LinkiteM *link_stack, int flag) +{ + IsoImage *volume; + IsoNode *node; + IsoSymlink *iso_symlink; + int ret, target_is_dir, source_is_dir, source_is_link, fret, was_failure= 0; + int do_not_dive, target_is_split= 0; + struct DirseQ *dirseq= NULL; + char *name, *img_name, *srcpt, *stbuf_src= ""; + struct stat stbuf, hstbuf; + dev_t dir_dev; + struct LinkiteM *own_link_stack; + char *sfe= NULL, *sfe2= NULL; + char *disk_path= NULL, *img_path= NULL, *link_target= NULL; + + /* Avoiding large local memory objects in order to save stack space */ + sfe= malloc(5*SfileadrL); + sfe2= malloc(5*SfileadrL); + disk_path= malloc(2*SfileadrL); + img_path= malloc(2*SfileadrL); + link_target= calloc(SfileadrL, 1); + if(sfe==NULL || sfe2==NULL || disk_path==NULL || img_path==NULL || + link_target==NULL) { + Xorriso_no_malloc_memory(xorriso, &sfe, 0); + {ret= -1; goto ex;} + } + + own_link_stack= link_stack; + + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + goto ex; + + stbuf_src= disk_dir_path; + if(lstat(disk_dir_path, &stbuf)==-1) + goto cannot_open_dir; + dir_dev= stbuf.st_dev; + if(S_ISLNK(stbuf.st_mode)) { + if(!(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&1)))) + {ret= 2; goto ex;} + stbuf_src= disk_dir_path; + if(stat(disk_dir_path, &stbuf)==-1) + goto cannot_open_dir; + if(dir_dev != stbuf.st_dev && + !(xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&1)))) + {ret= 2; goto ex;} + } + ret= Dirseq_new(&dirseq, disk_dir_path, 1); + if(ret<0) { + sprintf(xorriso->info_text,"Failed to create source filesystem iterator"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + {ret= -1; goto ex;} + } + if(ret==0) { +cannot_open_dir:; + Xorriso_msgs_submit(xorriso, 0, disk_dir_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text,"Cannot open as source directory: %s", + Text_shellsafe(disk_dir_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + + if(Sfile_str(disk_path, disk_dir_path,0)<=0) + {ret= -1; goto ex;} + if(disk_path[0]==0 || disk_path[strlen(disk_path)-1]!='/') + strcat(disk_path,"/"); + name= disk_path+strlen(disk_path); + if(Sfile_str(img_path, img_dir_path, 0)<=0) + {ret= -1; goto ex;} + if(img_path[0] || img_path[strlen(img_path)-1]!='/') + strcat(img_path,"/"); + img_name= img_path+strlen(img_path); + + while(1) { /* loop over directory content */ + stbuf_src= ""; + Linkitem_reset_stack(&own_link_stack, link_stack, 0); + srcpt= disk_path; + Xorriso_process_msg_queues(xorriso,0); + ret= Dirseq_next_adr(dirseq,name,0); /* name is a pointer into disk_path */ + if(ret==0) + break; + if(ret<0) { + sprintf(xorriso->info_text,"Failed to obtain next directory entry"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + {ret= -1; goto ex;} + } + + /* compare exclusions against disk_path resp. name */ + ret= Xorriso_path_is_excluded(xorriso, disk_path, 0); /* (is never param) */ + if(ret<0) + {ret= -1; goto ex;} + if(ret>0) + continue; + + strcpy(img_name, name); + if(Xorriso_much_too_long(xorriso, strlen(img_path), 0)<=0) + {ret= 0; goto was_problem;} + if(Xorriso_much_too_long(xorriso, strlen(srcpt), 0)<=0) + {ret= 0; goto was_problem;} + stbuf_src= srcpt; + if(lstat(srcpt, &stbuf)==-1) { +cannot_lstat:; + Xorriso_msgs_submit(xorriso, 0, srcpt, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, + "Cannot determine attributes of source file %s", + Text_shellsafe(srcpt, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + ret= 0; goto was_problem; + } + source_is_dir= 0; + source_is_link= S_ISLNK(stbuf.st_mode); + if(xorriso->do_follow_links && source_is_link) { + /* Xorriso_hop_link checks for wide link loops */ + ret= Xorriso_hop_link(xorriso, srcpt, &own_link_stack, &hstbuf, 0); + if(ret<0) + goto was_problem; + if(ret==1) { + ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 0); + if(ret<=0) + goto was_problem; + srcpt= link_target; + stbuf_src= srcpt; + if(lstat(srcpt, &stbuf)==-1) + goto cannot_lstat; + } else { + if(Xorriso_eval_problem_status(xorriso, 0, 1|2)<0) + {ret= 0; goto was_problem;} + ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 1); + if(ret<=0) + goto was_problem; + } + } else if (S_ISLNK(stbuf.st_mode)) { + ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 1); + if(ret<=0) + goto was_problem; + } + do_not_dive= 0; + if(S_ISDIR(stbuf.st_mode)) { + source_is_dir= 1; + if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount) + do_not_dive= 1; + } + + /* does a node exist with this name ? */ + node= NULL; + ret= Xorriso_node_from_path(xorriso, volume, img_path, &node, 1); + if(ret>0) { + target_is_dir= LIBISO_ISDIR(node); + target_is_split= 0; + if(target_is_dir) + target_is_split= Xorriso_is_split(xorriso, "", (void *) node, 1); + + if(!((target_is_dir && !target_is_split) && source_is_dir)) { + Xorriso_process_msg_queues(xorriso,0); + + /* handle overwrite situation */; + if(xorriso->do_overwrite==1 || + (xorriso->do_overwrite==2 && !(target_is_dir && !target_is_split))) { + ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, img_path, 1|8); + if(ret<=0) + goto was_problem; + if(ret==3) { + sprintf(xorriso->info_text, "User revoked adding of: %s", + Text_shellsafe(img_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + ret= 0; goto was_problem; + } + node= NULL; + } else { + Xorriso_msgs_submit(xorriso, 0, srcpt, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, + "While grafting %s : file object exists and may not be overwritten by %s", + Text_shellsafe(img_path,sfe,0), Text_shellsafe(stbuf_src,sfe2,0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto was_problem; + } + } + } + + if(node==NULL) { + if(S_ISLNK(stbuf.st_mode)) { + + /* ??? NG : A80107 : is this solved now ? */ + /* <<< One should rather change libisofs so that iso_tree_add_node() + adds a disk_link as RR link, if RR is enabled */ + + ret= iso_tree_add_new_symlink(dir, img_name, link_target, &iso_symlink); + node= (IsoNode *) iso_symlink; + if(ret>0) { + ret= Xorriso_transfer_properties(xorriso, &stbuf, node, 0); + if(ret<=0) + goto was_problem; + } else { + Xorriso_report_iso_error(xorriso, stbuf_src, ret, + "Cannot create symbolic link", 0, "FAILURE", 1|2); + {ret= 0; goto was_problem;} + } + } else { + ret= Xorriso_tree_graft_node(xorriso, volume, dir, srcpt, img_name, + "", img_path, (off_t) 0, (off_t) 0, + &node, 0); + } + } + if(node==NULL) { + Xorriso_process_msg_queues(xorriso,0); + Xorriso_msgs_submit(xorriso, 0, stbuf_src, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, "Grafting failed: %s = %s", + Text_shellsafe(img_path,sfe,0), Text_shellsafe(stbuf_src,sfe2,0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto was_problem; + } + + xorriso->pacifier_count++; + if((xorriso->pacifier_count%100)==0) + Xorriso_pacifier_callback(xorriso, "files added", xorriso->pacifier_count, + xorriso->pacifier_total, "", 0); + + xorriso->volset_change_pending= 1; + if(source_is_dir) { + if(do_not_dive) { + sprintf(xorriso->info_text, "Did not follow mount point : %s", + Text_shellsafe(disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + } else { + ret= Xorriso_add_tree(xorriso, (IsoDir *) node, + img_path, disk_path, own_link_stack, 1|(flag&2)); + } + if(ret<=0) + goto was_problem; + } + + continue; /* regular bottom of loop */ +was_problem:; + was_failure= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); + if(fret<0) + goto ex; + } + + ret= 1; +ex: + if(sfe!=NULL) + free(sfe); + if(sfe2!=NULL) + free(sfe2); + if(disk_path!=NULL) + free(disk_path); + if(img_path!=NULL) + free(img_path); + if(link_target!=NULL) + free(link_target); + Xorriso_process_msg_queues(xorriso,0); + Linkitem_reset_stack(&own_link_stack, link_stack, 0); + Dirseq_destroy(&dirseq, 0); + if(ret<=0) + return(ret); + return(!was_failure); +} + + +/* @param flag bit0= cut_out mode : base on leaf parent directory +*/ +int Xorriso_copy_implicit_properties(struct XorrisO *xorriso, IsoDir *dir, + char *full_img_path, char *img_path, char *full_disk_path, int flag) +{ + int ret, nfic, nic, nfdc, d, i; + char nfi[SfileadrL], ni[SfileadrL], nfd[SfileadrL], *cpt; + char sfe[5*SfileadrL]; + struct stat stbuf; + + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, full_img_path, nfi, + 1|2); + if(ret<=0) + return(ret); + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, img_path, ni, 1|2); + if(ret<=0) + return(ret); + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, full_disk_path, nfd, + 1|2|4); + if(ret<=0) + return(ret); + nfic= Sfile_count_components(nfi, 0); + nic= Sfile_count_components(ni, 0); + nfdc= Sfile_count_components(nfd, 0); + d= nfic-(flag&1)-nic; + if(d<0) + return(-1); + if(d>nfdc) + return(0); + for(i= 0; iinfo_text, + "Copied properties for %s", Text_shellsafe(ni, sfe, 0)); + sprintf(xorriso->info_text+strlen(xorriso->info_text), + " from %s", Text_shellsafe(nfd, sfe, 0)); + if(!((flag&1) && d==0)) + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + return(1); +} + + +/* @param bit0= copy link target properties rather than link properties + bit1= give directory x-permission where is r-permission +*/ +int Xorriso_copy_properties(struct XorrisO *xorriso, + char *disk_path, char *img_path, int flag) +{ + int ret; + IsoNode *node; + struct stat stbuf; + + ret= Xorriso_get_node_by_path(xorriso, img_path, NULL, &node, 0); + if(ret<=0) + return(ret); + if(lstat(disk_path, &stbuf)==-1) + return(0); + Xorriso_transfer_properties(xorriso, &stbuf, node, (flag&2)>>1); + xorriso->volset_change_pending= 1; + return(1); +} + + +/* @param boss_iter Opaque handle to be forwarded to actions in ISO image + Set to NULL if calling this function from outside ISO world + @param flag bit0= mkdir: graft in as empty directory, not as copy from disk + bit1= do not report added files + bit2= -follow, -not_*: this is not a command parameter + bit3= use offset and cut_size for cut_out_node + bit4= return 3 on rejection by exclusion or user + bit5= if directory then do not add sub tree + bit7= no special handling of split file directories + @return <=0 = error , 1 = added simple node , 2 = added directory , + 3 = rejected +*/ +int Xorriso_graft_in(struct XorrisO *xorriso, void *boss_iter, + char *disk_path, char *img_path, + off_t offset, off_t cut_size, int flag) +{ + IsoImage *volume; + char path[SfileadrL], *apt, *npt, *cpt, sfe[5*SfileadrL], sfe2[5*SfileadrL]; + char *disk_path_pt, resolved_disk_path[SfileadrL]; + IsoDir *dir, *hdir; + IsoNode *node; + int done= 0, is_dir= 0, l, ret, target_is_dir, source_is_dir, resolve_link= 0; + int target_is_split; + struct stat stbuf; + + ret= Xorriso_path_is_excluded(xorriso, disk_path, !(flag&4)); + if(ret<0) + return(ret); + if(ret>0) + return(3*!!(flag&16)); + + for(cpt= img_path; 1; cpt++) { + cpt= strstr(cpt,"/."); + if(cpt==NULL) + break; + if(cpt[2]=='.') { + if(cpt[3]=='/' || cpt[3]==0) + break; + } else if(cpt[2]=='/' || cpt[2]==0) + break; + } + if(cpt!=NULL) { + Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, + "Unsupported relative addressing in iso_rr_path %s (disk: %s)", + Text_shellsafe(img_path, sfe, 0), Text_shellsafe(disk_path, sfe2, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + return(0); + } + + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(ret); + + strncpy(path, img_path, sizeof(path)-1); + path[sizeof(path)-1]= 0; + apt= npt= path; + + if(!(flag&1)) { + ret= lstat(disk_path, &stbuf); + if(ret!=-1) { + if(S_ISDIR(stbuf.st_mode)) + is_dir= 1; + else if((stbuf.st_mode&S_IFMT)==S_IFLNK && + (xorriso->do_follow_links || + (xorriso->do_follow_param && !(flag&4)))) { + resolve_link= 1; + ret= stat(disk_path, &stbuf); + if(ret!=-1) { + if(S_ISDIR(stbuf.st_mode)) + is_dir= 1; + } + } + } + if(ret == -1) { + Xorriso_process_msg_queues(xorriso,0); + Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, + "Cannot determine attributes of source file %s", + Text_shellsafe(disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + return(0); + } + if(S_ISDIR(stbuf.st_mode)) { + is_dir= 1; + } else { + l= strlen(img_path); + if(l>0) + if(img_path[l-1]=='/') + l= 0; + if(l==0) { + Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, + "Source '%s' is not a directory. Target '%s' would be.", + Text_shellsafe(disk_path, sfe, 0), Text_shellsafe(img_path, sfe2, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + } + } + + dir= iso_image_get_root(volume); + if(dir==NULL) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "While grafting '%s' : no root node available", img_path); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(0); + } + for(npt= apt; !done; apt= npt+1) { + npt= strchr(apt, '/'); + if(npt==NULL) { + npt= apt+strlen(apt); + done= 1; + } else + *npt= 0; + if(*apt==0) { + *apt= '/'; + apt++; + if(done) + goto attach_source; + continue; + } + source_is_dir= (is_dir || (flag&1) || !done); + ret= Xorriso_node_from_path(xorriso, volume, path, &node, 1); + if(ret>0) { + target_is_dir= LIBISO_ISDIR(node); + + target_is_split= 0; + if(target_is_dir && !(flag&128)) + target_is_split= Xorriso_is_split(xorriso, "", (void *) node, 1); + + if(!((target_is_dir && !target_is_split) && source_is_dir)) { + Xorriso_process_msg_queues(xorriso,0); + + /* handle overwrite situation */; + if(xorriso->do_overwrite==1 || + (xorriso->do_overwrite==2 && !(target_is_dir && !target_is_split))) { + ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, path, 1|8); + if(ret<=0) + return(ret); + if(ret==3) { + sprintf(xorriso->info_text, "User revoked adding of: %s", + Text_shellsafe(disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(3*!!(flag&16)); + } + node= NULL; + goto handle_path_node; + } + + Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, + "While grafting '%s' : '%s' exists and may not be overwritten", + img_path, path); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + dir= (IsoDir *) node; + } + +handle_path_node:; + if(node==NULL && source_is_dir) { /* make a directory */ + ret= iso_tree_add_new_dir(dir, apt, &hdir); + if(ret<0) { + Xorriso_process_msg_queues(xorriso,0); + Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); + Xorriso_report_iso_error(xorriso, img_path, ret, + "Cannot create directory", 0, "FAILURE", 1); + sprintf(xorriso->info_text, + "While grafting '%s' : could not insert '%s'", img_path, path); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + dir= hdir; + xorriso->volset_change_pending= 1; + iso_node_set_ctime((IsoNode *) dir, time(NULL)); + iso_node_set_uid((IsoNode *) dir, geteuid()); + iso_node_set_gid((IsoNode *) dir, getegid()); + + if(disk_path!=NULL && !done) + Xorriso_copy_implicit_properties(xorriso, dir, img_path, path, disk_path, + !!(flag&8)); + + } + if(done) { +attach_source:; + if(flag&1) { + /* directory node was created above */; + + } else if(is_dir) { + Xorriso_transfer_properties(xorriso, &stbuf, (IsoNode *) dir, 0); + if(!(flag&32)) { + ret= Xorriso_add_tree(xorriso, dir, img_path, disk_path, NULL, + flag&2); + if(ret<=0) + return(ret); + } + } else { + if(resolve_link) { + ret= Xorriso_resolve_link(xorriso, disk_path, resolved_disk_path, 0); + if(ret<=0) + return(ret); + disk_path_pt= resolved_disk_path; + } else + disk_path_pt= disk_path; + + ret= Xorriso_tree_graft_node(xorriso, volume, dir, disk_path_pt, apt, + disk_path, img_path, + offset, cut_size, &node, flag&8); + if(ret<=0) { + sprintf(xorriso->info_text, "Grafting failed: %s = %s", + Text_shellsafe(img_path,sfe,0), Text_shellsafe(disk_path,sfe2,0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + xorriso->volset_change_pending= 1; + iso_node_set_name(node, apt); + + xorriso->pacifier_count++; + if(xorriso->pacifier_count%100 && !(flag&2)) + Xorriso_pacifier_callback(xorriso, "files added", + xorriso->pacifier_count, + xorriso->pacifier_total, "", 0); + } + } else + *npt= '/'; + } + Xorriso_process_msg_queues(xorriso,0); + return(1+!!is_dir); +} + + +/* @param flag bit0= -follow: disk_path is not a command parameter +*/ +int Xorriso_cut_out(struct XorrisO *xorriso, char *disk_path, + off_t startbyte, off_t bytecount, char *iso_rr_path, int flag) +{ + int ret; + char eff_source[SfileadrL], eff_dest[SfileadrL], sfe[SfileadrL*5]; + struct stat stbuf; + + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, eff_source, + 2|4); + if(ret<=0) + return(ret); + ret= Xorriso_path_is_excluded(xorriso, disk_path, !(flag&1)); + if(ret!=0) + return(0); + + if(lstat(eff_source, &stbuf)==-1) { + Xorriso_msgs_submit(xorriso, 0, eff_source, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, "-cut_out: Cannot determine type of %s", + Text_shellsafe(eff_source, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + return(0); + } + + if((stbuf.st_mode&S_IFMT) == S_IFLNK) { + if(!(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&1)))) + goto unsupported_type; + if(stat(eff_source, &stbuf)==-1) { + Xorriso_msgs_submit(xorriso, 0, eff_source, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, + "-cut_out: Cannot determine link target type of %s", + Text_shellsafe(eff_source, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); + return(0); + } + } + if(S_ISREG(stbuf.st_mode)) { + if(stbuf.st_sizeinfo_text, + "-cut_out: Byte offset %.f larger than file size %.f", + (double) startbyte, (double) stbuf.st_size); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "SORRY", 0); + return(0); + } + } else { +unsupported_type:; + Xorriso_msgs_submit(xorriso, 0, eff_source, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, "-cut_out: Unsupported file type (%s) with %s", + Ftypetxt(stbuf.st_mode, 0), Text_shellsafe(eff_source, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + return(0); + } + + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, iso_rr_path, eff_dest, + 2); + if(ret<=0) + return(ret); + + ret= Xorriso_graft_in(xorriso, NULL, eff_source, eff_dest, + startbyte, bytecount, 8); + return(ret); +} + + +/* @param flag bit0= in_node is valid, do not resolve img_path + bit1= test mode: print DEBUG messages + @return <0 = error, + 0 = surely not identical regular files , + 1 = surely identical + 2 = potentially depending on unknown disk file (e.g. -cut_out) +*/ +int Xorriso_restore_is_identical(struct XorrisO *xorriso, void *in_node, + char *img_path, char *disk_path, + char type_text[5], int flag) +{ + int ret; + unsigned int fs_id; + dev_t dev_id; + ino_t ino_id; + IsoStream *stream; + IsoImage *volume; + IsoNode *node; + struct stat stbuf; + int dummy; + + memset(type_text, 0, 5); + if(!xorriso->volset_change_pending) + return(0); + if(flag&1) { + node= (IsoNode *) in_node; + } else { + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(-1); + ret= Xorriso_node_from_path(xorriso, volume, img_path, &node, 1); + if(ret<=0) + return(-1); + } + ret= Xorriso__file_start_lba(node, &dummy, 0); + if(ret != 0) { + Xorriso_process_msg_queues(xorriso, 0); + return(0); + } + if(!LIBISO_ISREG(node)) + return(0); + stream= iso_file_get_stream((IsoFile *) node); + memcpy(type_text, stream->class->type, 4); + iso_stream_get_id(stream, &fs_id, &dev_id, &ino_id); + if(flag&2) { + sprintf(xorriso->info_text, "%s : fs=%d dev=%.f ino=%.f (%s)", + img_path, fs_id, (double) dev_id, (double) ino_id, type_text); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + } + ret= stat(disk_path, &stbuf); + if(ret==-1) + return(0); + if(flag&2) { + sprintf(xorriso->info_text, "%s : dev=%.f ino=%.f", + disk_path, (double) stbuf.st_dev, (double) stbuf.st_ino); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + } + if(fs_id!=1) + return(2); + + /* >>> obtain underlying dev_t ino_t of type "cout" */; + + if(strcmp(type_text, "fsrc")!=0) + return(2); + if(stbuf.st_dev==dev_id && stbuf.st_ino==ino_id) + return(1); + return(0); +} + + +/* @param flag bit0= minimal transfer: access permissions only + bit1= keep directory open: keep owner, allow rwx for owner + and push directory onto xorriso->perm_stack +*/ +int Xorriso_restore_properties(struct XorrisO *xorriso, char *disk_path, + IsoNode *node, int flag) +{ + int ret, is_dir= 0; + mode_t mode; + uid_t uid; + gid_t gid; + struct utimbuf utime_buffer; + char sfe[5*SfileadrL]; + struct stat stbuf; + + ret= lstat(disk_path, &stbuf); + if(ret==-1) { + sprintf(xorriso->info_text, + "Cannot obtain properties of disk file %s", + Text_shellsafe(disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + return(0); + } + uid= stbuf.st_uid; + + is_dir= S_ISDIR(stbuf.st_mode); + mode= iso_node_get_permissions(node); + if(is_dir && (flag&2)) { + ret= Xorriso_fake_stbuf(xorriso, "", &stbuf, &node, 1); + if(ret<=0) + return(0); + ret= Permstack_push(&(xorriso->perm_stack), disk_path, &stbuf, 0); + if(ret<=0) { + Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); + strcpy(xorriso->info_text, + "Cannot memorize permissions for disk directory"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(-1); + } + mode|= S_IRUSR|S_IWUSR|S_IXUSR; + } + ret= chmod(disk_path, mode); + if(ret==-1) { + sprintf(xorriso->info_text, + "Cannot change access permissions of disk file %s", + Text_shellsafe(disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + return(0); + } + if(flag&1) + return(1); + + gid= iso_node_get_gid(node); + if(!(S_ISDIR(stbuf.st_mode) && (flag&2))) + uid= iso_node_get_uid(node); + chown(disk_path, uid, gid); /* don't complain if it fails */ + utime_buffer.actime= iso_node_get_atime(node); + utime_buffer.modtime= iso_node_get_mtime(node); + ret= utime(disk_path,&utime_buffer); + if(ret==-1) { + sprintf(xorriso->info_text, + "Cannot change atime, mtime of disk file %s", + Text_shellsafe(disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + return(0); + } + return(1); +} + + +/* @param flag + bit1= minimal transfer: access permissions only + bit2= keep directory open: keep owner, allow rwx for owner + push to xorriso->perm_stack +*/ +int Xorriso_restore_implicit_properties(struct XorrisO *xorriso, + char *full_disk_path, char *disk_path, char *full_img_path, int flag) +{ + int ret, nfic, ndc, nfdc, d, i; + char nfi[SfileadrL], nd[SfileadrL], nfd[SfileadrL], *cpt; + char sfe[5*SfileadrL]; + struct stat stbuf; + IsoNode *node; + + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, full_disk_path, nfd, + 1|2|4); + if(ret<=0) + return(ret); + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, nd, 1|2); + if(ret<=0) + return(ret); + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, full_img_path, nfi, + 1|2); + if(ret<=0) + return(ret); + nfdc= Sfile_count_components(nfd, 0); + ndc= Sfile_count_components(nd, 0); + nfic= Sfile_count_components(nfi, 0); + d= nfdc-ndc; + if(d<0) + return(-1); + if(d>nfic) + return(0); + for(i= 0; i>1)&3)); + if(ret<=0) + return(ret); + sprintf(xorriso->info_text, + "Restored properties for %s", Text_shellsafe(nd, sfe, 0)); + sprintf(xorriso->info_text+strlen(xorriso->info_text), + " from %s", Text_shellsafe(nfi, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + return(1); +} + + +/* @param flag bit0= Minimal transfer: access permissions only + bit1= offset and bytes is valid for writing to regular file + bit2= This is not a parameter. Do not report if ignored + bit3= do not restore properties + bit4= issue pacifier messages with long lasting copying + @return <0 severe error , 0 failure , 1 success , + 2 regularly not installed (disallowed device, UNIX domain socket) +*/ +int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node, + char *img_path, char *disk_path, + off_t offset, off_t bytes, int flag) +{ + int ret= 0, write_fd= -1, wanted, wret, open_flags, l_errno= 0; + int target_deleted= 0; + char *what= "[unknown filetype]", sfe[5*SfileadrL], sfe2[5*SfileadrL]; + char buf[32*1024], type_text[5], temp_path[SfileadrL]; + char *link_target, *open_path_pt= NULL; + off_t todo= 0, size, seek_ret, last_p_count= 0, already_done; + void *data_stream= NULL; + mode_t mode; + dev_t dev= 0; + struct stat stbuf; + struct utimbuf utime_buffer; + + if(LIBISO_ISDIR(node)) { + what= "directory"; + ret= mkdir(disk_path, 0777); + l_errno= errno; + + } else if(LIBISO_ISREG(node)) { + what= "regular file"; + ret= Xorriso_iso_file_open(xorriso, img_path, (void *) node, &data_stream, + 1); + if(ret<=0) + goto ex; + open_path_pt= disk_path; + ret= stat(open_path_pt, &stbuf); + if(flag&2) { + if(ret!=-1 && !S_ISREG(stbuf.st_mode)) { + sprintf(xorriso->info_text, + "Restore offset demanded. But filesystem path leads to non-data file %s", + Text_shellsafe(disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); + l_errno= 0; + goto cannot_restore; + } + } else { + /* If source and target are the same disk file then do not copy content */ + ret= Xorriso_restore_is_identical(xorriso, (void *) node, img_path, + disk_path, type_text, 1); + if(ret<0) + goto ex; + if(ret==1) { + /* preliminarily emulate touch (might get overridden later) */ + utime_buffer.actime= stbuf.st_atime; + utime_buffer.modtime= time(0); + utime(disk_path,&utime_buffer); + goto restore_properties; + } + if(ret==2) { + /* Extract to temporary file and rename only after copying */ + ret= Xorriso_make_tmp_path(xorriso, disk_path, temp_path, &write_fd, 0); + if(ret<=0) + goto ex; + open_path_pt= temp_path; + } + } + if(write_fd==-1) { + open_flags= O_WRONLY|O_CREAT; + if(offset==0 || !(flag&2)) + open_flags|= O_EXCL; + write_fd= open(open_path_pt, open_flags, S_IRUSR|S_IWUSR); + l_errno= errno; + if(write_fd==-1) + goto cannot_restore; + } + todo= size= iso_file_get_size((IsoFile *) node); + if(flag&2) { + if(bytesinfo_text, + "Cannot address byte %.f in filesystem path %s", + (double) offset, Text_shellsafe(open_path_pt, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); + goto cannot_restore; + } + } + while(todo>0) { + wanted= sizeof(buf); + if(wanted>todo) + wanted= todo; + ret= Xorriso_iso_file_read(xorriso, data_stream, buf, wanted, 0); + if(ret<=0) { + if(xorriso->extract_error_mode == 0) { + close(write_fd); + write_fd= -1; + already_done= (size - todo) / (off_t) 2048; + already_done*= (off_t) 2048; + sprintf(xorriso->info_text, + "Starting best_effort handling on ISO file %s at byte %.f", + Text_shellsafe(img_path, sfe, 0), (double) already_done); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + ret= Xorriso_read_file_data(xorriso, node, img_path, open_path_pt, + already_done, already_done, size - already_done, 2); + if(ret >= 0) + xorriso->pacifier_byte_count+= todo; + if(ret > 0) + todo= 0; + else + todo= -1; + } + if(ret <= 0) { + sprintf(xorriso->info_text, "Cannot read all bytes from ISO file %s", + Text_shellsafe(img_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + } + break; + } + wret= write(write_fd, buf, ret); + if(wret>=0) { + todo-= wret; + xorriso->pacifier_byte_count+= wret; + if((flag&16) && + xorriso->pacifier_byte_count - last_p_count >= 128*1024) { + Xorriso_pacifier_callback(xorriso, "files restored", + xorriso->pacifier_count, + xorriso->pacifier_total, "", 2|4); + last_p_count= xorriso->pacifier_byte_count; + } + } + if(wret != ret) { + sprintf(xorriso->info_text, + "Cannot write all bytes to disk filesystem path %s", + Text_shellsafe(open_path_pt, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); + break; + } + } + if(write_fd > 0) + close(write_fd); + write_fd= -1; + if(todo > 0 && xorriso->extract_error_mode == 2 && open_path_pt != NULL) { + unlink(open_path_pt); + target_deleted= 1; + } + Xorriso_iso_file_close(xorriso, &data_stream, 0); + data_stream= NULL; + if(temp_path==open_path_pt && !target_deleted) { + ret= rename(temp_path, disk_path); + if(ret==-1) { + sprintf(xorriso->info_text, + "Cannot rename temporary path %s to final disk path %s", + Text_shellsafe(temp_path, sfe, 0), + Text_shellsafe(disk_path, sfe2, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); + unlink(temp_path); + ret= 0; goto ex; + } + } + ret= -(todo > 0); + l_errno= 0; + + } else if(LIBISO_ISLNK(node)) { + what= "symbolic link"; + link_target= (char *) iso_symlink_get_dest((IsoSymlink *) node); + ret= symlink(link_target, disk_path); + l_errno= errno; + + } else if(LIBISO_ISCHR(node)) { + what= "character device"; + if(xorriso->allow_restore!=2) { +ignored:; + if(!(flag&4)) { + sprintf(xorriso->info_text, "Ignored file type: %s %s = %s", what, + Text_shellsafe(img_path,sfe,0), Text_shellsafe(disk_path,sfe2,0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + } + {ret= 2; goto ex;} + } + mode= S_IFCHR | 0777; + ret= Xorriso_node_get_dev(xorriso, node, img_path, &dev, 0); + if(ret<=0) + goto ex; + if(dev == (dev_t) 1) { +probably_damaged:; + sprintf(xorriso->info_text, + "Most probably damaged device file not restored: mknod %s %s 0 1", + Text_shellsafe(disk_path, sfe, 0), LIBISO_ISCHR(node) ? "c" : "b"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + ret= 0; goto ex; + } + ret= mknod(disk_path, mode, dev); + l_errno= errno; + + } else if(LIBISO_ISBLK(node)) { + what= "block device"; + if(xorriso->allow_restore!=2) + goto ignored; + mode= S_IFBLK | 0777; + ret= Xorriso_node_get_dev(xorriso, node, img_path, &dev, 0); + if(ret<=0) + goto ex; + if(dev == (dev_t) 1) + goto probably_damaged; + ret= mknod(disk_path, mode, dev); + l_errno= errno; + + } else if(LIBISO_ISFIFO(node)) { + what= "named pipe"; + mode= S_IFIFO | 0777; + ret= mknod(disk_path, mode, dev); + l_errno= errno; + + } else if(LIBISO_ISSOCK(node)) { + what= "unix socket"; + /* Restoring a socket file is not possible. One rather needs to restart + the service which temporarily created the socket. */ + goto ignored; + + } else { + sprintf(xorriso->info_text, "Cannot restore file type '%s'", what); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + ret= 0; goto ex; + } + if(ret==-1) { +cannot_restore:; + sprintf(xorriso->info_text, + "Cannot restore %s to disk filesystem: %s", + what, Text_shellsafe(img_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, l_errno, "FAILURE", 0); + ret= 0; goto ex; + } + +restore_properties:; + if((flag&8) || LIBISO_ISLNK(node)) + ret= 1; + else + ret= Xorriso_restore_properties(xorriso, disk_path, node, flag&1); + if(todo < 0) + ret= 0; +ex:; + if(write_fd >= 0) { + close(write_fd); + if(ret <= 0 && xorriso->extract_error_mode == 2 && open_path_pt != NULL) + unlink(open_path_pt); + } + if(data_stream!=NULL) + Xorriso_iso_file_close(xorriso, &data_stream, 0); + return(ret); +} + + +/* Handle overwrite situation in disk filesystem. + @param node intended source of overwriting or NULL + @param flag + bit4= return 3 on rejection by exclusion or user +*/ +int Xorriso_restore_overwrite(struct XorrisO *xorriso, + IsoNode *node, char *img_path, + char *path, char *nominal_path, + struct stat *stbuf, int flag) +{ + int ret; + char sfe[5*SfileadrL], sfe2[5*SfileadrL], type_text[5]; + + Xorriso_process_msg_queues(xorriso,0); + if(xorriso->do_overwrite==1 || + (xorriso->do_overwrite==2 && !S_ISDIR(stbuf->st_mode))) { + + ret= Xorriso_restore_is_identical(xorriso, (void *) node, img_path, + path, type_text, (node!=NULL)); + if(ret<0) + return(ret); + if(ret>0) /* will be handled properly by restore functions */ + ret= Xorriso_reassure_restore(xorriso, path, 8); + else + ret= Xorriso_rmx(xorriso, (off_t) 0, path, 8); + if(ret<=0) + return(ret); + if(ret==3) { + sprintf(xorriso->info_text, "User revoked restoring of (ISO) file: %s", + Text_shellsafe(img_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(3*!!(flag&16)); + } + return(1); + } + Xorriso_msgs_submit(xorriso, 0, nominal_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, + "While restoring %s : %s exists and may not be overwritten", + Text_shellsafe(nominal_path, sfe, 0), strcmp(nominal_path, path)==0 ? + "file object" : Text_shellsafe(path, sfe2, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); +} + + +/* + @param flag bit0= offset and bytes is valid for writing to regular file + bit1= do not report copied files + bit2= -follow, -not_*: this is not a command parameter + bit3= keep directory open: keep owner, allow rwx for owner + bit6= this is a copy action: do not fake times and ownership + @return <=0 = error , 1 = added leaf file object , 2 = added directory , +*/ +int Xorriso_restore_disk_object(struct XorrisO *xorriso, + char *img_path, IsoNode *node, + char *disk_path, + off_t offset, off_t bytes, int flag) +{ + int ret, i, split_count= 0, partno, total_parts, leaf_is_split= 0; + off_t total_bytes, was_byte_count; + char *part_name, part_path[SfileadrL], *img_path_pt; + char sfe[5*SfileadrL], sfe2[5*SfileadrL]; + IsoImage *volume; + IsoNode *part_node, *first_part_node= NULL; + struct SplitparT *split_parts= NULL; + struct stat stbuf; + + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + goto ex; + + was_byte_count= xorriso->pacifier_byte_count; + + if(LIBISO_ISDIR(node) && xorriso->do_concat_split) + leaf_is_split= Xorriso_identify_split(xorriso, img_path, node, + &split_parts, &split_count, &stbuf, 1|2); + if(leaf_is_split) { + /* map all files in directory img_path into regular file disk_path */ + + for(i=0 ; itotal_bytes) + bytes= total_bytes-offset; + ret= Xorriso_tree_restore_node(xorriso, part_node, part_path, disk_path, + offset, bytes, + (!!(flag&64)) | 2 | (flag&4) | 8 | ( 16 * !(flag&2))); + if(ret<=0) + goto restoring_failed; + } + if(first_part_node!=NULL) + Xorriso_restore_properties(xorriso, disk_path, first_part_node, + !!(flag&64)); + goto went_well; + } + +#ifdef Osirrox_not_yeT + + if(resolve_link) { + ret= Xorriso_resolve_link(xorriso, disk_path, resolved_disk_path, 0); + if(ret<=0) + goto ex; + disk_path_pt= resolved_disk_path; + } else + +#endif /* Osirrox_not_yeT */ + + img_path_pt= img_path; + + ret= Xorriso_tree_restore_node(xorriso, node, img_path_pt, disk_path, + offset, bytes, + (flag&(4|8)) | (!!(flag&64)) | ((flag&1)<<1) | ( 16 * !(flag&2))); + if(ret>0 && (flag&8)) + ret= Xorriso_restore_properties(xorriso, disk_path, node, 2 | !!(flag&64)); + if(ret<=0) { +restoring_failed:; + sprintf(xorriso->info_text, "Restoring failed: %s = %s", + Text_shellsafe(img_path,sfe,0), Text_shellsafe(disk_path,sfe2,0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + if(ret==2) + {ret= 3; goto ex;} +went_well:; + xorriso->pacifier_count++; + if(!(flag&2)) + Xorriso_pacifier_callback(xorriso, "files restored", + xorriso->pacifier_count, + xorriso->pacifier_total, "", 4); + ret= 1; +ex:; + if(split_parts!=NULL) + Splitparts_destroy(&split_parts, split_count, 0); + return(ret); +} + + +/* @param flag bit0= source is a directory and not to be restored as split file + @return <=0 error , 1=collision handled , 2=no collision , 3=revoked by user +*/ +int Xorriso_handle_collision(struct XorrisO *xorriso, + IsoNode *node, char *img_path, + char *disk_path, char *nominal_disk_path, + int *stbuf_ret, int flag) +{ + int ret, target_is_dir= 0, target_is_link= 0, stat_ret; + struct stat target_stbuf, lt_stbuf; + + /* does a disk file exist with this name ? */ + *stbuf_ret= lstat(disk_path, &target_stbuf); + + if(*stbuf_ret==-1) + return(2); + + target_is_link= S_ISLNK(target_stbuf.st_mode); + if(target_is_link) { + stat_ret= stat(disk_path, <_stbuf); + if(stat_ret!=-1) + target_is_dir= S_ISDIR(lt_stbuf.st_mode); + } else { + target_is_dir= S_ISDIR(target_stbuf.st_mode); + } + if(target_is_dir && (!target_is_link) && !(flag&1)) { + strcpy(xorriso->info_text, "Attempt to replace DISK directory "); + Text_shellsafe(nominal_disk_path, + xorriso->info_text+strlen(xorriso->info_text), 0); + strcat(xorriso->info_text, " by ISO file "); + Text_shellsafe(img_path, xorriso->info_text+strlen(xorriso->info_text), 0); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + + if(!(target_is_dir && (flag&1))) { + Xorriso_process_msg_queues(xorriso,0); + ret= Xorriso_restore_overwrite(xorriso, node, img_path, disk_path, + nominal_disk_path, &target_stbuf, 16); + if(ret==3) + return(3); + if(ret<=0) + return(ret); + *stbuf_ret= -1; /* It might still exist but will be handled properly */ + } + return(1); +} + + +/* @param flag bit0= recursion is active + bit1= do not report restored files + bit6= this is a copy action: do not fake times and ownership +*/ +int Xorriso_restore_tree(struct XorrisO *xorriso, IsoDir *dir, + char *img_dir_path, char *disk_dir_path, + off_t boss_mem, + struct LinkiteM *link_stack, int flag) +{ + IsoImage *volume; + IsoNode *node; + IsoDirIter *iter= NULL; + IsoNode **node_array= NULL; + int node_count, node_idx; + int ret, source_is_dir, source_is_link, fret, was_failure= 0; + int do_not_dive, source_is_split= 0, len_dp, len_ip, stbuf_ret, hflag, hret; + char *name, *disk_name, *leaf_name, *srcpt, *stbuf_src= ""; + struct LinkiteM *own_link_stack; + char *sfe= NULL, *sfe2= NULL; + char *disk_path= NULL, *img_path= NULL, *link_target= NULL; + off_t mem; + struct PermiteM *perm_stack_mem; + struct stat stbuf; + + perm_stack_mem= xorriso->perm_stack; + + /* Avoiding large local memory objects in order to save stack space */ + sfe= malloc(5*SfileadrL); + sfe2= malloc(5*SfileadrL); + disk_path= malloc(2*SfileadrL); + img_path= malloc(2*SfileadrL); + link_target= malloc(SfileadrL); + if(sfe==NULL || sfe2==NULL || disk_path==NULL || img_path==NULL || + link_target==NULL) { + Xorriso_no_malloc_memory(xorriso, &sfe, 0); + {ret= -1; goto ex;} + } + + own_link_stack= link_stack; + + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + goto ex; + + stbuf_src= img_dir_path; + node= (IsoNode *) dir; + ret= Xorriso_fake_stbuf(xorriso, stbuf_src, &stbuf, &node, 1); + if(ret<=0) { + Xorriso_msgs_submit(xorriso, 0, disk_dir_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text,"Cannot open as (ISO) source directory: %s", + Text_shellsafe(img_dir_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + +#ifdef Osirrox_not_yeT + + dev_t dir_dev; + dir_dev= stbuf.st_dev; + + if(S_ISLNK(stbuf.st_mode)) { + if(!(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&1)))) + {ret= 2; goto ex;} + stbuf_src= disk_dir_path; + if(stat(disk_dir_path, &stbuf)==-1) + goto cannot_open_dir; + if(dir_dev != stbuf.st_dev && + !(xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&1)))) + {ret= 2; goto ex;} + } + +#endif /* Osirrox_not_yeT */ + + if(!S_ISDIR(stbuf.st_mode)) { + Xorriso_msgs_submit(xorriso, 0, disk_dir_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text,"Is not a directory in ISO image: %s", + Text_shellsafe(img_dir_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + + mem= boss_mem; + ret= Xorriso_findi_iter(xorriso, dir, &mem, &iter, &node_array, &node_count, + &node_idx, &node, 1|4); + if(ret<=0) + goto ex; + + if(Sfile_str(img_path, img_dir_path,0)<=0) { +much_too_long:; + Xorriso_much_too_long(xorriso, SfileadrL, 2); + {ret= 0; goto ex;} + } + if(img_path[0]==0 || img_path[strlen(img_path)-1]!='/') + strcat(img_path,"/"); + name= img_path+strlen(img_path); + if(Sfile_str(disk_path, disk_dir_path, 0)<=0) + goto much_too_long; + if(disk_path[0]==0 || disk_path[strlen(disk_path)-1]!='/') + strcat(disk_path,"/"); + disk_name= disk_path+strlen(disk_path); + + len_dp= strlen(disk_path); + len_ip= strlen(img_path); + + while(1) { /* loop over ISO directory content */ + stbuf_src= ""; + +#ifdef Osirrox_not_yeT + + Linkitem_reset_stack(&own_link_stack, link_stack, 0); + +#endif + + srcpt= img_path; + Xorriso_process_msg_queues(xorriso,0); + ret= Xorriso_findi_iter(xorriso, dir, &mem, &iter, &node_array, &node_count, + &node_idx, &node, 0); + if(ret<0) + goto ex; + if(ret==0 || xorriso->request_to_abort) + break; + leaf_name= (char *) iso_node_get_name(node); + if(Xorriso_much_too_long(xorriso, len_dp + strlen(leaf_name)+1, 0)<=0) + {ret= 0; goto was_problem;} + if(Xorriso_much_too_long(xorriso, len_ip + strlen(leaf_name)+1, 0)<=0) + {ret= 0; goto was_problem;} + /* name is a pointer into img_path */ + strcpy(name, leaf_name); + strcpy(disk_name, leaf_name); + + stbuf_src= srcpt; + ret= Xorriso_fake_stbuf(xorriso, img_path, &stbuf, &node, 1); + if(ret<=0) + goto was_problem; + source_is_dir= 0; + source_is_link= S_ISLNK(stbuf.st_mode); + +#ifdef Osirrox_not_yeT + + if(xorriso->do_follow_links && source_is_link) { + /* Xorriso_hop_link checks for wide link loops */ + ret= Xorriso_hop_link(xorriso, srcpt, &own_link_stack, &hstbuf, 0); + if(ret<0) + goto was_problem; + if(ret==1) { + ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 0); + if(ret<=0) + goto was_problem; + srcpt= link_target; + stbuf_src= srcpt; + if(lstat(srcpt, &stbuf)==-1) + goto cannot_lstat; + } else { + if(Xorriso_eval_problem_status(xorriso, 0, 1|2)<0) + {ret= 0; goto was_problem;} + } + } else if (S_ISLNK(stbuf.st_mode)) { + ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 1); + if(ret<=0) + goto was_problem; + } + +#endif /* Osirrox_not_yeT */ + + do_not_dive= 0; + if(S_ISDIR(stbuf.st_mode)) + source_is_dir= 1; + source_is_split= 0; + if(source_is_dir) + source_is_split= Xorriso_is_split(xorriso, img_path, node, 1|2); + if(source_is_split) + do_not_dive= 1; + ret= Xorriso_handle_collision(xorriso, node, img_path, disk_path, disk_path, + &stbuf_ret, (source_is_dir && !source_is_split)); + if(ret<=0 || ret==3) + goto was_problem; + + if(stbuf_ret!=-1) { /* (Can only happen with directory) */ + Xorriso_auto_chmod(xorriso, disk_path, 0); + } else { + hflag= 4 | (flag & (2|64)); + if(source_is_dir && !do_not_dive) + hflag|= 8; /* keep directory open for user */ + ret= Xorriso_restore_disk_object(xorriso, img_path, node, disk_path, + (off_t) 0, (off_t) 0, hflag); + if(ret<=0) + goto was_problem; + } + if(source_is_dir && !do_not_dive) { + ret= Xorriso_restore_tree(xorriso, (IsoDir *) node, + img_path, disk_path, mem, + own_link_stack, 1|(flag&2)); + /* eventually restore exact access permissions of directory */ + hret= Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, + !!(flag&64)); + if(hret<=0 && hretperm_stack), perm_stack_mem, xorriso, !!(flag&64)); + } + + ret= 1; +ex: + Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, !!(flag&64)); + if(sfe!=NULL) + free(sfe); + if(sfe2!=NULL) + free(sfe2); + if(disk_path!=NULL) + free(disk_path); + if(img_path!=NULL) + free(img_path); + if(link_target!=NULL) + free(link_target); + Xorriso_findi_iter(xorriso, dir, &mem, &iter, &node_array, &node_count, + &node_idx, &node, (1<<31)); + + Xorriso_process_msg_queues(xorriso,0); + +#ifdef Osirrox_not_yeT + + Linkitem_reset_stack(&own_link_stack, link_stack, 0); + +#endif + + if(ret<=0) + return(ret); + return(!was_failure); +} + + +/* + @param flag + >>> bit0= mkdir: graft in as empty directory, not as copy from iso + bit1= do not report copied files + bit2= -follow, -not_*: this is not a command parameter + bit3= use offset and cut_size for -paste_in + bit4= return 3 on rejection by exclusion or user + bit5= if directory then do not add sub tree + bit6= this is a copy action: do not fake times and ownership + @return <=0 = error , 1 = added leaf file object , 2 = added directory , + 3 = rejected +*/ +int Xorriso_restore(struct XorrisO *xorriso, + char *img_path, char *disk_path, + off_t offset, off_t bytes, int flag) +{ + IsoImage *volume; + char path[SfileadrL], *apt, *npt, sfe[5*SfileadrL]; + IsoNode *node= NULL; + int done= 0, is_dir= 0, ret, source_is_dir, stbuf_ret, hret; + int leaf_is_split= 0, source_is_split= 0, new_dir_made= 0; + struct stat stbuf; + struct PermiteM *perm_stack_mem; + + perm_stack_mem= xorriso->perm_stack; + + ret= Xorriso_path_is_excluded(xorriso, disk_path, !(flag&4)); + if(ret<0) + goto ex; + if(ret>0) + {ret= 3*!!(flag&16); goto ex;} + + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + goto ex; + + strncpy(path, disk_path, sizeof(path)-1); + path[sizeof(path)-1]= 0; + apt= npt= path; + + if(!(flag&1)) { + ret= Xorriso_fake_stbuf(xorriso, img_path, &stbuf, &node, 0); + if(ret>0) { + if(S_ISDIR(stbuf.st_mode)) + is_dir= 1; + +#ifdef Osirrox_not_yeT + else if((stbuf.st_mode&S_IFMT)==S_IFLNK && + (xorriso->do_follow_links || + (xorriso->do_follow_param && !(flag&4)))) { + resolve_link= 1; + ret= Xorriso_iso_lstat(xorriso, img_path, &stbuf, 1|2); + if(ret!=-1) { + if(S_ISDIR(stbuf.st_mode)) + is_dir= 1; + } + } +#endif /* Osirrox_not_yeT */ + + } else { + Xorriso_process_msg_queues(xorriso,0); + Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, + "Cannot determine attributes of (ISO) source file %s", + Text_shellsafe(img_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + ret= 0; goto ex; + } + if(is_dir && xorriso->do_concat_split) + leaf_is_split= Xorriso_is_split(xorriso, img_path, node, 1|2); + } + for(npt= apt; !done; apt= npt+1) { + npt= strchr(apt, '/'); + if(npt==NULL) { + npt= apt+strlen(apt); + done= 1; + } else + *npt= 0; + if(*apt==0) { + *apt= '/'; + apt++; + if(done) + goto attach_source; + continue; + } + source_is_dir= (is_dir || (flag&1) || !done); + source_is_split= done && leaf_is_split; + + if((flag&8) && done) { + + /* ??? move down from Xorriso_paste_in() : + check whether target does not exist or both are regular */; + + } else { + ret= Xorriso_handle_collision(xorriso, node, img_path, path, disk_path, + &stbuf_ret, (source_is_dir && !source_is_split)); + if(ret<=0 || ret==3) + goto ex; + } + + new_dir_made= 0; + if(stbuf_ret==-1 && (source_is_dir && !source_is_split)) { + /* make a directory */ + ret= mkdir(path, 0777); + if(ret==-1) { + Xorriso_process_msg_queues(xorriso,0); + Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, + "While restoring '%s' : could not insert '%s'", disk_path, path); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); + {ret= 0; goto ex;} + } + if(!done) { + /* keep rwx for the owner */ + Xorriso_restore_implicit_properties(xorriso, disk_path, path, + img_path, 4); + } + new_dir_made= 1; + } else if(source_is_dir && !source_is_split) { + Xorriso_auto_chmod(xorriso, path, 0); + } + if(done) { +attach_source:; + + if(flag&1) { + /* directory was created above */; + + } else if(is_dir && !source_is_split) { + if(new_dir_made) /* keep open and push to Permstack */ + Xorriso_restore_properties(xorriso, disk_path, node, 2 | !!(flag&64)); + if(!(flag&32)) { + ret= Xorriso_restore_tree(xorriso, (IsoDir *) node, img_path, path, + (off_t) 0, NULL, flag&(2|64)); + if(ret<=0) + goto ex; + if(new_dir_made && !(flag&64)) + /* set timestamps which Permstack_pop() will not set */ + Xorriso_restore_properties(xorriso, disk_path, node, 2); + } + } else { + ret= Xorriso_restore_disk_object(xorriso, img_path, node, path, + offset, bytes, (flag & (2|4|64)) | !!(flag&8)); + if(ret<=0) + goto ex; + } + } else + *npt= '/'; + } + Xorriso_process_msg_queues(xorriso,0); + ret= 1 + (is_dir && !leaf_is_split); +ex:; + /* restore exact access permissions of stacked paths */ + hret= Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, + 2 | !!(flag&64)); + if(hret<=0 && hretwdx, disk_path, eff_dest, + 2|4); + if(ret<=0) + return(ret); + ret= Xorriso_path_is_excluded(xorriso, disk_path, !(flag&1)); + if(ret!=0) + return(0); + ret= stat(eff_dest, &stbuf); + if(ret!=-1 && !S_ISREG(stbuf.st_mode)) { + Xorriso_msgs_submit(xorriso, 0, eff_dest, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, + "-paste_in: DISK file %s exists and is not a data file", + Text_shellsafe(eff_source, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + return(0); + } + + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, iso_rr_path, + eff_source, 2); + if(ret<=0) + return(ret); + ret= Xorriso_fake_stbuf(xorriso, eff_source, &stbuf, &node, 4); + if(ret<=0) + return(0); + if(!S_ISREG(stbuf.st_mode)) { + Xorriso_msgs_submit(xorriso, 0, eff_dest, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, "-paste_in: ISO file %s is not a data file", + Text_shellsafe(eff_source, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + return(0); + } + + /* >>> eventually obtain parameters from file name */; + + ret= Xorriso_restore(xorriso, eff_source, eff_dest, startbyte, bytecount, 8); + return(ret); +} + + +int Xorriso_process_msg_queues(struct XorrisO *xorriso, int flag) +{ + int ret, error_code= 0, os_errno= 0, count= 0, pass, imgid, tunneled; + char severity[80]; + + if(!xorriso->libs_are_started) + return(1); + for(pass= 0; pass< 2; pass++) { + while(1) { + tunneled= 0; + if(pass==0) + ret= iso_obtain_msgs("ALL", &error_code, &imgid, + xorriso->info_text, severity); + else { + ret= burn_msgs_obtain("ALL", &error_code, xorriso->info_text, &os_errno, + severity); + if((error_code>=0x00030000 && error_code<0x00040000) || + (error_code>=0x00050000 && error_code<0x00060000)) + tunneled= -1; /* "libisofs:" */ + else if(error_code>=0x00060000 && error_code<0x00070000) + tunneled= 1; /* "libisoburn:" */ + } + if(ret<=0) + break; + + /* <<< tunneled MISHAP from libisoburn through libburn + or well known error codes of MISHAP events + With libburn-0.4.4 this is not necessary */ + if(error_code==0x5ff73 || error_code==0x3ff73 || + error_code==0x3feb9 || error_code==0x3feb2) + strcpy(severity, "MISHAP"); + else if(error_code==0x51001) + strcpy(severity, "ERRFILE"); + + Xorriso_msgs_submit(xorriso, error_code, xorriso->info_text, os_errno, + severity, ((pass+tunneled)+1)<<2); + count++; + } + } + if(xorriso->library_msg_direct_print && count>0) { + sprintf(xorriso->info_text," (%d library messages repeated by xorriso)\n", + count); + Xorriso_info(xorriso, 0); + } + return(1); +} + + +/* @param flag + bit3=report to info channel (else to result channel) +*/ +int Xorriso_toc_line(struct XorrisO *xorriso, int flag) +{ + if(!(flag & 8)) { + Xorriso_result(xorriso,0); + return(1); + } + strcpy(xorriso->info_text, xorriso->result_line); + Xorriso_info(xorriso, 0); + return(1); +} + + +/* @param flag bit0= no output if no boot record was found + bit1= short form + bit3= report to info channel (else to result channel) +*/ +int Xorriso_show_boot_info(struct XorrisO *xorriso, int flag) +{ + int ret, bin_path_valid= 0,has_isolinux_mbr= 0, i; + unsigned int mbr_lba= 0; + off_t lb0_count; + char *respt, sfe[5*SfileadrL], path[SfileadrL]; + unsigned char lb0[2048]; + struct burn_drive_info *dinfo; + struct burn_drive *drive; + IsoImage *image= NULL; + ElToritoBootImage *bootimg; + IsoFile *bootimg_node; + IsoBoot *bootcat_node; + + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to print boot info", 0); + if(ret<=0) + return(0); + respt= xorriso->result_line; + image= isoburn_get_attached_image(drive); + if(image == NULL) { + ret= 0; +no_boot:; + if(!(flag & 1)) { + sprintf(respt, "Boot record : none\n"); + Xorriso_toc_line(xorriso, flag & 8); + } + return(ret); + } + + /* Using the nodes with extreme care . They might be deleted meanwhile. */ + ret= iso_image_get_boot_image(image, &bootimg, &bootimg_node, &bootcat_node); + if(ret != 1) + goto no_boot; + ret= Xorriso_path_from_node(xorriso, NULL, xorriso->loaded_boot_bin_lba, + path, 1); + if(ret > 0) + bin_path_valid= 1; + sprintf(respt, "Boot record : El Torito"); + if(bin_path_valid) + ret= Xorriso_is_isohybrid(xorriso, bootimg_node, 0); + else + ret= 0; + if(ret > 0) { + /* Load and examine potential MBR */ + ret= burn_read_data(drive, (off_t) 0, (char *) lb0, (off_t) 2048, + &lb0_count, 2); + if(ret > 0) { + has_isolinux_mbr= 1; + if(lb0[510] != 0x55 || lb0[511] != 0xaa) + has_isolinux_mbr= 0; + mbr_lba= lb0[432] | (lb0[433] << 8) | (lb0[434] << 16) | (lb0[435] << 24); + mbr_lba/= 4; + if(mbr_lba != xorriso->loaded_boot_bin_lba) + has_isolinux_mbr= 0; + if(has_isolinux_mbr) { + for(i= 0; i < 426; i++) + if(strncmp((char *) (lb0 + i), "isolinux", 8) == 0) + break; + if(i >= 426) + has_isolinux_mbr= 0; + } + for(i= 462; i < 510; i++) + if(lb0[i]) + break; + if(i < 510) + has_isolinux_mbr= 0; + } + if(has_isolinux_mbr) + strcat(respt, " , ISOLINUX isohybrid MBR pointing to boot image"); + else + strcat(respt, " , ISOLINUX boot image capable of isohybrid"); + } + strcat(respt, "\n"); + Xorriso_toc_line(xorriso, flag & 8); + if(flag & 2) + return(1); + if(bin_path_valid) + sprintf(respt, "Boot bin_path: %s\n", Text_shellsafe(path, sfe, 0)); + else if(xorriso->loaded_boot_bin_lba <= 0) + sprintf(respt, "Boot bin_path: -not-found-at-load-time-\n"); + else + sprintf(respt, "Boot bin_path: -not-found-any-more-by-lba=%d\n", + xorriso->loaded_boot_bin_lba); + Xorriso_toc_line(xorriso, flag & 8); + if(xorriso->loaded_boot_cat_path[0]) + sprintf(respt, "Boot cat_path: %s\n", + Text_shellsafe(xorriso->loaded_boot_cat_path, sfe, 0)); + else + sprintf(respt, "Boot cat_path: -not-found-at-load-time-\n"); + Xorriso_toc_line(xorriso, flag & 8); + return(1); +} + + +/* @param flag bit0=short report form + bit1=report about output drive + bit2=do not try to read ISO heads + bit3=report to info channel (else to result channel) +*/ +int Xorriso_toc(struct XorrisO *xorriso, int flag) +{ + int num_sessions= 0, num_tracks= 0, lba= 0, nwa= -1, pmin, psec, pframe, ret; + int track_count= 0, session_no, track_no, profile_no= -1, track_size; + int last_track_start= 0, last_track_size= -1, num_data= 0, is_data= 0; + int is_inout_drive= 0, drive_role, status, num_formats; + int num_payload= 0, num_wasted= 0, num_nondata= 0; + char profile_name[80],*respt,*devadr, *typetext= ""; + struct burn_toc_entry toc_entry; + struct burn_drive_info *dinfo; + struct burn_drive *drive; + enum burn_disc_status s; + char mem_text[80]; + off_t start_byte= 0, num_free= 0, size; + unsigned dummy; + struct isoburn_toc_disc *disc= NULL; + struct isoburn_toc_session **sessions; + struct isoburn_toc_track **tracks; + int image_blocks; + char volume_id[33]; + struct burn_toc_entry next_toc_entry; + + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to print Table Of Content", flag&2); + if(ret<=0) + return(0); + + respt= xorriso->result_line; + + if(strcmp(xorriso->indev, xorriso->outdev)==0) + is_inout_drive= 1; + if(flag&2) + devadr= xorriso->outdev; + else + devadr= xorriso->indev; + sprintf(respt, "Drive current: %s '%s'\n", + (is_inout_drive ? "-dev" : (flag&2 ? "-outdev" : "-indev")), + devadr); + Xorriso_toc_line(xorriso, flag & 8); + sprintf(respt, "Drive type : vendor '%s' product '%s' revision '%s'\n", + dinfo[0].vendor, dinfo[0].product, dinfo[0].revision); + if(!(flag&1)) + Xorriso_toc_line(xorriso, flag & 8); + + sprintf(respt, "Media current: "); + ret= burn_disc_get_profile(drive, &profile_no, profile_name); + if (profile_no > 0 && ret > 0) { + if (profile_name[0]) + sprintf(respt+strlen(respt), "%s", profile_name); + else + sprintf(respt+strlen(respt), "%4.4Xh", profile_no); + drive_role= burn_drive_get_drive_role(drive); + if(drive_role==2) + sprintf(respt+strlen(respt), ", overwriteable"); + else if(drive_role==0 || drive_role==3) + sprintf(respt+strlen(respt), ", sequential"); + strcat(respt, "\n"); + } else + sprintf(respt+strlen(respt), "is not recognizable\n"); + Xorriso_toc_line(xorriso, flag & 8); + + sprintf(respt, "Media status : "); + s= isoburn_disc_get_status(drive); + if (s == BURN_DISC_FULL) { + sprintf(respt+strlen(respt), "is written , is closed\n"); + } else if (s == BURN_DISC_APPENDABLE) { + sprintf(respt+strlen(respt), "is written , is appendable\n"); + } else if (s == BURN_DISC_BLANK) { + sprintf(respt+strlen(respt), "is blank\n"); + } else if (s == BURN_DISC_EMPTY) + sprintf(respt+strlen(respt), "is not present\n"); + else + sprintf(respt+strlen(respt), "is not recognizable\n"); + Xorriso_toc_line(xorriso, flag & 8); + + if(s == BURN_DISC_BLANK) { + sprintf(respt, "Media summary: 0 sessions, 0 data blocks, 0 data"); + num_free= isoburn_disc_available_space(drive, NULL); + Sfile_scale((double) num_free, mem_text,5,1e4,1); + sprintf(respt+strlen(respt), ", %s free\n", mem_text); + Xorriso_toc_line(xorriso, flag & 8); + } + if(s != BURN_DISC_FULL && s != BURN_DISC_APPENDABLE) + return(1); + if(xorriso->request_to_abort) + return(1); + + if(!(flag & 2)) + Xorriso_show_boot_info(xorriso, 1 | (flag & 8) | ((flag & 1) << 1)); + + disc= isoburn_toc_drive_get_disc(drive); + if(flag & 4) + sprintf(respt, "TOC layout : %3s , %9s , %10s\n", + "Idx", "sbsector", "Size"); + else + sprintf(respt, "TOC layout : %3s , %9s , %10s , %s\n", + "Idx", "sbsector", "Size", "Volume Id"); + if(!(flag&1)) + Xorriso_toc_line(xorriso, flag & 8); + + if (disc==NULL) { + Xorriso_process_msg_queues(xorriso,0); + ret= isoburn_get_min_start_byte(drive, &start_byte, 0); + nwa= start_byte / 2048; + if(ret<=0) { + Xorriso_process_msg_queues(xorriso,0); + if(flag&1) + return(0); + sprintf(xorriso->info_text, "Cannot obtain Table Of Content"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + + /* fabricate TOC */ + typetext= "Other session"; + if(flag & 4) { + ret= 0; + typetext= "Session "; + } else + ret= isoburn_read_iso_head(drive, 0, &image_blocks, volume_id, 1); + if(ret>0) { + sprintf(respt, "ISO session : %3d , %9d , %9ds , %s\n", + 1, 0, image_blocks, volume_id); + nwa= image_blocks; + } else { + nwa= 0; + ret= burn_disc_get_formats(drive, &status, &size, &dummy, + &num_formats); + if(ret>0 && status==BURN_FORMAT_IS_FORMATTED) + nwa= size/2048; + sprintf(respt, "%13s: %3d , %9d , %9ds , \n", + typetext, 1, 0, nwa); + } + if(!(flag&1)) + Xorriso_toc_line(xorriso, flag & 8); + last_track_start= lba; + num_payload= num_data= last_track_size= nwa; + num_sessions= 1; + } else { + sessions= isoburn_toc_disc_get_sessions(disc, &num_sessions); + for (session_no= 0; session_norequest_to_abort); + session_no++) { + tracks= isoburn_toc_session_get_tracks(sessions[session_no], &num_tracks); + if (tracks==NULL) + continue; + for(track_no= 0; track_norequest_to_abort); + track_no++) { + track_count++; + is_data= 0; + isoburn_toc_track_get_entry(tracks[track_no], &toc_entry); + if (toc_entry.extensions_valid & 1) { + /* DVD extension valid */ + lba= toc_entry.start_lba; + track_size= toc_entry.track_blocks; + } else { + lba= burn_msf_to_lba(toc_entry.pmin, toc_entry.psec, + toc_entry.pframe); + if(track_no==num_tracks-1) { + isoburn_toc_session_get_leadout_entry(sessions[session_no], + &next_toc_entry); + } else { + isoburn_toc_track_get_entry(tracks[track_no+1], &next_toc_entry); + } + track_size= burn_msf_to_lba(next_toc_entry.pmin, next_toc_entry.psec, + next_toc_entry.pframe) - lba; + } + if(flag&(1|4)) + ret= 0; + else { + ret= isoburn_read_iso_head(drive, lba, &image_blocks, volume_id, 1); + if(image_blocks > track_size) { + sprintf(xorriso->info_text, + "Session %d bears ISO image size %ds larger than track size %ds", + session_no + 1, image_blocks, track_size); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", + 0); + image_blocks= track_size; + } + } + if(ret>0 && track_no==0) { + sprintf(respt, "ISO session : %3d , %9d , %9ds , %s\n", + session_no+1, lba, image_blocks , volume_id); + } else if(ret>0) { + sprintf(respt, "ISO track : %3d , %9d , %9ds , %s\n", + track_count, lba, image_blocks , volume_id); + } else if(track_no==0) { + typetext= "Other session"; + if(flag & 4) + typetext= "Session "; + sprintf(respt, "%13s: %3d , %9d , %9ds , \n", + typetext, session_no+1, lba, track_size); + } else { + typetext= "Other track "; + if(flag & 4) + typetext= "Track "; + sprintf(respt, "%13s: %3d , %9d , %9ds , \n", + typetext, track_count, lba, track_size); + } + if(!(flag&1)) + Xorriso_toc_line(xorriso, flag & 8); + if(track_no>0) + num_payload+= lba - last_track_start; + last_track_start= lba; + if((toc_entry.control&7)>=4) /* data track */ + is_data= 1; + } + isoburn_toc_session_get_leadout_entry(sessions[session_no], &toc_entry); + if (toc_entry.extensions_valid & 1) { + lba= toc_entry.start_lba; + burn_lba_to_msf(lba, &pmin, &psec, &pframe); + } else { + lba= burn_msf_to_lba(pmin, psec, pframe); + lba= burn_msf_to_lba(toc_entry.pmin, toc_entry.psec, toc_entry.pframe); + } + last_track_size= lba - last_track_start; + num_payload+= last_track_size; + if(is_data) + num_data+= last_track_size; + } + } + if(xorriso->request_to_abort) + return(1); + num_wasted= lba - num_payload; + num_nondata= lba - num_data; + Sfile_scale(((double) num_data) * 2048.0, mem_text,5,1e4,1); + + sprintf(respt, "Media summary: %d session%s, %d data blocks, %s data", + num_sessions, (num_sessions==1 ? "" : "s"), num_data, mem_text); + num_free= isoburn_disc_available_space(drive, NULL); + Sfile_scale((double) num_free, mem_text,5,1e4,1); + sprintf(respt+strlen(respt), ", %s free", mem_text); + + sprintf(respt+strlen(respt), "\n"); + Xorriso_toc_line(xorriso, flag & 8); + + if (s==BURN_DISC_APPENDABLE && nwa!=0) { + ret= isoburn_disc_track_lba_nwa(drive, NULL, 0, &lba, &nwa); + if(ret>0) { + sprintf(respt, "Media nwa : %ds\n", nwa); + if(!(flag&1)) + Xorriso_toc_line(xorriso, flag & 8); + } + } + + if (disc!=NULL) + isoburn_toc_disc_free(disc); + Xorriso_process_msg_queues(xorriso,0); + return(1); +} + + +int Xorriso_show_devices(struct XorrisO *xorriso, int flag) +{ + char adr[BURN_DRIVE_ADR_LEN]; + int i, j, max_dev_len= 1, pad; + struct burn_drive_info *drive_list= NULL; + unsigned int drive_count; + char *respt, perms[8]; + struct stat stbuf; + + sprintf(xorriso->info_text, "Beginning to scan for devices ...\n"); + Xorriso_info(xorriso,0); + + burn_drive_clear_whitelist(); + while(!burn_drive_scan(&drive_list, &drive_count)) { + Xorriso_process_msg_queues(xorriso,0); + usleep(100000); + } + Xorriso_process_msg_queues(xorriso,0); + if(drive_count <= 0) { + + /* >>> was a drive_list created at all ? */ + /* >>> must it be freed ? */ + + sprintf(xorriso->info_text, "No drives found"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + sprintf(xorriso->info_text, "Full drive scan done\n"); + Xorriso_info(xorriso,0); + + sprintf(xorriso->info_text, "-----------------------------------------------------------------------------\n"); + Xorriso_info(xorriso,0); + respt= xorriso->result_line; + for(i= 0; i < drive_count && !(xorriso->request_to_abort); i++) { + if(burn_drive_get_adr(&(drive_list[i]), adr)<=0) + strcpy(adr, "-get_adr_failed-"); + Xorriso_process_msg_queues(xorriso,0); + if(strlen(adr)>max_dev_len) + max_dev_len= strlen(adr); + } + for(i= 0; i < drive_count && !(xorriso->request_to_abort); i++) { + if(burn_drive_get_adr(&(drive_list[i]), adr)<=0) + strcpy(adr, "-get_adr_failed-"); + Xorriso_process_msg_queues(xorriso,0); + if(stat(adr,&stbuf)==-1) { + sprintf(perms,"errno=%d",errno); + } else { + strcpy(perms,"------"); + if(stbuf.st_mode&S_IRUSR) perms[0]= 'r'; + if(stbuf.st_mode&S_IWUSR) perms[1]= 'w'; + if(stbuf.st_mode&S_IRGRP) perms[2]= 'r'; + if(stbuf.st_mode&S_IWGRP) perms[3]= 'w'; + if(stbuf.st_mode&S_IROTH) perms[4]= 'r'; + if(stbuf.st_mode&S_IWOTH) perms[5]= 'w'; + } + sprintf(respt, "%d -dev '%s' ", i, adr); + pad= max_dev_len-strlen(adr); + if(pad>0) + for(j= 0; jinfo_text, "-----------------------------------------------------------------------------\n"); + Xorriso_info(xorriso,0); + + burn_drive_info_free(drive_list); + Xorriso_process_msg_queues(xorriso,0); + return(1); +} + + +int Xorriso_tell_media_space(struct XorrisO *xorriso, + int *media_space, int *free_space, int flag) +{ + int ret; + struct burn_drive_info *dinfo; + struct burn_drive *drive; + struct burn_write_opts *burn_options; + + (*free_space)= (*media_space)= 0; + + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to -tell_media_space", 2); + if(ret<=0) + return(0); + + ret= Xorriso_make_write_options(xorriso, drive, &burn_options, 0); + if(ret<=0) + return(-1); + (*free_space)= (*media_space)= + isoburn_disc_available_space(drive, burn_options) / (off_t) 2048; + burn_write_opts_free(burn_options); + + if(xorriso->volset_change_pending) { + ret= Xorriso_write_session(xorriso, 1); + if(ret>0) + (*free_space)-= ret; + } + Xorriso_process_msg_queues(xorriso,0); + return(1); +} + + +/* @param flag bit0= fast + bit1= deformat + bit2= do not re-aquire drive + @return 0=failure, did not touch media , -1=failure, altered media + 1=success, altered media , 2=success, did not touch media +*/ +int Xorriso_blank_media(struct XorrisO *xorriso, int flag) +{ + int ret, do_deformat= 0; + struct burn_drive_info *dinfo; + struct burn_drive *drive; + enum burn_disc_status disc_state; + struct burn_progress p; + double percent = 1.0; + int current_profile; + char current_profile_name[80]; + time_t start_time; + char mode_names[4][80]= {"all", "fast", "deformat", "deformat_quickest"}; + + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to -blank", 2); + if(ret<=0) + return(0); + + burn_disc_get_profile(drive, ¤t_profile, current_profile_name); + + disc_state = isoburn_disc_get_status(drive); + if(current_profile == 0x13) { /* overwriteable DVD-RW */ + /* Depending on flag bit1 formatted DVD-RW will get blanked to sequential + state or pseudo blanked by invalidating an eventual ISO image. */ + if(flag&2) + do_deformat= 1; + } else if(current_profile == 0x14) { /* sequential DVD-RW */ + if((flag&1) && !(flag&2)) { + sprintf(xorriso->info_text, + "-blank: DVD-RW present. Mode 'fast' defaulted to mode 'all'."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + sprintf(xorriso->info_text, + "Mode 'deformat_quickest' produces single-session-only media."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0); + flag&= ~1; + } + } else if(disc_state == BURN_DISC_BLANK) { + sprintf(xorriso->info_text,"Blank media detected. Will leave it untouched"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return 2; + } else if(disc_state==BURN_DISC_FULL || disc_state==BURN_DISC_APPENDABLE) { + ; + } else if(disc_state == BURN_DISC_EMPTY) { + sprintf(xorriso->info_text,"No media detected in drive"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return 0; + } else { + sprintf(xorriso->info_text, "Unsuitable drive and media state"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return 0; + } + if(!isoburn_disc_erasable(drive)) { + sprintf(xorriso->info_text, "Media is not of erasable type"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return 0; + } + if(xorriso->do_dummy) { + sprintf(xorriso->info_text, + "-dummy mode prevents blanking of media in mode '%s'.", + mode_names[flag&3]); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(1); + } + sprintf(xorriso->info_text, "Beginning to blank media in mode '%s'.\n", + mode_names[flag&3]); + Xorriso_info(xorriso,0); + + if(do_deformat) + burn_disc_erase(drive, (flag&1)); + else + isoburn_disc_erase(drive, (flag&1)); + start_time= time(0); + usleep(1000000); + while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) { + Xorriso_process_msg_queues(xorriso,0); + if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */ + percent = 1.0 + ((double) p.sector+1.0) / ((double) p.sectors) * 98.0; + sprintf(xorriso->info_text, "Blanking ( %.1f%% done in %d seconds )", + percent, (int) (time(0) - start_time)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0); + usleep(1000000); + } + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, "Blanking done\n"); + Xorriso_info(xorriso,0); + if(!(flag & 4)) { + ret= Xorriso_reaquire_outdev(xorriso, + 2 + (xorriso->in_drive_handle == xorriso->out_drive_handle)); + if(ret <= 0) + return(-1); + } + return(1); +} + + +/* @param flag bit0= try to achieve faster formatting + bit1= use parameter size (else use default size) + bit2= do not re-aquire drive + bit7= by_index mode: + bit8 to bit15 contain the index of the format to use. + @return 0=failure, did not touch media , -1=failure, altered media + 1=success, altered media , 2=success, did not touch media +*/ +int Xorriso_format_media(struct XorrisO *xorriso, off_t in_size, int flag) +{ + int ret, mode_flag= 0, index, status, num_formats; + unsigned dummy; + struct burn_drive_info *dinfo; + struct burn_drive *drive; + struct burn_progress p; + double percent = 1.0; + int current_profile; + char current_profile_name[80]; + off_t size= 0; + time_t start_time; + enum burn_disc_status disc_state; + + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to -format", 2); + if(ret<=0) + return(0); + + if(flag & 2) { + mode_flag= 0; /* format to given size */ + } else { + mode_flag= 4; /* format to full size */ + } + burn_disc_get_profile(drive, ¤t_profile, current_profile_name); + + if(flag&128) { /* by_index */ + index= (flag>>8) & 0xff; + ret= burn_disc_get_formats(drive, &status, &size, &dummy, &num_formats); + if(ret<=0) + num_formats= 0; + if(ret<=0 || index<0 || index>=num_formats) { + if(num_formats>0) + sprintf(xorriso->info_text, + "-format by_index_%d: format descriptors range from index 0 to %d", + index, num_formats-1); + else + sprintf(xorriso->info_text, + "-format by_index_%d: no format descriptors available", index); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + mode_flag|= (flag & 0xff80); + if(flag&1) + mode_flag|= (1<<6); + + } else if(current_profile == 0x12) { /* DVD+RAM */ + if(!(flag & 2)) + mode_flag= 6; /* format to default payload size */ + if(flag&1) + mode_flag|= (1<<6); + + } else if(current_profile == 0x13) { /* DVD-RW */ + if(flag&1) { + sprintf(xorriso->info_text, + "Detected formatted DVD-RW. Thus omitting desired fast format run."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(2); + } + + } else if(current_profile == 0x14) { /* DVD-RW sequential */ + if(flag & 1) { + size= 128*1024*1024; + mode_flag= 1; /* format to size, then write size of zeros */ + } else + mode_flag= 4; + + } else if(current_profile == 0x1a) { /* DVD+RW */ + if(flag&1) { + sprintf(xorriso->info_text, + "Detected DVD+RW. Thus omitting desired fast format run."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(2); + } + + } else if(current_profile == 0x41) { /* BD-R SRM */ + if(!(flag & 2)) + mode_flag= 6; /* format to default payload size */ + if(flag&1) + mode_flag|= (1<<6); + + } else if(current_profile == 0x43) { /* BD-RE */ + if(!(flag & 2)) + mode_flag= 6; /* format to default payload size */ + if(flag&1) + mode_flag|= (1<<6); + + } else { + sprintf(xorriso->info_text, + "-format: Unsuitable media detected."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + sprintf(xorriso->info_text,"Media current: %s (%4.4xh)", + current_profile_name, current_profile); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(0); + } + if(!(flag & 1)) + mode_flag|= 16; /* enable re-formatting */ + + if(xorriso->do_dummy) { + sprintf(xorriso->info_text, "-dummy mode prevents formatting of media."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(1); + } + sprintf(xorriso->info_text, "Beginning to format media.\n"); + Xorriso_info(xorriso, 0); + if(flag & 2) + size= in_size; + burn_disc_format(drive, size, mode_flag); + + start_time= time(0); + usleep(1000000); + while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) { + Xorriso_process_msg_queues(xorriso,0); + if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */ + percent = 1.0 + ((double) p.sector+1.0) / ((double) p.sectors) * 98.0; + sprintf(xorriso->info_text, "Formatting ( %.1f%% done in %d seconds )", + percent, (int) (time(0) - start_time)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0); + usleep(1000000); + } + + Xorriso_process_msg_queues(xorriso,0); + + if(burn_drive_wrote_well(drive)) { + sprintf(xorriso->info_text, "Formatting done\n"); + Xorriso_info(xorriso,0); + } else { + sprintf(xorriso->info_text, + "libburn indicates failure with formatting."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(-1); + } + + if(!(flag & 4)) { + ret= Xorriso_reaquire_outdev(xorriso, + 2 + (xorriso->in_drive_handle == xorriso->out_drive_handle)); + if(ret <= 0) + return(-1); + } + disc_state = isoburn_disc_get_status(drive); + if(disc_state==BURN_DISC_FULL && !(flag&1)) { + /* Blank because full format certification pattern might be non-zero */ + ret= Xorriso_blank_media(xorriso, 1); + if(ret <= 0) + return(0); + } + return(1); +} + + +/* @param flag bit2= formatting rather than blanking + @return 0=failure, did not touch media , -1=failure, altered media + 1=success, altered media , 2=success, did not touch media +*/ +int Xorriso_blank_as_needed(struct XorrisO *xorriso, int flag) +{ + int ret, is_formatted= -1, status, num_formats, did_work= 0; + struct burn_drive_info *dinfo; + struct burn_drive *drive; + enum burn_disc_status disc_state; + unsigned dummy; + int current_profile; + char current_profile_name[80]; + off_t size; + + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to blank or format", 2); + if(ret<=0) + return(0); + + burn_disc_get_profile(drive, ¤t_profile, current_profile_name); + + ret= burn_disc_get_formats(drive, &status, &size, &dummy, &num_formats); + if(ret>0) { + if(status==BURN_FORMAT_IS_FORMATTED) + is_formatted= 1; + else if(status == BURN_FORMAT_IS_UNFORMATTED) + is_formatted= 0; + } + if(current_profile == 0x12 || current_profile == 0x43) { /* DVD+RAM , BD-RE */ + if(is_formatted<0) { + sprintf(xorriso->info_text, + "-blank or -format: Unclear formatting status of %s", + current_profile_name); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + if(!is_formatted) { + ret= Xorriso_format_media(xorriso, (off_t) 0, (current_profile == 0x43)); + if(ret <= 0) + return(ret); + did_work= (ret == 1); + } + } else if(current_profile == 0x14 && (flag&4)) { /* DVD-RW sequential */ + ret= Xorriso_format_media(xorriso, (off_t) 0, 0); + if(ret <= 0) + return(ret); + did_work= (ret == 1); + } else if(current_profile == 0x41) { /* BD-R SRM */ + if(!is_formatted) { + ret= Xorriso_format_media(xorriso, (off_t) 0, 1); + if(ret <= 0) + return(ret); + did_work= (ret == 1); + } + } + + disc_state = isoburn_disc_get_status(drive); + if(disc_state != BURN_DISC_BLANK && !(flag&4)) { + ret= Xorriso_blank_media(xorriso, 1); + return(ret); + } + if(did_work) + return(1); + sprintf(xorriso->info_text, "%s as_needed: no need for action detected", + (flag&4) ? "-format" : "-blank"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(2); +} + + +/* @return <=0 error, 1 success +*/ +int Xorriso_list_formats(struct XorrisO *xorriso, int flag) +{ + int ret, i, status, num_formats, profile_no, type; + off_t size; + unsigned dummy; + char status_text[80], profile_name[90], *respt; + struct burn_drive_info *dinfo; + struct burn_drive *drive; + + respt= xorriso->result_line; + + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to obtain format descriptor list", 2); + if(ret<=0) + return(0); + + ret= burn_drive_get_drive_role(drive); + if(ret!=1) { + sprintf(xorriso->info_text, + "output device is not an MMC drive. -list_format does not apply"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + ret= 2; goto ex; + } + + ret = burn_disc_get_formats(drive, &status, &size, &dummy, + &num_formats); + if(ret<=0) { + sprintf(xorriso->info_text, "Cannot obtain format list info"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + ret= Xorriso_toc(xorriso, 3); + if(ret<=0) + goto ex; + ret= burn_disc_get_profile(drive, &profile_no, profile_name); + if(ret<=0) + goto ex; + + if(status == BURN_FORMAT_IS_UNFORMATTED) + sprintf(status_text, "unformatted, up to %.1f MiB", + ((double) size) / 1024.0 / 1024.0); + else if(status == BURN_FORMAT_IS_FORMATTED) { + if(profile_no==0x12 || profile_no==0x13 || profile_no==0x1a || + profile_no==0x43) + sprintf(status_text, "formatted, with %.1f MiB", + ((double) size) / 1024.0 / 1024.0); + else + sprintf(status_text, "written, with %.1f MiB", + ((double) size) / 1024.0 / 1024.0); + } else if(status == BURN_FORMAT_IS_UNKNOWN) { + if (profile_no > 0) + sprintf(status_text, "intermediate or unknown"); + else + sprintf(status_text, "no media or unknown media"); + } else + sprintf(status_text, "illegal status according to MMC-5"); + sprintf(respt, "Format status: %s\n", status_text); + Xorriso_result(xorriso,0); + + for (i= 0; i < num_formats; i++) { + ret= burn_disc_get_format_descr(drive, i, &type, &size, &dummy); + if (ret <= 0) + continue; + sprintf(respt, "Format idx %-2d: %2.2Xh , %.fs , %.1f MiB\n", + i, type, ((double) size) / 2048.0, ((double) size) / 1024.0/1024.0); + Xorriso_result(xorriso,0); + } + ret= 1; +ex:; + return(ret); +} + + +int Xorriso_cannot_create_iter(struct XorrisO *xorriso, int iso_error,int flag) +{ + Xorriso_process_msg_queues(xorriso,0); + Xorriso_report_iso_error(xorriso, "", iso_error, "Cannot create iter", 0, + "FATAL", 1); + sprintf(xorriso->info_text, "Cannot create IsoDirIter object"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(1); +} + + +int Xorriso__node_lba_cmp(const void *node1, const void *node2) +{ + int ret; + int lba1= 0, lba2= 0; + + ret= Xorriso__file_start_lba(*((IsoNode **) node1), &lba1, 0); + if(ret!=1) + lba1= 0; + ret= Xorriso__file_start_lba(*((IsoNode **) node2), &lba2, 0); + if(ret!=1) + lba2= 0; + return(lba1-lba2); +} + +/* The caller shall make no assumptions about the meaning of iter, node_array, + node_count, node_idx ! They are just opaque handles for which the caller + provides the memory of proper type. + @param flag bit0= initialize iteration + bit1= action needs full freedom of object manipulation + bit2= action needs LBA sorted iteration + bit31= end iteration (mandatory !) +*/ +int Xorriso_findi_iter(struct XorrisO *xorriso, IsoDir *dir_node, off_t *mem, + IsoDirIter **iter, + IsoNode ***node_array, int *node_count, int *node_idx, + IsoNode **iterated_node, int flag) +{ + int ret, i; + IsoNode *node; + off_t new_mem= 0; + char mem_text[80], limit_text[80]; + + if(flag&1) { + *node_array= NULL; + *node_count= -1; + *node_idx= 0; + *iter= NULL; + ret= iso_dir_get_children(dir_node, iter); + if(ret<0) { +cannot_iter:; + Xorriso_cannot_create_iter(xorriso, ret, 0); + return(-1); + } + if((flag&2)|(flag&4)) { + /* copy list of nodes and prepare soft iterator */ + *node_count= 0; + while(iso_dir_iter_next(*iter, &node) == 1) + (*node_count)++; + iso_dir_iter_free(*iter); + *iter= NULL; + + new_mem= ((*node_count)+1) * sizeof(IsoNode *); + if(new_mem > xorriso->temp_mem_limit) { + Sfile_scale((double) new_mem, mem_text, 5,1e4, 0); + Sfile_scale((double) xorriso->temp_mem_limit, limit_text, 5,1e4, 0); + sprintf(xorriso->info_text, + "Stacked directory snapshots exceed -temp_mem_limit (%s > %s)", + mem_text, limit_text); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + *node_count= -1; + return(-1); + } + (*node_array)= (IsoNode **) calloc((*node_count)+1, sizeof(IsoNode *)); + if(*node_array == NULL) { + sprintf(xorriso->info_text, + "Could not allocate inode list of %.f bytes", + ((double) (*node_count)+1) * (double) sizeof(IsoNode *)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + *node_count= -1; + return(-1); + } + *mem= new_mem; + ret= iso_dir_get_children(dir_node, iter); + if(ret<0) + goto cannot_iter; + while(iso_dir_iter_next(*iter, &node) == 1 && *node_idx < *node_count) { + (*node_array)[*node_idx]= node; + iso_node_ref(node); + (*node_idx)++; + } + iso_dir_iter_free(*iter); + *iter= NULL; + *node_count= *node_idx; + *node_idx= 0; + if((flag&4) && *node_count>1) + qsort(*node_array, *node_count, sizeof(IsoNode *), + Xorriso__node_lba_cmp); + } + } + + if(flag&(1<<31)) { + if(*node_count>=0 && *node_array!=NULL) { + for(i= 0; i<*node_count; i++) + iso_node_unref((*node_array)[i]); + free(*node_array); + *node_array= NULL; + *node_count= -1; + *node_idx= 0; + } else { + if(*iter!=NULL) + iso_dir_iter_free(*iter); + *iter= NULL; + } + } + + if(flag&(1|(1<<31))) + return(1); + if(*node_count>=0) { + /* return next node_array element */ + if(*node_idx>=*node_count) + return(0); + *iterated_node= (*node_array)[*node_idx]; + (*node_idx)++; + } else { + ret= iso_dir_iter_next(*iter, iterated_node); + return(ret == 1); + } + return(1); +} + + +/* @param boss_iter If not NULL then this is an iterator suitable for + iso_dir_iter_remove() which is then to be used instead + of iso_node_remove(). + @param flag bit0= remove whole sub tree: rm -r + bit1= remove empty directory: rmdir + bit2= recursion: do not reassure in mode 2 "tree" + bit3= this is for overwriting and not for plain removal + bit4= count deleted files in xorriso->pacifier_count + bit5= with bit0 only remove directory content, not the directory + @return <=0 = error + 1 = removed simple node + 2 = removed directory or tree + 3 = did not remove on user revocation +*/ +int Xorriso_rmi(struct XorrisO *xorriso, void *boss_iter, off_t boss_mem, + char *path, int flag) +{ + int ret, is_dir= 0, pl, not_removed= 0, fret; + IsoNode *victim_node, *node; + IsoDir *boss_node, *root_dir; + IsoDirIter *iter= NULL; + IsoImage *volume; + char *sub_name, *name; + char *sfe= NULL, *sub_path= NULL; + off_t mem; + IsoNode **node_array= NULL; + int node_count, node_idx; + + /* Avoiding large local memory objects in order to save stack space */ + sfe= malloc(5*SfileadrL); + sub_path= malloc(2*SfileadrL); + if(sfe==NULL || sub_path==NULL) { + Xorriso_no_malloc_memory(xorriso, &sfe, 0); + {ret= -1; goto ex;} + } + +#ifndef Libisofs_iso_dir_iter_sufficienT + /* Ticket 127: A80301 - A80302 + I do not not deem IsoDirIter safe for node list manipulations. + The parameter boss_iter once was intended to allow such but + has now been downgraded to a mere check for eventual programming bugs. + */ + if(boss_iter!=NULL) { + sprintf(xorriso->info_text, + "Program error: Xorriso_rmi() was requested to delete iterated node %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + ret= -1; goto ex; + } +#endif /* Libisofs_iso_dir_iter_sufficienT */ + + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + goto ex; + + if(Xorriso_much_too_long(xorriso, strlen(path), 0)<=0) + {ret= 0; goto ex;} + ret= Xorriso_node_from_path(xorriso, volume, path, &victim_node, 0); + if(ret<=0) + goto ex; + root_dir= iso_image_get_root(volume); + if(((void *) root_dir) == ((void *) victim_node)) { + sprintf(xorriso->info_text, "May not delete root directory"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + + if(LIBISO_ISDIR(victim_node)) + is_dir= 1; + if(!is_dir) { + if(flag&2) { /* rmdir */ + sprintf(xorriso->info_text, "%s in loaded ISO image is not a directory", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + } else { + if(flag&1) { /* rm -r */ + if((xorriso->do_reassure==1 && !xorriso->request_not_to_ask) || + (flag&32)) { + /* Iterate over subordinates and delete them */ + mem= boss_mem; + + ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem, + &iter, &node_array, &node_count, &node_idx, + &node, 1|2); + if(ret<=0) { +cannot_create_iter:; + Xorriso_cannot_create_iter(xorriso, ret, 0); + ret= -1; goto ex; + } + pl= strlen(path); + strcpy(sub_path, path); + if(pl==0 || sub_path[pl-1]!='/') { + sub_path[pl++]= '/'; + sub_path[pl]= 0; + } + sub_name= sub_path+pl; + while(1) { + ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem, &iter, + &node_array, &node_count, &node_idx, &node, 0); + if(ret<0) + goto ex; + if(ret==0 || xorriso->request_to_abort) + break; + name= (char *) iso_node_get_name(node); + if(Xorriso_much_too_long(xorriso, pl+1+strlen(name), 0)<=0) + {ret= 0; goto rm_r_problem_handler;} + strcpy(sub_name, name); + ret= Xorriso_rmi(xorriso, iter, mem, sub_path, (flag&(1|2|8|16))|4); + if(ret==3 || ret<=0 || xorriso->request_to_abort) { +rm_r_problem_handler:; + not_removed= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); + if(fret<0) + goto dir_not_removed; + } + } + if(flag&32) + {ret= 2; goto ex;} + + if(not_removed) { +dir_not_removed:; + sprintf(xorriso->info_text, "Directory not removed: %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + if(ret>0) + ret= 3; + goto ex; + } + } + } else { + if(!(flag&2)) { /* not rmdir */ + sprintf(xorriso->info_text, "%s in loaded ISO image is a directory", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + + ret= iso_dir_get_children((IsoDir *) victim_node, &iter); + Xorriso_process_msg_queues(xorriso,0); + if(ret<0) + goto cannot_create_iter; + if(ret>0) { + if(iso_dir_iter_next(iter, &node) == 1) { + sprintf(xorriso->info_text, + "Directory not empty on attempt to delete: %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + } + } + } + + if(xorriso->request_to_abort) + {ret= 3; goto ex;} + boss_node= iso_node_get_parent(victim_node); + Xorriso_process_msg_queues(xorriso,0); + if(boss_node==NULL) { + sprintf(xorriso->info_text, + "Cannot find parent node of %s in loaded ISO image", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + + while((xorriso->do_reassure==1 || (xorriso->do_reassure==2 && !(flag&4))) + && !xorriso->request_not_to_ask) { + /* ls -ld */ + Xorriso_ls_filev(xorriso, xorriso->wdi, 1, &path, (off_t) 0, 1|2|8); + if(is_dir) /* du -s */ + Xorriso_ls_filev(xorriso, xorriso->wdi, 1, &path, (off_t) 0, 2|4); + if(flag&8) + sprintf(xorriso->info_text, + "File exists. Remove ? n= keep old, y= remove, x= abort, @= stop asking\n"); + else + sprintf(xorriso->info_text, + "Remove above file ? n= keep it, y= remove it, x= abort, @= stop asking\n"); + Xorriso_info(xorriso, 4); + ret= Xorriso_request_confirmation(xorriso, 1|2|4|16); + if(ret<=0) + goto ex; + if(xorriso->request_to_abort) { + sprintf(xorriso->info_text, + "Removal operation aborted by user before file: %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + ret= 3; goto ex; + } + if(ret==3) + continue; + if(ret==6) /* yes */ + break; + if(ret==4) { /* yes, do not ask again */ + xorriso->request_not_to_ask= 1; + break; + } + if(ret==1) { /* no */ + sprintf(xorriso->info_text, "Kept in existing state: %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + ret= 3; goto ex; + } + } + +#ifdef Libisofs_iso_dir_iter_sufficienT + + if(boss_iter!=NULL) { + ret= iso_dir_iter_remove((IsoDirIter *) boss_iter); + if(ret<0) + ret= -1; + } else + ret= iso_node_remove(victim_node); + +#else /* ! Libisofs_iso_dir_iter_sufficienT */ + + ret= iso_node_remove(victim_node); + +#endif /* Libisofs_iso_dir_iter_sufficienT */ + + Xorriso_process_msg_queues(xorriso,0); + if(ret<0) { + Xorriso_report_iso_error(xorriso, path, ret, "Cannot remove node", 0, + "FATAL", 1); + sprintf(xorriso->info_text, + "Internal failure to remove %s from loaded ISO image", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + ret= -1; goto ex; + } + if(flag&16) + xorriso->pacifier_count++; + xorriso->volset_change_pending= 1; + ret= 1+!!is_dir; +ex:; + if(sfe!=NULL) + free(sfe); + if(sub_path!=NULL) + free(sub_path); + Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem, &iter, + &node_array, &node_count, &node_idx, &node, (1<<31)); + return(ret); +} + + +int Xorriso__node_name_cmp(const void *node1, const void *node2) +{ + char *name1, *name2; + + name1= (char *) iso_node_get_name(*((IsoNode **) node1)); + name2= (char *) iso_node_get_name(*((IsoNode **) node2)); + return(strcmp(name1,name2)); +} + + +/* @param flag bit0= only accept directory nodes + bit1= do not report memory usage as DEBUG + bit2= do not apply search pattern but accept any node +*/ +int Xorriso_sorted_node_array(struct XorrisO *xorriso, + IsoDir *dir_node, + int *nodec, IsoNode ***node_array, + off_t boss_mem, int flag) +{ + int i, ret, failed_at; + char *npt; + IsoDirIter *iter= NULL; + IsoNode *node; + off_t mem; + + mem= ((*nodec)+1)*sizeof(IsoNode *); + ret= Xorriso_check_temp_mem_limit(xorriso, mem+boss_mem, flag&2); + if(ret<=0) + return(ret); + + *node_array= calloc(sizeof(IsoNode *), (*nodec)+1); + if(*node_array==NULL) { + sprintf(xorriso->info_text, + "Cannot allocate memory for %d directory entries", *nodec); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(-1); + } + + ret= iso_dir_get_children(dir_node, &iter); + if(ret<0) { + Xorriso_cannot_create_iter(xorriso, ret, 0); + return(-1); + } + + for(i= 0; iso_dir_iter_next(iter, &node) == 1 && i<*nodec; ) { + npt= (char *) iso_node_get_name(node); + if(!(flag&4)) { + ret= Xorriso_regexec(xorriso, npt, &failed_at, 0); + if(ret) + continue; /* no match */ + } + if(flag&1) + if(!LIBISO_ISDIR(node)) + continue; + (*node_array)[i++]= node; + } + iso_dir_iter_free(iter); + *nodec= i; + if(*nodec<=0) + return(1); + qsort(*node_array, *nodec, sizeof(IsoNode *), Xorriso__node_name_cmp); + return(1); +} + + +/* @param flag bit0= do not only sum up sizes but also print subdirs +*/ +int Xorriso_show_du_subs(struct XorrisO *xorriso, IsoDir *dir_node, + char *abs_path, char *rel_path, off_t *size, + off_t boss_mem, int flag) +{ + int i, ret, no_sort= 0, filec= 0, l; + IsoDirIter *iter= NULL; + IsoNode *node, **node_array= NULL; + char *name; + off_t sub_size, report_size, mem= 0; + char *path= NULL, *show_path= NULL, *sfe= NULL; + + sfe= malloc(5*SfileadrL); + path= malloc(SfileadrL); + show_path= malloc(SfileadrL); + if(path==NULL || show_path==NULL || sfe==NULL) { + Xorriso_no_malloc_memory(xorriso, &sfe, 0); + {ret= -1; goto ex;} + } + + *size= 0; + ret= iso_dir_get_children(dir_node, &iter); + if(ret<0) { +cannot_create_iter:; + Xorriso_cannot_create_iter(xorriso, ret, 0); + {ret= -1; goto ex;} + } + for(i= 0; iso_dir_iter_next(iter, &node) == 1; ) { + sub_size= 0; + name= (char *) iso_node_get_name(node); + strcpy(show_path, rel_path); + if(Sfile_add_to_path(show_path, name, 0)<=0) + goto much_too_long; + if(LIBISO_ISDIR(node)) { + strcpy(path, abs_path); + if(Sfile_add_to_path(path, name, 0)<=0) { +much_too_long:; + Xorriso_much_too_long(xorriso, strlen(path)+strlen(name)+1, 2); + {ret= -1; goto ex;} + } + filec++; + l= strlen(rel_path)+1; + mem+= l; + if(l % sizeof(char *)) + mem+= sizeof(char *)-(l % sizeof(char *)); + if(flag&1) /* diving and counting is done further below */ + continue; + ret= Xorriso_show_du_subs(xorriso, (IsoDir *) node, + path, show_path, &sub_size, boss_mem, 0); + if(ret<0) + goto ex; + if(ret==0) + continue; + } + + if(LIBISO_ISREG(node)) { + sub_size+= iso_file_get_size((IsoFile *) node)+2048; +/* + sub_size+= iso_file_get_size((IsoFile *) node)+strlen(name)+1; +*/ + } + + if(sub_size>0) + (*size)+= sub_size; + Xorriso_process_msg_queues(xorriso,0); + } + + if(filec<=0 || !(flag&1)) + {ret= 1; goto ex;} + + /* Reset iteration */ + iso_dir_iter_free(iter); + iter= NULL; + Xorriso_process_msg_queues(xorriso,0); + + ret= Xorriso_sorted_node_array(xorriso, dir_node, &filec, &node_array, + boss_mem, 1|2|4); + if(ret<0) + goto ex; + if(ret==0) { + no_sort= 1; + ret= iso_dir_get_children(dir_node, &iter); + if(ret<0) + goto cannot_create_iter; + } + + for(i= 0; (no_sort || irequest_to_abort); i++) { + if(no_sort) { + ret= iso_dir_iter_next(iter, &node); + if(ret!=1) + break; + if(!LIBISO_ISDIR(node)) + continue; + } else + node= node_array[i]; + + sub_size= 0; + name= (char *) iso_node_get_name(node); + strcpy(show_path, rel_path); + if(Sfile_add_to_path(show_path, name, 0)<=0) + goto much_too_long; + strcpy(path, abs_path); + if(Sfile_add_to_path(path, name, 0)<=0) + goto much_too_long; + ret= Xorriso_show_du_subs(xorriso, (IsoDir *) node, + path, show_path, &sub_size, boss_mem+mem, flag&1); + if(ret<0) + goto ex; + + if(LIBISO_ISREG(node)) { + sub_size+= iso_file_get_size((IsoFile *) node)+2048; +/* + sub_size+= iso_tree_node_get_size((IsoFile *) node)+strlen(name)+1; +*/ + } + if(sub_size>0) + (*size)+= sub_size; + report_size= sub_size/1024; + if(report_size*1024result_line, "%7.f ",(double) (report_size)); + sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s\n", + Text_shellsafe(show_path, sfe, 0)); + Xorriso_result(xorriso, 0); + } + ret= 1; +ex:; + if(sfe!=NULL) + free(sfe); + if(path!=NULL) + free(path); + if(show_path!=NULL) + free(show_path); + if(iter!=NULL) + iso_dir_iter_free(iter); + if(node_array!=NULL) + free((char *) node_array); + Xorriso_process_msg_queues(xorriso,0); + return(ret); +} + + +int Xorriso_sorted_dir_i(struct XorrisO *xorriso, IsoDir *dir_node, + int *filec, char ***filev, off_t boss_mem, int flag) +{ + int i,j,ret; + IsoDirIter *iter= NULL; + IsoNode *node; + char *name; + off_t mem; + + (*filec)= 0; + (*filev)= NULL; + + ret= iso_dir_get_children(dir_node, &iter); + if(ret<0) { +cannot_iter:; + Xorriso_cannot_create_iter(xorriso, ret, 0); + {ret= -1; goto ex;} + } + mem= 0; + for(i= 0; iso_dir_iter_next(iter, &node) == 1; ) { + name= (char *) iso_node_get_name(node); + mem+= sizeof(char *)+strlen(name)+8; + (*filec)++; + } + iso_dir_iter_free(iter); + iter= NULL; + if(*filec==0) + {ret= 1; goto ex;} + + ret= Xorriso_check_temp_mem_limit(xorriso, mem+boss_mem, 2); + if(ret<=0) + goto ex; + (*filev)= (char **) calloc(*filec, sizeof(char *)); + if(*filev==NULL) + {ret= -1; goto ex; } + ret= iso_dir_get_children(dir_node, &iter); + if(ret<0) + goto cannot_iter; + for(i= 0; i<*filec; i++) { + ret= iso_dir_iter_next(iter, &node); + if(ret!=1) + break; + name= (char *) iso_node_get_name(node); + (*filev)[i]= strdup(name); + if((*filev)[i]==NULL) { + for(j= 0; jresult_line; + + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(ret); + + Sort_argv(filec, filev, 0); + + /* Count valid nodes, warn of invalid ones */ + for(i= 0; iinfo_text, "Not found in ISO image: %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); + was_error++; + continue; + } + } + + if((flag&8) && !(flag&(2|4))) { + sprintf(xorriso->info_text, "Valid ISO nodes found: %d\n", filec-was_error); + Xorriso_info(xorriso,1); + if(filec-was_error<=0) + return(!was_error); + } + + passes= 1+!(flag&(4|8)); + for(pass= 0; passrequest_to_abort); i++) { + rpt[0]= 0; + ret= Xorriso_make_abs_adr(xorriso, wd, filev[i], path, 1|2|4); + if(ret<=0) + continue; + ret= Xorriso_fake_stbuf(xorriso, path, &stbuf, &node, (flag&4)>>1); + if(ret<=0) + continue; + if(LIBISO_ISDIR(node) && !(flag&(4|8))) { + if(pass==0) + continue; + if(filec>1) { + strcpy(xorriso->result_line, "\n"); + Xorriso_result(xorriso,0); + sprintf(xorriso->result_line, "%s:\n", Text_shellsafe(filev[i], sfe,0)); + Xorriso_result(xorriso,0); + } + ret= Xorriso_sorted_dir_i(xorriso, + (IsoDir *) node, &dfilec, &dfilev, boss_mem, 0); + if(ret<=0) { + + /* >>> libisofs iterator loop and single item Xorriso_lsx_filev() */; + + } else { + if(flag&1) { + sprintf(xorriso->result_line, "total %d\n", dfilec); + Xorriso_result(xorriso,0); + } + Xorriso_ls_filev(xorriso, path, + dfilec, dfilev, boss_mem, (flag&1)|2|8); + } + if(dfilec>0) + Sfile_destroy_argv(&dfilec, &dfilev, 0); + continue; + } else + if(pass>0) + continue; + link_target[0]= 0; + if((flag&5)==1) { /* -ls_l */ + ret= Xorriso_format_ls_l(xorriso, &stbuf, 1); + if(ret<=0) + continue; + if(LIBISO_ISLNK(node)) { + if(Sfile_str(link_target, (char *) iso_symlink_get_dest( + (IsoSymlink *) node), 0)<=0) + link_target[0]= 0; + } + } else if(flag&4) { /* -du or -dus */ + size= stbuf.st_size; + if(S_ISDIR(stbuf.st_mode)) { + ret= Xorriso_show_du_subs(xorriso, (IsoDir *) node, + path, filev[i], &size, boss_mem, flag&1); + if(ret<0) + return(-1); + if(ret==0) + continue; + } + sprintf(rpt, "%7.f ",(double) (size/1024)); + } + if(link_target[0] && (flag&5)==1) + sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s -> %s\n", + Text_shellsafe(filev[i], sfe, 0), + Text_shellsafe(link_target, sfe2, 0)); + else + sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s\n", + Text_shellsafe(filev[i], sfe, 0)); + Xorriso_result(xorriso, 0); + } + return(!was_error); +} + + +/* This function needs less buffer memory than Xorriso_ls_filev() but cannot + perform structured pattern matching as done by Xorriso_expand_pattern() + for subsequent Xorriso_ls_filev(). + @param flag bit0= long format + bit1= only check for directory existence + bit2= do not apply search pattern but accept any file + bit3= just count nodes and return number +*/ +int Xorriso_ls(struct XorrisO *xorriso, int flag) +{ + int ret, is_dir= 0, i, filec= 0, failed_at, no_sort= 0; + IsoNode *node, **node_array= NULL; + IsoDir *dir_node; + IsoImage *volume; + IsoDirIter *iter= NULL; + char sfe[5*SfileadrL], sfe2[5*SfileadrL], link_target[SfileadrL], *npt, *rpt; + struct stat stbuf; + + rpt= xorriso->result_line; + + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(ret); + + ret= Xorriso_node_from_path(xorriso, volume, xorriso->wdi, &node, 0); + if(ret<=0) + goto wdi_is_not_a_dir; + if(LIBISO_ISDIR(node)) + is_dir= 1; + if(!is_dir) { +wdi_is_not_a_dir:; + sprintf(xorriso->info_text, + "Working directory path does not lead to a directory in ISO image"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + if(flag&2) + {ret= 1; goto ex;} + + dir_node= (IsoDir *) node; + ret= iso_dir_get_children(dir_node, &iter); + if(ret<0) { +cannot_create_iter:; + Xorriso_cannot_create_iter(xorriso, ret, 0); + {ret= -1; goto ex;} + } + Xorriso_process_msg_queues(xorriso,0); + + for(i= 0; iso_dir_iter_next(iter, &node) == 1; ) { + npt= (char *) iso_node_get_name(node); + if(!(flag&4)) { + ret= Xorriso_regexec(xorriso, npt, &failed_at, 0); + if(ret) + continue; /* no match */ + } + filec++; + } + /* Reset iteration */ + iso_dir_iter_free(iter); + iter= NULL; + Xorriso_process_msg_queues(xorriso,0); + if(flag&8) + {ret= filec; goto ex;} + sprintf(xorriso->info_text, "Valid ISO nodes found: %d\n", filec); + Xorriso_info(xorriso,1); + + ret= Xorriso_sorted_node_array(xorriso, dir_node, &filec, &node_array, 0, + flag&4); + if(ret<0) + goto ex; + if(ret==0) { + no_sort= 1; + ret= iso_dir_get_children(dir_node, &iter); + if(ret<0) + goto cannot_create_iter; + } + + for(i= 0; irequest_to_abort); i++) { + if(no_sort) { + ret= iso_dir_iter_next(iter, &node); + if(ret!=1) + break; + npt= (char *) iso_node_get_name(node); + if(!(flag&4)) { + ret= Xorriso_regexec(xorriso, npt, &failed_at, 0); + if(ret) + continue; /* no match */ + } + } else + node= node_array[i]; + + npt= (char *) iso_node_get_name(node); + link_target[0]= 0; + if(LIBISO_ISLNK(node)) { + if(Sfile_str(link_target, (char *) iso_symlink_get_dest( + (IsoSymlink *) node), 0)<=0) + link_target[0]= 0; + } + rpt[0]= 0; + if(flag&1) { + ret= Xorriso_fake_stbuf(xorriso, "", &stbuf, &node, 1); + if(ret<=0) + continue; + ret= Xorriso_format_ls_l(xorriso, &stbuf, 1); + if(ret<=0) + continue; + } + if(link_target[0] && (flag&1)) + sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s -> %s\n", + Text_shellsafe(npt, sfe, 0), + Text_shellsafe(link_target, sfe2, 0)); + else + sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s\n", + Text_shellsafe(npt, sfe, 0)); + Xorriso_result(xorriso, 0); + } + + ret= 1; +ex:; + if(iter!=NULL) + iso_dir_iter_free(iter); + Xorriso_process_msg_queues(xorriso,0); + if(node_array!=NULL) + free((char *) node_array); + return(ret); +} + + +/* @param boss_iter Opaque handle to be forwarded to actions in ISO image + Set to NULL if calling this function from outside ISO world +*/ +int Xorriso_rename(struct XorrisO *xorriso, void *boss_iter, + char *origin, char *dest, int flag) +{ + int ret, ol, dest_ret; + char sfe[5*SfileadrL], eff_dest[SfileadrL], dir_adr[SfileadrL], *cpt; + char *leafname, eff_origin[SfileadrL], sfe2[5*SfileadrL], *old_leafname; + IsoImage *volume; + IsoDir *origin_dir, *dest_dir; + IsoNode *node, *iso_node; + +#ifndef Libisofs_iso_dir_iter_sufficienT + /* Ticket 127: A80301 - A80302 + I do not not deem IsoDirIter safe for node list manipulations. + The parameter boss_iter once was intended to allow such but + has now been downgraded to a mere check for eventual programming bugs. + */ + if(boss_iter!=NULL) { + sprintf(xorriso->info_text, + "Program error: Xorriso_rename() was requested to delete iterated node %s", + Text_shellsafe(origin, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(-1); + } +#endif /* Libisofs_iso_dir_iter_sufficienT */ + + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, origin, eff_origin, 0); + if(ret<=0) + return(ret); + dest_ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, dest, eff_dest,1); + if(dest_ret<0) + return(dest_ret); + if(dest_ret==0) { /* obtain eff_dest address despite it does not exist */ + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, dest, eff_dest, 2); + if(ret<=0) + return(ret); + } + + /* Prevent that destination is a subordinate of origin + (that would be a black hole plopping out of the universe) */ + ol= strlen(eff_origin); + if(ol==0) { + sprintf(xorriso->info_text, "May not rename root directory"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } else if(strcmp(eff_origin, eff_dest)==0) { + sprintf(xorriso->info_text, "Ignored attempt to rename %s to itself", + Text_shellsafe(eff_origin,sfe,0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); + return(0); + } else if(strncmp(eff_origin, eff_dest, ol)==0 && + (eff_dest[ol]==0 || eff_dest[ol]=='/')) { + sprintf(xorriso->info_text, + "May not rename %s to its own sub address %s", + Text_shellsafe(eff_origin,sfe,0), Text_shellsafe(eff_dest,sfe2,0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + + /* Check whether destination exists and may be not overwriteable */ + if(dest_ret==2 && xorriso->do_overwrite!=1) { + sprintf(xorriso->info_text, "Renaming may not overwrite directory: %s", + Text_shellsafe(eff_dest, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } else if (dest_ret==1 && !xorriso->do_overwrite) { + sprintf(xorriso->info_text, "Renaming may not overwite: %s", + Text_shellsafe(eff_dest, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } else if(dest_ret>0) { + ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, eff_dest, 1|8); + if(ret<=0) + return(0); + if(ret==3) { + sprintf(xorriso->info_text, "User revoked renaming of: %s", + Text_shellsafe(eff_origin, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(0); + } + } + + /* Ensure existence of destination directory */ + strcpy(dir_adr, eff_dest); + cpt= strrchr(dir_adr, '/'); + if(cpt==NULL) + cpt= dir_adr+strlen(dir_adr); + *cpt= 0; + if(dir_adr[0]!=0) { + ret= Xorriso_graft_in(xorriso, boss_iter, NULL, dir_adr, + (off_t) 0, (off_t) 0, 1); + if(ret<=0) + return(ret); + } + + /* Move node */ + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(ret); + Xorriso_node_from_path(xorriso, volume, dir_adr, &iso_node, 0); + dest_dir= (IsoDir *) iso_node; + strcpy(dir_adr, eff_origin); + cpt= strrchr(dir_adr, '/'); + if(cpt==NULL) + cpt= dir_adr+strlen(dir_adr); + *cpt= 0; + Xorriso_node_from_path(xorriso, volume, dir_adr, &iso_node, 0); + origin_dir= (IsoDir *) iso_node; + Xorriso_node_from_path(xorriso, volume, eff_origin, &node, 0); + if(dest_dir==NULL || origin_dir==NULL || node==NULL) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "Internal error on rename: confirmed node turns out as NULL"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(-1); + } + ret= iso_node_take(node); + if(ret<0) { + Xorriso_process_msg_queues(xorriso,0); + Xorriso_report_iso_error(xorriso, eff_dest, 0, "Cannot take", 0, "FATAL",1); + sprintf(xorriso->info_text, + "Internal error on rename: failed to take node"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(-1); + } + leafname= strrchr(eff_dest, '/'); + if(leafname==NULL) + leafname= eff_dest; + else + leafname++; + + old_leafname= (char *) iso_node_get_name(node); + if(strcmp(leafname, old_leafname)!=0) + ret= iso_node_set_name(node, leafname); + else + ret= 1; + if(ret<0) { + Xorriso_process_msg_queues(xorriso,0); + Xorriso_report_iso_error(xorriso, eff_dest, 0, "Cannot set name", 0, + "FAILURE", 1); + return(-1); + } + Xorriso_process_msg_queues(xorriso,0); + ret= iso_dir_add_node(dest_dir, node, 0); + if(ret<0) { + Xorriso_process_msg_queues(xorriso,0); + Xorriso_report_iso_error(xorriso, eff_dest, 0, "Cannot add", 0, "FATAL", 1); + sprintf(xorriso->info_text, + "Internal error on rename: failed to insert node"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(-1); + } + return(1); +} + + +/* @param flag bit0= do not produce info message on success + @return 1=success, + 0=was already directory, -1=was other type, -2=other error +*/ +int Xorriso_mkdir(struct XorrisO *xorriso, char *path, int flag) +{ + int ret; + char eff_path[SfileadrL], sfe[5*SfileadrL]; + + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, path, eff_path, 1); + if(ret<0) + return(-2); + if(ret>0) { + sprintf(xorriso->info_text,"-mkdir: Address already existing %s", + Text_shellsafe(eff_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, + (ret==2 ? "WARNING" : "FAILURE"), 0); + return(-1+(ret==2)); + } + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, path, eff_path, 2); + if(ret<0) + return(-2); + ret= Xorriso_graft_in(xorriso, NULL, NULL, eff_path, (off_t) 0, (off_t) 0, 1); + if(ret<=0) + return(-2); + if(!(flag&1)) { + sprintf(xorriso->info_text, "Created directory in ISO image: %s\n", + Text_shellsafe(eff_path,sfe,0)); + Xorriso_info(xorriso, 0); + } + return(1); +} + + +/* @param flag bit0= count results rather than storing them + bit1= this is a recursion + bit2= prepend wd (automatically done if wd[0]!=0) +*/ +int Xorriso_obtain_pattern_files_i( + struct XorrisO *xorriso, char *wd, IsoDir *dir, + int *filec, char **filev, int count_limit, off_t *mem, + int *dive_count, int flag) +{ + int ret, failed_at; + IsoDirIter *iter= NULL; + IsoNode *node; + char *name; + char *adr= NULL; + + adr= malloc(SfileadrL); + if(adr==NULL) { + Xorriso_no_malloc_memory(xorriso, &adr, 0); + {ret= -1; goto ex;} + } + + if(!(flag&2)) + *dive_count= 0; + else + (*dive_count)++; + ret= Xorriso_check_for_root_pattern(xorriso, filec, filev, count_limit, + mem, (flag&1)|2); + if(ret!=2) + goto ex; + + ret= iso_dir_get_children(dir, &iter); + if(ret<0) { + Xorriso_cannot_create_iter(xorriso, ret, 0); + {ret= -1; goto ex;} + } + while(iso_dir_iter_next(iter, &node) == 1) { + name= (char *) iso_node_get_name(node); + ret= Xorriso_make_abs_adr(xorriso, wd, name, adr, flag&4); + if(ret<=0) + goto ex; + ret= Xorriso_regexec(xorriso, adr, &failed_at, 1); + if(ret) { /* no match */ + if(failed_at <= *dive_count) /* no hope for a match */ + continue; + + if(!LIBISO_ISDIR(node)) { + + /* >>> How to deal with softlinks ? */ + + continue; + } + /* dive deeper */ + ret= Xorriso_obtain_pattern_files_i( + xorriso, adr, (IsoDir *) node, + filec, filev, count_limit, mem, dive_count, flag|2); + if(ret<=0) + goto ex; + } else { + ret= Xorriso_register_matched_adr(xorriso, adr, count_limit, + filec, filev, mem, (flag&1)|2); + if(ret<=0) + goto ex; + } + } + ret= 1; +ex:; + if(adr!=NULL) + free(adr); + if(flag&2) + (*dive_count)--; + return(ret); +} + + +/* @param flag bit0= a match count !=1 is a FAILURE event + bit1= with bit0 tolerate 0 matches if pattern is a constant +*/ +int Xorriso_expand_pattern(struct XorrisO *xorriso, + int num_patterns, char **patterns, int extra_filec, + int *filec, char ***filev, off_t *mem, int flag) +{ + int ret, count= 0, abs_adr= 0, i, was_count, was_filec; + int nonconst_mismatches= 0, dive_count= 0; + char sfe[5*SfileadrL]; + IsoImage *volume; + IsoDir *dir= NULL, *root_dir; + IsoNode *iso_node; + + *filec= 0; + *filev= NULL; + + xorriso->search_mode= 3; + xorriso->structured_search= 1; + + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(ret); + root_dir= iso_image_get_root(volume); + if(root_dir==NULL) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "While expanding pattern : Cannot obtain root node of ISO image"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + ret= -1; goto ex; + } + + for(i= 0; iwdi does not exist yet, but one may + not use it as base for relative address searches. + */ + ret= Xorriso_node_from_path(xorriso, volume, xorriso->wdi, &iso_node, 1); + dir= (IsoDir *) iso_node; + if(ret<=0) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "While expanding pattern %s : Working directory does not exist in ISO image", + Text_shellsafe(patterns[i], sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + if(!LIBISO_ISDIR((IsoNode *) dir)) { + sprintf(xorriso->info_text, + "Working directory path does not lead to a directory in ISO image"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + } + + /* count the matches */ + was_count= count; + ret= Xorriso_obtain_pattern_files_i(xorriso, "", dir, &count, NULL, 0, + mem, &dive_count, 1 | abs_adr); + if(ret<=0) + goto ex; + if(was_count==count && strcmp(patterns[i],"*")!=0 && (flag&3)!=1) { + count++; + Xorriso_eval_nonmatch(xorriso, patterns[i], &nonconst_mismatches, mem, 0); + } + } + + ret= Xorriso_check_matchcount(xorriso, count, nonconst_mismatches, + num_patterns, patterns, (flag&1)|2); + if(ret<=0) + goto ex; + count+= extra_filec; + mem+= extra_filec*sizeof(char *); + if(count<=0) + {ret= 0; goto ex;} + ret= Xorriso_alloc_pattern_mem(xorriso, *mem, count, filev, 0); + if(ret<=0) + goto ex; + /* now store addresses */ + for(i= 0; iinfo_text,"Permissions now: %-5.5o %s", + mode, Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + xorriso->volset_change_pending= 1; + Xorriso_process_msg_queues(xorriso,0); + return(1); +} + + +int Xorriso_set_uid(struct XorrisO *xorriso, char *in_path, uid_t uid, + int flag) +{ + int ret; + IsoNode *node; + + ret= Xorriso_get_node_by_path(xorriso, in_path, NULL, &node, 0); + if(ret<=0) + return(ret); + iso_node_set_uid(node, uid); + iso_node_set_ctime(node, time(NULL)); + xorriso->volset_change_pending= 1; + Xorriso_process_msg_queues(xorriso,0); + return(1); +} + + +int Xorriso_set_gid(struct XorrisO *xorriso, char *in_path, gid_t gid, + int flag) +{ + int ret; + IsoNode *node; + + ret= Xorriso_get_node_by_path(xorriso, in_path, NULL, &node, 0); + if(ret<=0) + return(ret); + iso_node_set_gid(node, gid); + iso_node_set_ctime(node, time(NULL)); + xorriso->volset_change_pending= 1; + Xorriso_process_msg_queues(xorriso,0); + return(1); +} + + +/* @parm flag bit0= atime, bit1= ctime, bit2= mtime, bit8=no auto ctime */ +int Xorriso_set_time(struct XorrisO *xorriso, char *in_path, time_t t, + int flag) +{ + int ret; + IsoNode *node; + + ret= Xorriso_get_node_by_path(xorriso, in_path, NULL, &node, 0); + if(ret<=0) + return(ret); + if(flag&1) + iso_node_set_atime(node, t); + if(flag&2) + iso_node_set_ctime(node, t); + if(flag&4) + iso_node_set_mtime(node, t); + if(!(flag&(2|256))) + iso_node_set_ctime(node, time(NULL)); + xorriso->volset_change_pending= 1; + Xorriso_process_msg_queues(xorriso,0); + return(1); +} + + +int Xorriso__start_end_lbas(IsoNode *node, + int *lba_count, int **start_lbas, int **end_lbas, + off_t *size, int flag) +{ + int section_count= 0, ret, i; + struct iso_file_section *sections= NULL; + + *lba_count= 0; + *start_lbas= *end_lbas= NULL; + *size= 0; + if(!LIBISO_ISREG(node)) + return(0); + *size= iso_file_get_size((IsoFile *) node); + ret= iso_file_get_old_image_sections((IsoFile *) node, §ion_count, + §ions, 0); + if(ret < 0) + {ret= -1; goto ex;} + if(ret != 1 || section_count <= 0) + {ret= 0; goto ex;} + *start_lbas= calloc(section_count, sizeof(int)); + *end_lbas= calloc(section_count, sizeof(int)); + if(*start_lbas == NULL || *end_lbas == NULL) + {ret= -1; goto ex;} + for(i= 0; i < section_count; i++) { + (*start_lbas)[i]= sections[i].block; + (*end_lbas)[i]= sections[i].block + sections[i].size / 2048 - 1; + if(sections[i].size % 2048) + (*end_lbas)[i]++; + } + *lba_count= section_count; + ret= 1; +ex:; + if(sections != NULL) + free((char *) sections); + if(ret <= 0) { + if((*start_lbas) != NULL) + free((char *) *start_lbas); + if((*end_lbas) != NULL) + free((char *) *end_lbas); + *start_lbas= *end_lbas= NULL; + *lba_count= 0; + } + return(ret); +} + + +int Xorriso__file_start_lba(IsoNode *node, + int *lba, int flag) +{ + int *start_lbas= NULL, *end_lbas= NULL, lba_count= 0, i, ret; + off_t size; + + *lba= -1; + ret= Xorriso__start_end_lbas(node, &lba_count, &start_lbas, &end_lbas, + &size, 0); + if(ret <= 0) + return(ret); + for(i= 0; i < lba_count; i++) { + if(*lba < 0 || start_lbas[i] < *lba) + *lba= start_lbas[i]; + } + if(start_lbas != NULL) + free((char *) start_lbas); + if(end_lbas != NULL) + free((char *) end_lbas); + if(*lba < 0) + return(0); + return(1); +} + + +/* @param damage_start Returns first damaged byte address + @param damage_end Returns first byte address after last damaged byte + @return <0 error, 0=undamaged , 1=damaged +*/ +int Xorriso_file_eval_damage(struct XorrisO *xorriso, IsoNode *node, + off_t *damage_start, off_t *damage_end, + int flag) +{ + int *start_lbas= NULL, *end_lbas= NULL, lba_count= 0, sect; + int i, sectors, sector_size, ret; + off_t sect_base= 0, size= 0, byte; + struct SectorbitmaP *map; + + *damage_start= *damage_end= -1; + map= xorriso->in_sector_map; + if(map == NULL) + return(0); + Sectorbitmap_get_layout(map, §ors, §or_size, 0); + sector_size/= 2048; + + ret= Xorriso__start_end_lbas(node, &lba_count, &start_lbas, &end_lbas, + &size, 0); + if(ret <= 0) { + Xorriso_process_msg_queues(xorriso, 0); + return(ret); + } + for(sect= 0; sect < lba_count; sect++) { + for(i= start_lbas[sect]; i <= end_lbas[sect]; i+= sector_size) { + if(Sectorbitmap_is_set(map, i / sector_size, 0) == 0) { + byte= ((off_t) 2048) * ((off_t) (i - start_lbas[sect])) + sect_base; + if(*damage_start < 0 || byte < *damage_start) + *damage_start= byte; + if(byte + (off_t) 2048 > *damage_end) + *damage_end= byte + (off_t) 2048; + } + } + sect_base+= ((off_t) 2048) * + ((off_t) (end_lbas[sect] - start_lbas[sect] + 1)); + } + if(*damage_end > size) + *damage_end= size; + if(start_lbas != NULL) + free((char *) start_lbas); + if(end_lbas != NULL) + free((char *) end_lbas); + if(*damage_start < 0) + return(0); + return(1); +} + + +int Xorriso_report_lba(struct XorrisO *xorriso, char *show_path, + IsoNode *node, int flag) +{ + int ret, *start_lbas= NULL, *end_lbas= NULL, lba_count, i; + off_t size; + char sfe[5*SfileadrL]; + + ret= Xorriso__start_end_lbas(node, &lba_count, &start_lbas, &end_lbas, + &size, 0); + if(ret < 0) { + Xorriso_process_msg_queues(xorriso, 0); + {ret= -1; goto ex;} + } + if(ret == 0) + {ret= 1; goto ex;} /* it is ok to ignore other types */ + for(i= 0; i < lba_count; i++) { + sprintf(xorriso->result_line, + "File data lba: %2d , %8d , %8d , %8.f , %s\n", + i, start_lbas[i], end_lbas[i] + 1 - start_lbas[i], (double) size, + Text_shellsafe(show_path, sfe, 0)); + Xorriso_result(xorriso, 0); + } + ret= 1; +ex:; + if(start_lbas != NULL) + free((char *) start_lbas); + if(end_lbas != NULL) + free((char *) end_lbas); + return(ret); +} + + +int Xorriso_report_damage(struct XorrisO *xorriso, char *show_path, + IsoNode *node, int flag) +{ + int ret; + off_t size= 0, damage_start, damage_end; + char sfe[5*SfileadrL]; + + ret= Xorriso_file_eval_damage(xorriso, node, &damage_start, &damage_end, 0); + if(ret < 0) + return(0); + + if(LIBISO_ISREG(node)) + size= iso_file_get_size((IsoFile *) node); + if(ret > 0) { + sprintf(xorriso->result_line, "File damaged : %8.f , %8.f , %8.f , %s\n", + (double) damage_start, (double) (damage_end - damage_start) , + (double) size, Text_shellsafe(show_path, sfe, 0)); + Xorriso_result(xorriso, 0); + } else { + sprintf(xorriso->result_line, "File seems ok: %8.f , %8.f , %8.f , %s\n", + -1.0, -1.0, (double) size, Text_shellsafe(show_path, sfe, 0)); + Xorriso_result(xorriso, 0); + } + return(1); +} + + +/* @param flag bit0= not a command parameter (directory iteration or recursion) + bit1= do not count deleted files with rm and rm_r + @return <=0 error, + 1=ok + 2=ok, node has been deleted, + 3=ok, do not dive into directory (e.g. because it is a split file) +*/ +int Xorriso_findi_action(struct XorrisO *xorriso, struct FindjoB *job, + IsoDirIter *boss_iter, off_t boss_mem, + char *abs_path, char *show_path, + IsoNode *node, int depth, int flag) +{ + int ret= 0, type, action= 0, hflag, deleted= 0, no_dive= 0; + uid_t user= 0; + gid_t group= 0; + time_t date= 0; + mode_t mode_or= 0, mode_and= ~1; + char *target, sfe[5*SfileadrL], *iso_prefix; + struct FindjoB *subjob; + struct stat dir_stbuf; + + action= Findjob_get_action_parms(job, &target, &user, &group, + &mode_and, &mode_or, &type, &date, &subjob, 0); + if(action<0) + action= 0; + + hflag= 16*!(flag&2); + if(action==1) { /* rm (including rmdir) */ + ret= Xorriso_fake_stbuf(xorriso, abs_path, &dir_stbuf, &node, 1); + if(ret>0) { + if(S_ISDIR(dir_stbuf.st_mode)) + hflag= 2; + ret= Xorriso_rmi(xorriso, boss_iter, boss_mem, abs_path, hflag); + deleted= 1; + } + } else if(action==2) { /* rm_r */ + ret= Xorriso_rmi(xorriso, boss_iter, boss_mem, abs_path, 1|hflag); + deleted= 1; + } else if(action==3) { + + /* >>> mv target */; + + } else if(action==4) { /* chown */ + ret= Xorriso_set_uid(xorriso, abs_path, user, 0); + } else if(action==5) { /* chgrp */ + ret= Xorriso_set_gid(xorriso, abs_path, group, 0); + } else if(action==6) { /* chmod */ + ret= Xorriso_set_st_mode(xorriso, abs_path, mode_and, mode_or, 0); + } else if(action==7) { /* alter_date */ + ret= Xorriso_set_time(xorriso, abs_path, date, type&7); + } else if(action==8) { /* lsdl */ + ret= Xorriso_ls_filev(xorriso, "", 1, &abs_path, (off_t) 0, 1|2|8); + } else if(action>=9 && action<=13) { /* actions which have own findjobs */ + Findjob_set_start_path(subjob, abs_path, 0); + ret= Xorriso_findi(xorriso, subjob, boss_iter, boss_mem, NULL, + abs_path, &dir_stbuf, depth, 1); + } else if(action==14 || action==17) { /* compare , update */ + Findjob_get_start_path(job, &iso_prefix, 0); + ret= Xorriso_find_compare(xorriso, (void *) boss_iter, abs_path, + iso_prefix, target, (action==17)|((flag&1)<<1)); + if(ret==2) + deleted= 1; + if(ret==3) + no_dive= 1; + if(ret>=0) + ret= 1; + } else if(action==16 || action==18) { /* not_in_iso , add_missing */ + ; + } else if(action == 21) { /* report_damage */ + ret= Xorriso_report_damage(xorriso, show_path, node, 0); + } else if(action == 22) { + ret= Xorriso_report_lba(xorriso, show_path, node, 0); + } else if(action == 23) { + ret= Findjob_set_found_path(job, show_path, 0); + } else { /* includes : 15 in_iso */ + sprintf(xorriso->result_line, "%s\n", Text_shellsafe(show_path, sfe, 0)); + Xorriso_result(xorriso, 0); + ret= 1; + } + if(ret<=0) + return(ret); + if(deleted) + return(2); + if(no_dive) + return(3); + return(1); +} + + +int Xorriso_findi_test(struct XorrisO *xorriso, struct FindjoB *job, + IsoNode *node, char *name, + struct stat *boss_stbuf, struct stat *stbuf, + int depth, int flag) +{ + int ret, start_lba, end_lba, damage_filter, commit_filter, lba; + off_t damage_start, damage_end, size; + int lba_count, *file_end_lbas= NULL, *file_start_lbas= NULL, i; + void *wanted_node; + + ret= Findjob_test(job, name, boss_stbuf, stbuf, depth, 1); + if(ret<=0) + return(ret); + + Findjob_get_lba_damage_filter(job, &start_lba, &end_lba, &damage_filter, 0); + if(damage_filter != 0) { + ret= Xorriso_file_eval_damage(xorriso, node, &damage_start, &damage_end, 0); + if(ret < 0) + return(ret); + if((damage_filter > 0) != (ret > 0)) + return(0); + } + if(start_lba >= 0 && end_lba >= 0) { + ret= Xorriso__start_end_lbas(node, &lba_count, + &file_start_lbas, &file_end_lbas, &size, 0); + if(ret <= 0) { + Xorriso_process_msg_queues(xorriso, 0); + goto ex; + } + for(i= 0; i < lba_count; i++) { + if(file_end_lbas[i] < start_lba || file_start_lbas[i] > end_lba) + {ret= 0; goto ex;} + } + } + Findjob_get_commit_filter(job, &commit_filter, 0); + if(commit_filter & 1) { /* -pending_data */ + if(!LIBISO_ISREG(node)) + {ret= 0; goto ex;} + ret= Xorriso__file_start_lba(node, &lba, 0); + if(ret > 0 && lba >= 0) + {ret= 0; goto ex;} + } + Findjob_get_wanted_node(job, &wanted_node, 0); + if(wanted_node != NULL && ((IsoNode *) wanted_node) != node) + {ret= 0; goto ex;} + ret= 1; +ex:; + if(file_start_lbas != NULL) + free((char *) file_start_lbas); + if(file_end_lbas != NULL) + free((char *) file_end_lbas); + return(ret); +} + + +/* @param flag bit0= recursion + bit1= do not count deleted files with rm and rm_r + @return <=0 error, 1= ok , 2= dir node and path has been deleted +*/ +int Xorriso_findi(struct XorrisO *xorriso, struct FindjoB *job, + void *boss_iter, off_t boss_mem, + void *dir_node_generic, char *dir_path, + struct stat *dir_stbuf, int depth, int flag) +{ + int ret, action= 0, hflag, deleted= 0, no_dive= 0; + IsoDirIter *iter= NULL; + IsoDir *dir_node= NULL; + IsoNode *node, *iso_node; + IsoImage *volume= NULL; + struct stat stbuf; + char *name; + off_t mem; + IsoNode **node_array= NULL; + int node_count, node_idx; + char *path= NULL, *abs_path= NULL; + + path= malloc(SfileadrL); + abs_path= malloc(SfileadrL); + if(path==NULL || abs_path==NULL) { + Xorriso_no_malloc_memory(xorriso, &path, 0); + {ret= -1; goto ex;} + } + + action= Findjob_get_action(job, 0); + if(action<0) + action= 0; + if(!(flag & 1)) { + if(action == 21) { + sprintf(xorriso->result_line, "Report layout: %8s , %8s , %8s , %s\n", + "at byte", "Range", "Filesize", "ISO image path"); + Xorriso_result(xorriso, 0); + } else if(action == 22) { + sprintf(xorriso->result_line, + "Report layout: %2s , %8s , %8s , %8s , %s\n", + "xt", "Startlba", "Blocks", "Filesize", "ISO image path"); + Xorriso_result(xorriso, 0); + } + } + + dir_node= (IsoDir *) dir_node_generic; + if(dir_node==NULL) { + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + {ret= -1; goto ex;} + ret= Xorriso_make_abs_adr(xorriso, xorriso->wdi, dir_path, path, 1|2|4); + if(ret<=0) + goto ex; + ret= Xorriso_node_from_path(xorriso, volume, path, &iso_node, 0); + dir_node= (IsoDir *) iso_node; + if(ret<=0) + {ret= 0; goto ex;} + ret= Xorriso_fake_stbuf(xorriso, "", dir_stbuf, &iso_node, 1); + if(ret<=0) + goto ex; + + name= strrchr(dir_path, '/'); + if(name==NULL) + name= dir_path; + else + name++; + + ret= Xorriso_findi_test(xorriso, job, iso_node, name, NULL, dir_stbuf, + depth, 0); + if(ret<0) + goto ex; + if(ret>0) { + ret= Xorriso_findi_action(xorriso, job, + (IsoDirIter *) boss_iter, boss_mem, + path, dir_path, (IsoNode *) dir_node, depth, + flag&(1|2)); + if(ret<=0) + goto ex; + if(ret==2) { + /* re-determine dir_node in case it has a new persona */ + ret= Xorriso_node_from_path(xorriso, volume, path, &iso_node, 1); + if(ret==0) { + deleted= 1; + {ret= 2; goto ex;} + } + if(ret<0) + {ret= 0; goto ex;} + dir_node= (IsoDir *) iso_node; + ret= Xorriso_fake_stbuf(xorriso, "", dir_stbuf, &iso_node, 1); + if(ret<=0) + goto ex; + } + if(ret==3) + no_dive= 1; + } + } + if(no_dive || !LIBISO_ISDIR((IsoNode *) dir_node)) + {ret= 1; goto ex;} + if(Xorriso_is_split(xorriso, dir_path, (IsoNode *) dir_node, 1)>0) + {ret= 1; goto ex;} + + mem= boss_mem; + hflag= 1; + if(action==1 || action==2 || action==3 || action==17) + hflag|= 2; /* need freedom to manipulate image */ + if(action==14 || action==17) + hflag|= 4; /* need LBA sorted iteration for good data reading performance */ + ret= Xorriso_findi_iter(xorriso, dir_node, &mem, + &iter, &node_array, &node_count, &node_idx, + &node, hflag); + if(ret<=0) + goto ex; + while(1) { + ret= Xorriso_findi_iter(xorriso, dir_node, &mem, &iter, + &node_array, &node_count, &node_idx, &node, 0); + if(ret<0) + goto ex; + if(ret==0 || xorriso->request_to_abort) + break; + name= (char *) iso_node_get_name(node); + ret= Xorriso_make_abs_adr(xorriso, dir_path, name, path, 4); + if(ret<=0) + goto ex; + ret= Xorriso_fake_stbuf(xorriso, "", &stbuf, &node, 1); + if(ret<0) + goto ex; + if(ret==0) + continue; + +/* ??? This seems to be redundant with the single test above + ??? Should i dive in unconditionally and leave out test and action here ? + ??? Then do above test unconditionally ? + --- Seems that the current configuration represents the special + handling of the find start path with mount points. Dangerous to change. +*/ + + ret= Xorriso_findi_test(xorriso, job, node, name, dir_stbuf, &stbuf, + depth, 0); + if(ret<0) + goto ex; + if(ret>0) { + ret= Xorriso_make_abs_adr(xorriso, xorriso->wdi, path, abs_path, 1|2|4); + if(ret<=0) + goto ex; + ret= Xorriso_findi_action(xorriso, job, iter, mem, + abs_path, path, node, depth, 1|(flag&2)); + if(ret==2) { /* node has been deleted */ + /* re-determine node in case it has a new persona */ + if(volume==NULL) { + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + {ret= -1; goto ex;} + } + ret= Xorriso_node_from_path(xorriso, volume, abs_path, &node, 1); + if(ret==0) + continue; + if(ret<0) + {ret= 0; goto ex;} + ret= Xorriso_fake_stbuf(xorriso, "", &stbuf, &node, 1); + if(ret<0) + goto ex; + if(ret==0) + continue; + } + no_dive= (ret==3); + if(ret<=0) { + if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0) + goto ex; + } + } + + if(S_ISDIR(stbuf.st_mode) && !no_dive) { + ret= Xorriso_findi(xorriso, job, (void *) iter, mem, + (void *) node, path, &stbuf, depth+1, flag|1); + if(ret<0) + goto ex; + } + } + + ret= 1; +ex:; + if(path!=NULL) + free(path); + if(abs_path!=NULL) + free(abs_path); + Xorriso_process_msg_queues(xorriso,0); + + Xorriso_findi_iter(xorriso, dir_node, &mem, &iter, &node_array, &node_count, + &node_idx, &node, (1<<31)); + if(ret<=0) + return(ret); + if(deleted) + return(2); + return(1); +} + + +/* @param flag bit0= use lba rather than node pointer +*/ +int Xorriso_path_from_node(struct XorrisO *xorriso, IsoNode *node, int lba, + char path[SfileadrL], int flag) +{ + int ret; + struct FindjoB *job= NULL; + struct stat dir_stbuf; + char *found_path; + + path[0]= 0; + if((flag & 1) && lba <= 0) + return(0); + + ret= Findjob_new(&job, "/", 0); + if(ret <= 0) { + Xorriso_no_findjob(xorriso, "path_from_node", 0); + return(ret); + } + if(flag & 1) + Findjob_set_lba_range(job, lba, 1, 0); + else + Findjob_set_wanted_node(job, (void *) node, 0); + Findjob_set_action_found_path(job, 0); + ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0, + NULL, "/", &dir_stbuf, 0, 0); + if(ret > 0) { + ret= 1; + Findjob_get_found_path(job, &found_path, 0); + if(found_path == NULL) + ret= 0; + else if(Sfile_str(path, found_path, 0) <= 0) + ret= -1; + } + Findjob_destroy(&job, 0); + return(ret); +} + + +/* @param flag bit0= do not mark image as changed */ +int Xorriso_set_volid(struct XorrisO *xorriso, char *volid, int flag) +{ + int ret; + IsoImage *volume; + + if(xorriso->in_volset_handle == NULL) + return(2); + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(ret); + iso_image_set_volume_id(volume, volid); + if(!(flag&1)) + xorriso->volset_change_pending= 1; + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text,"Volume ID: '%s'",iso_image_get_volume_id(volume)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + return(1); +} + + +int Xorriso_get_volid(struct XorrisO *xorriso, char volid[33], int flag) +{ + int ret; + IsoImage *volume; + + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(ret); + strncpy(volid, iso_image_get_volume_id(volume), 32); + volid[32]= 0; + return(1); +} + + +#ifdef NIX + +/* @param flag bit0= do not mark image as changed */ +int Xorriso_set_publisher(struct XorrisO *xorriso, char *name, int flag) +{ + int ret; + IsoImage *volume; + + if(xorriso->in_volset_handle == NULL) + return(2); + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(ret); + iso_image_set_publisher_id(volume, name); + + if(!(flag&1)) + xorriso->volset_change_pending= 1; + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text,"Publisher: '%s'", + iso_image_get_publisher_id(volume)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + return(1); +} + + +/* @param flag bit0= do not mark image as changed */ +int Xorriso_set_application_id(struct XorrisO *xorriso, char *name, int flag) +{ + int ret; + IsoImage *volume; + + if(xorriso->in_volset_handle == NULL) + return(2); + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(ret); + iso_image_set_application_id(volume, name); + + if(!(flag&1)) + xorriso->volset_change_pending= 1; + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text,"Application id: '%s'", + iso_image_get_application_id(volume)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + return(1); +} + +#endif /* NIX */ + + +/* @param flag bit0=prepare for a burn run */ +int Xorriso_set_abort_severity(struct XorrisO *xorriso, int flag) +{ + int ret, abort_on_number; + char *sev_text; + static int note_number= -1, failure_number= -1; + + if(note_number==-1) + Xorriso__text_to_sev("NOTE", ¬e_number, 0); + if(failure_number==-1) + Xorriso__text_to_sev("FAILURE", &failure_number, 0); + sev_text= xorriso->abort_on_text; + ret= Xorriso__text_to_sev(xorriso->abort_on_text, &abort_on_number, 0); + if(ret<=0) + return(ret); + if(abort_on_numberfailure_number) + sev_text= "FAILURE"; + ret= iso_set_abort_severity(sev_text); + return(ret>=0); +} + + +int Xorriso_report_lib_versions(struct XorrisO *xorriso, int flag) +{ + int major, minor, micro; + int req_major, req_minor, req_micro; + + iso_lib_version(&major, &minor, µ); + isoburn_libisofs_req(&req_major, &req_minor, &req_micro); + sprintf(xorriso->result_line, + "libisofs in use : %d.%d.%d (min. %d.%d.%d)\n", + major, minor, micro, req_major, req_minor, req_micro); + Xorriso_result(xorriso, 0); + burn_version(&major, &minor, µ); + isoburn_libburn_req(&req_major, &req_minor, &req_micro); + sprintf(xorriso->result_line, + "libburn in use : %d.%d.%d (min. %d.%d.%d)\n", + major, minor, micro, req_major, req_minor, req_micro); + Xorriso_result(xorriso, 0); + isoburn_version(&major, &minor, µ); + sprintf(xorriso->result_line, + "libisoburn in use : %d.%d.%d (min. %d.%d.%d)\n", + major, minor, micro, + isoburn_header_version_major, isoburn_header_version_minor, + isoburn_header_version_micro); + Xorriso_result(xorriso, 0); + return(1); +} + + +/* @param flag bit0= -inq + bit1= -checkdrive +*/ +int Xorriso_atip(struct XorrisO *xorriso, int flag) +{ + int ret, profile_number= 0; + char *respt, profile_name[80]; + double x_speed_max, x_speed_min= -1.0; + struct burn_drive_info *dinfo; + struct burn_drive *drive; + enum burn_disc_status s; + + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to print drive and media info", 2); + if(ret<=0) + return(0); + respt= xorriso->result_line; + sprintf(respt, "Device type : "); + ret= burn_drive_get_drive_role(drive); + if(ret==0) + sprintf(respt+strlen(respt), "%s\n", "Emulated (null-drive)"); + else if(ret==2) + sprintf(respt+strlen(respt), "%s\n", + "Emulated (stdio-drive, 2k random read-write)"); + else if(ret==3) + sprintf(respt+strlen(respt), "%s\n", + "Emulated (stdio-drive, sequential write-only)"); + else if(ret!=1) + sprintf(respt+strlen(respt), "%s\n","Emulated (stdio-drive)"); + else + sprintf(respt+strlen(respt), "%s\n","Removable CD-ROM"); + sprintf(respt+strlen(respt), "Vendor_info : '%s'\n",dinfo->vendor); + sprintf(respt+strlen(respt), "Identifikation : '%s'\n",dinfo->product); + sprintf(respt+strlen(respt), "Revision : '%s'\n",dinfo->revision); + Xorriso_result(xorriso,1); + if(flag&1) + return(1); + sprintf(respt, "Driver flags : BURNFREE\n"); + sprintf(respt+strlen(respt), "Supported modes: SAO TAO\n"); + Xorriso_result(xorriso,1); + if(flag&2) + return(1); + + s= burn_disc_get_status(drive); + ret= burn_disc_get_profile(drive,&profile_number,profile_name); + if(ret<=0) { + profile_number= 0; + strcpy(profile_name, "-unidentified-"); + } + if(s != BURN_DISC_UNSUITABLE) { + ret= burn_disc_read_atip(drive); + if(ret>0) { + ret= burn_drive_get_min_write_speed(drive); + x_speed_min= ((double) ret)/176.4; + } + } + if(s==BURN_DISC_EMPTY) { + sprintf(respt, "Current: none\n"); + Xorriso_result(xorriso,1); + return(1); + } else + sprintf(respt, "Current: %s\n",profile_name); + Xorriso_result(xorriso,1); + if(strstr(profile_name,"DVD")==profile_name) { + sprintf(respt, "book type: %s (emulated booktype)\n", profile_name); + Xorriso_result(xorriso,1); + if(profile_number == 0x13) { + sprintf(respt, "xorriso: message for sdvdbackup: \"(growisofs mode Restricted Overwrite)\"\n"); + Xorriso_result(xorriso,1); + } + } else { + sprintf(respt, "ATIP info from disk:\n"); + Xorriso_result(xorriso,1); + if(burn_disc_erasable(drive)) + sprintf(respt, " Is erasable\n"); + else + sprintf(respt, " Is not erasable\n"); + Xorriso_result(xorriso,1); + { int start_lba,end_lba,min,sec,fr; + ret= burn_drive_get_start_end_lba(drive,&start_lba,&end_lba,0); + if(ret>0) { + burn_lba_to_msf(start_lba,&min,&sec,&fr); + sprintf(respt, " ATIP start of lead in: %d (%-2.2d:%-2.2d/%-2.2d)\n", + start_lba,min,sec,fr); + Xorriso_result(xorriso,1); + burn_lba_to_msf(end_lba,&min,&sec,&fr); + sprintf(respt, " ATIP start of lead out: %d (%-2.2d:%-2.2d/%-2.2d)\n", + end_lba,min,sec,fr); + Xorriso_result(xorriso,1); + } + } + ret= burn_drive_get_write_speed(drive); + x_speed_max= ((double) ret)/176.4; + if(x_speed_min<0) + x_speed_min= x_speed_max; + sprintf(respt, + " 1T speed low: %.f 1T speed high: %.f\n",x_speed_min,x_speed_max); + Xorriso_result(xorriso,1); + } + return(1); +} + + +int Xorriso_update_in_sector_map(struct XorrisO *xorriso, + struct SpotlisT *spotlist, int read_chunk, + struct CheckmediajoB *job, int flag) +{ + int sectors, sector_size, sector_blocks, ret; + struct SectorbitmaP *map; + + Sectorbitmap_destroy(&(xorriso->in_sector_map), 0); + if(job->use_dev == 1) + return(1); + map= job->sector_map; + sectors= Spotlist_block_count(spotlist, 0); + if(sectors <= 0) + return(0); + sector_size= Spotlist_sector_size(spotlist, read_chunk, 0); + sector_blocks= sector_size / 2048; + if(sector_blocks > 1) + sectors= sectors / sector_blocks + !!(sectors % sector_blocks); + ret= Sectorbitmap_new(&(xorriso->in_sector_map), sectors, sector_size, 0); + if(ret <= 0) + return(ret); + if(map != NULL) + Sectorbitmap_copy(map, xorriso->in_sector_map, 0); + ret= Xorriso_spotlist_to_sectormap(xorriso, spotlist, read_chunk, + &(xorriso->in_sector_map), 1); + return(ret); +} + + +/* + @param flag bit0= obtain iso_lba from indev + bit1= head_buffer already contains a valid head + bit2= issue message about success + bit3= check whether source blocks are banned by in_sector_map +*/ +int Xorriso_update_iso_lba0(struct XorrisO *xorriso, int iso_lba, int isosize, + char *head_buffer, struct CheckmediajoB *job, + int flag) +{ + int ret, full_size, i; + char *headpt; + struct burn_drive_info *dinfo; + struct burn_drive *drive; + off_t seek_ret; + + if(flag & 1) { + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to learn current session lba", 1); + if(ret<=0) + return(0); + ret= isoburn_disc_get_msc1(drive, &iso_lba); + if(ret<=0) + return(0); + drive= NULL; /* indev will not be used furtherly */ + } + if(job == NULL) { + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to update at lba 0 to 31", 2); + if(ret<=0) + return(0); + } + if(iso_lba < 32) + return(2); + if(!(flag & 2)) { + /* head_buffer was not filled yet. Read it from output media. */ + if(job != NULL && job->data_to_fd >= 0) { + if((flag & 8) && job->sector_map != NULL) { + ret= Sectorbitmap_bytes_are_set(job->sector_map, + ((off_t) iso_lba) * (off_t) 2048, + ((off_t) (iso_lba + 32)) * ((off_t) 2048) - (off_t) 1, 0); + if(ret <= 0) { + sprintf(xorriso->info_text, + "ISO image head at lba %d is marked as invalid blocks in file copy", + iso_lba); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", + 0); + return(0); + } + } + seek_ret= lseek(job->data_to_fd, ((off_t) 2048) * (off_t) iso_lba, + SEEK_SET); + if(seek_ret == -1) + ret= 0; + else + ret= read(job->data_to_fd, head_buffer, 64 * 1024); + if(ret < 64 * 1024) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "Cannot read ISO image head from file copy"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); + return(0); + } + } else { + ret= isoburn_read_iso_head(drive, iso_lba, &isosize, head_buffer, 2); + if(ret<=0) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "Cannot read freshly written ISO image head"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + } + } + /* patch ISO header */ + full_size= iso_lba + isosize; + headpt= head_buffer + 32*1024; + for(i=0;i<4;i++) + headpt[87-i]= headpt[80+i]= (full_size >> (8*i)) & 0xff; + + if(job != NULL) { + seek_ret= lseek(job->data_to_fd, (off_t) 0, SEEK_SET); + if(seek_ret == -1) + ret= 0; + else + ret= write(job->data_to_fd, head_buffer, 64 * 1024); + if(ret < 64 * 1024) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "Cannot write ISO image head to file copy"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); + return(0); + } + } else { + ret= burn_random_access_write(drive, (off_t) 0, head_buffer, + (off_t) (64*1024), 1); + if(ret<=0) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "Cannot write new ISO image head to LBA 0"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + } + if(flag & 4) { + sprintf(xorriso->info_text, + "Overwrote LBA 0 to 31 by 64 KiB from LBA %d", iso_lba); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + } + return(1); +} + + +/* @param write_start_address is valid if >=0 + @param tsize is valid if >0 + @param flag bit0= grow_overwriteable_iso + bit1= do_isosize +*/ +int Xorriso_burn_track(struct XorrisO *xorriso, off_t write_start_address, + char *track_source, off_t tsize, int flag) +{ + int ret, fd, unpredicted_size, profile_number, is_cd= 0, dummy, nwa= -1; + int isosize= -1, do_isosize, is_bd= 0; + + struct burn_drive_info *dinfo; + struct burn_drive *drive; + struct burn_write_opts *burn_options; + struct burn_disc *disc= NULL; + struct burn_session *session; + struct burn_track *track; + struct stat stbuf; + off_t fixed_size= 0; + struct burn_source *data_src, *fifo_src; + enum burn_disc_status disc_state; + char reasons[BURN_REASONS_LEN], sfe[5*SfileadrL], profile_name[80]; + char head_buffer[64*1024]; + + ret= Xorriso_auto_format(xorriso, 0); + if(ret <=0 ) + return(0); + + do_isosize= !!(flag&2); + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to burn track", 2); + if(ret<=0) + return(0); + ret= Xorriso_make_write_options(xorriso, drive, &burn_options, 0); + if(ret<=0) + goto ex; + + disc= burn_disc_create(); + session= burn_session_create(); + ret= burn_disc_add_session(disc,session,BURN_POS_END); + if(ret==0) { + sprintf(xorriso->info_text, "Cannot add session object to disc object."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + goto ex; + } + track= burn_track_create(); + if(track_source[0] == '-' && track_source[1] == 0) { + fd= 0; + } else { + fd= open(track_source, O_RDONLY); + if(fd>=0) + if(fstat(fd,&stbuf)!=-1) + if((stbuf.st_mode&S_IFMT)==S_IFREG) + fixed_size= stbuf.st_size; + } + if(fixed_size==0) + unpredicted_size= 1; + + data_src= NULL; + if(fd>=0) + data_src= burn_fd_source_new(fd, -1, fixed_size); + if(data_src==NULL) { + sprintf(xorriso->info_text, "Could not open data source %s", + Text_shellsafe(track_source,sfe,0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + ret= 0; goto ex; + } + if(do_isosize && xorriso->fs < 64) + xorriso->fs= 64; + fifo_src= burn_fifo_source_new(data_src, 2048, xorriso->fs, 0); + if(fifo_src == NULL) { + sprintf(xorriso->info_text, "Could not create fifo object of 4 MB"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + ret= 0; goto ex; + } + xorriso->pacifier_fifo= fifo_src; + if(burn_track_set_source(track, fifo_src)!=BURN_SOURCE_OK) { + sprintf(xorriso->info_text, + "Cannot attach source object to track object"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + ret= 0; goto ex; + } + burn_session_add_track(session, track, BURN_POS_END); + burn_source_free(data_src); + + if(flag&1) + /* consider overwriteables with ISO as appendable */ + disc_state= isoburn_disc_get_status(drive); + else + /* handle overwriteables as always blank */ + disc_state= burn_disc_get_status(drive); + + if(disc_state == BURN_DISC_BLANK || disc_state == BURN_DISC_APPENDABLE) { + /* ok */; + } else { + if(disc_state == BURN_DISC_FULL) { + sprintf(xorriso->info_text, + "Closed media with data detected. Need blank or appendable media."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + if(burn_disc_erasable(drive)) { + sprintf(xorriso->info_text, "Try -blank as_needed\n"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0); + } + } else if(disc_state == BURN_DISC_EMPTY) { + sprintf(xorriso->info_text, "No media detected in drive"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + } else { + sprintf(xorriso->info_text, + "Cannot recognize state of drive and media"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + } + ret= 0; goto ex; + } + if(isoburn_needs_emulation(drive)) + burn_write_opts_set_multi(burn_options, 0); + + if(tsize > 0) { + fixed_size= tsize; + burn_track_set_size(track, fixed_size); + } + if(do_isosize) { + ret= burn_fifo_peek_data(xorriso->pacifier_fifo, head_buffer, 64*1024, 0); + if(ret<=0) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "Cannot obtain first 64 kB from input stream."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + /* read isosize from head_buffer, not from media*/ + ret= isoburn_read_iso_head(drive, 0, &isosize, head_buffer, (1<<13)); + if(ret<=0) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "Option -isosize given but data stream seems not to be ISO 9660"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + sprintf(xorriso->info_text, "Size of ISO 9660 image: %ds", isosize); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + fixed_size= ((off_t) (isosize)) * (off_t) 2048; + burn_track_set_size(track, fixed_size); + } + + ret= Xorriso_get_profile(xorriso, &profile_number, profile_name, 2); + is_cd= (ret==2); + is_bd= (ret == 3); + + if(isoburn_needs_emulation(drive)) { + if(flag&1) { + ret= isoburn_disc_track_lba_nwa(drive, burn_options, 0, &dummy, &nwa); + if(ret<=0) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "Cannot obtain next writeable address of emulated multi-session media\n"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + if(nwa==32) + nwa= 0; /* No automatic toc emulation. Formatter might not be aware. */ + burn_write_opts_set_start_byte(burn_options,((off_t) nwa) * (off_t) 2048); + } else { + nwa= 0; + burn_write_opts_set_start_byte(burn_options, (off_t) 0); + } + } + + if(write_start_address>=0) { + nwa= write_start_address / (off_t) 2048; + if(((off_t) nwa) * (off_t) 2048 < write_start_address ) + nwa++; + burn_write_opts_set_start_byte(burn_options, ((off_t) nwa) * (off_t) 2048); + } + + if(burn_write_opts_auto_write_type(burn_options, disc, reasons, 0) == + BURN_WRITE_NONE) { + sprintf(xorriso->info_text, + "Failed to find a suitable write mode with this media.\n"); + sprintf(xorriso->info_text+strlen(xorriso->info_text), + "Reasons given:\n%s", reasons); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + + ret= Xorriso_sanitize_image_size(xorriso, drive, disc, burn_options, 2); + if(ret<=0) + goto ex; + + xorriso->run_state= 1; /* Indicate that burning has started */ + burn_disc_write(burn_options, disc); + + ret= Xorriso_pacifier_loop(xorriso, drive, 2 | (is_cd << 4) | (is_bd << 5)); + if(ret<=0) + goto ex; + if(!burn_drive_wrote_well(drive)) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "libburn indicates failure with writing."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + + if(flag & 1) { + ret= Xorriso_update_iso_lba0(xorriso, nwa, isosize, head_buffer, NULL, + flag & 2); + if(ret <= 0) + goto ex; + } + sprintf(xorriso->info_text, "Writing to %s completed sucessfully.\n\n", + Text_shellsafe(xorriso->outdev,sfe,0)); + Xorriso_info(xorriso, 0); + ret= 1; +ex:; + Xorriso_process_msg_queues(xorriso,0); + if(disc!=NULL) + burn_disc_free(disc); + if(xorriso->pacifier_fifo!=NULL) + burn_source_free(xorriso->pacifier_fifo); + xorriso->pacifier_fifo= NULL; + xorriso->run_state= 0; /* Indicate that burning has ended */ + return(ret); +} + + +/* @param flag bit1= outdev rather than indev + @return <0 error, 0 = no profile to see , 1= ok , 2= ok, is CD profile + 3= ok, is BD profile +*/ +int Xorriso_get_profile(struct XorrisO *xorriso, int *profile_number, + char profile_name[80], int flag) +{ + int ret; + struct burn_drive_info *dinfo; + struct burn_drive *drive; + + *profile_number= 0; + profile_name[0]= 0; + if(((flag&2) && xorriso->out_drive_handle==NULL) || + ((!(flag&2)) && xorriso->in_drive_handle==NULL)) + return(0); + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to determine media type", flag&2); + if(ret<=0) + return(0); + ret=burn_disc_get_profile(drive, profile_number, profile_name); + if(ret<=0) + return(ret); + if(*profile_number==0x08 || *profile_number==0x09 || *profile_number==0x0a) + return(2); + if(*profile_number == 0x40 || *profile_number == 0x41 || + *profile_number == 0x42 || *profile_number == 0x43) + return(3); + return(0); +} + + +int Xorriso_iso_file_open(struct XorrisO *xorriso, char *pathname, + void *node_pt, void **stream, int flag) +{ + int ret; + char eff_path[SfileadrL]; + IsoNode *node= NULL; + IsoFile *filenode= NULL; + IsoStream *iso_stream= NULL; + + *stream= NULL; + if(flag&1) { + node= (IsoNode *) node_pt; + } else { + ret= Xorriso_get_node_by_path(xorriso, pathname, eff_path, &node, 0); + if(ret<=0) + return(ret); + } + if(!LIBISO_ISREG(node)) { + sprintf(xorriso->info_text, + "Given path does not lead to a regular data file in the image"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + + filenode= (IsoFile *) node; + iso_stream= iso_file_get_stream(filenode); + if(iso_stream==NULL) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "Could not obtain source stream of file in the image for reading"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + ret= iso_stream_open(iso_stream); + if(ret<0) { + sprintf(xorriso->info_text, + "Could not open data file in the image for reading"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + if(!iso_stream_is_repeatable(iso_stream)) { + sprintf(xorriso->info_text, + "The data production of the file in the image is one-time only"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + iso_stream_close(iso_stream); + return(0); + } + Xorriso_process_msg_queues(xorriso,0); + *stream= iso_stream; + +#ifdef NIX + /* <<< */ + { + unsigned int fs_id; + dev_t dev_id; + ino_t ino; + + iso_stream_get_id(iso_stream, &fs_id, &dev_id, &ino); + fprintf(stderr, "xorriso_debug: iso_ino= %ld\n", (long int) ino); + } +#endif + + return(1); +} + + +int Xorriso_iso_file_read(struct XorrisO *xorriso, void *stream, char *buf, + int count, int flag) +{ + int ret, rcnt= 0; + IsoStream *stream_pt; + + stream_pt= (IsoStream *) stream; + + while(rcntcovered) + incomplete= 1; + else if(offset covered) + covered= offset+bytes; + } + if(total_bytes>covered) + incomplete= 1; + memcpy(total_stbuf, &first_stbuf, sizeof(struct stat)); + total_stbuf->st_size= total_bytes; + ret= !(overlapping || ((flag&2)&&incomplete)); +ex:; + if(iter!=NULL) + iso_dir_iter_free(iter); + return(ret); +} + + +/* @param flag bit0= node is valid, do not resolve path + bit1= insist in complete collection of part files +*/ +int Xorriso_is_split(struct XorrisO *xorriso, char *path, void *node, + int flag) +{ + struct SplitparT *split_parts= NULL; + int split_count= 0, ret; + struct stat stbuf; + + ret= Xorriso_identify_split(xorriso, path, node, &split_parts, + &split_count, &stbuf, flag & 3); + if(split_parts!=NULL) + Splitparts_destroy(&split_parts, split_count, 0); + return(ret>0); +} + + +/* @param flag bit0= grow_overwriteable_iso + bit1= obtain info from outdev +*/ +int Xorriso_msinfo(struct XorrisO *xorriso, int *msc1, int *msc2, int flag) +{ + int ret, dummy; + struct burn_drive *drive; + struct burn_drive_info *dinfo; + enum burn_disc_status disc_state; + + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to obtain msinfo", flag&2); + if(ret<=0) + return(ret); + + if(flag&1) + disc_state= isoburn_disc_get_status(drive); + else + disc_state= burn_disc_get_status(drive); + if(disc_state != BURN_DISC_APPENDABLE) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "%s media is not appendable. Cannot obtain -msinfo.", + (flag&2) ? "Output" : "Input"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + ret= isoburn_disc_get_msc1(drive, msc1); + if(ret<=0) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, "Cannot obtain address of most recent session"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + ret= isoburn_disc_track_lba_nwa(drive, NULL, 0, &dummy, msc2); + if(ret<0) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, "Cannot obtain next writeable address on media"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + return(1); +} + +/* @param flag bit0= this is a follow-up session (i.e. on CD: TAO) + bit1= no pacifier messages + @return <=0 error, 1= done, 2= aborted due to limit +*/ +int Xorriso_check_interval(struct XorrisO *xorriso, struct SpotlisT *spotlist, + struct CheckmediajoB *job, + int from_lba, int block_count, int read_chunk, + int flag) +{ + int i, j, ret, total_count= 0, sectors= -1, sector_size= -1, skip_reading; + int prev_quality= -1, quality= -1, retry= 0, profile_no, is_cd= 0; + int start_sec, end_sec, first_value, fret; + char profile_name[80]; + int start_lba= 0; + struct burn_drive *drive; + struct burn_drive_info *dinfo; + char data[64*1024], sfe[5*SfileadrL]; + off_t data_count, to_read, read_count= 0, write_amount; + double pre_read_time, post_read_time, time_diff, total_time_diff= 0; + double last_abort_file_time= 0; + struct stat stbuf; + + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to check media readability", + 2 * !!job->use_dev); + if(ret<=0) + goto ex; + ret= burn_disc_get_profile(drive, &profile_no, profile_name); + if(ret > 0) + if(profile_no >= 0x08 && profile_no <= 0x0a) + is_cd= 1; + + if(job->sector_map != NULL) { + Sectorbitmap_get_layout(job->sector_map, §ors, §or_size, 0); + sector_size/= 2048; + } + + if(job->retry > 0) + retry= 1; + else if(job->retry == 0 && is_cd) + retry= 1; + + start_lba= from_lba; + to_read= read_chunk; + post_read_time= Sfile_microtime(0); + for(i= 0; i < block_count; i+= to_read) { + skip_reading= 0; + + if(job->abort_file_path[0]) { + if(post_read_time - last_abort_file_time >= 0.1) { + if(stat(job->abort_file_path, &stbuf) != -1) { + if(stbuf.st_mtime >= xorriso->start_time) { + sprintf(xorriso->info_text, + "-check_media: Found fresh abort_file=%s", + job->abort_file_path); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + goto abort_check; + } + } + last_abort_file_time= post_read_time; + } + } + if(job->item_limit > 0 && + Spotlist_count(spotlist, 0) + 2 >= job->item_limit) { + sprintf(xorriso->info_text, "-check_media: Reached item_limit=%d", + job->item_limit); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + goto abort_check; + } + pre_read_time= Sfile_microtime(0); + if(job->time_limit > 0 + && job->start_time + job->time_limit < pre_read_time) { + sprintf(xorriso->info_text, "-check_media: Reached time_limit=%d", + job->time_limit); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); +abort_check:; + if(prev_quality >= 0) { + ret= Spotlist_add_item(spotlist, start_lba, i + from_lba - start_lba, + prev_quality, 0); + if(ret <= 0) + goto ex; + } + ret= Spotlist_add_item(spotlist, i + from_lba, block_count - i, + Xorriso_read_quality_untesteD, 0); + if(ret > 0) + ret= 2; + goto ex; + } + + to_read= read_chunk; + if(i + to_read > block_count) + to_read= block_count - i; + if(is_cd && i + to_read + 2 >= block_count) { + /* Read last 2 blocks of CD track separately, because with TAO tracks + they are always unreadable but with SAO tracks they contain data. + */ + if(to_read > 2) + to_read-= 2; + else if(to_read > 1) { + if(flag & 1) { + quality= Xorriso_read_quality_tao_enD; + skip_reading= 1; + } else + to_read--; + } + } + + if(sector_size == read_chunk && from_lba % read_chunk == 0 + && !skip_reading) { + if(Sectorbitmap_is_set(job->sector_map, (i + from_lba) / sector_size, 0)){ + quality= Xorriso_read_quality_valiD; + skip_reading= 1; + } + } else if(sector_size > 0 && !skip_reading) { + start_sec= (i + from_lba) / sector_size; + end_sec= (i + to_read + from_lba) / sector_size; + first_value= Sectorbitmap_is_set(job->sector_map, start_sec, 0); + for(j= start_sec; j < end_sec; j++) + if(Sectorbitmap_is_set(job->sector_map, j, 0) != first_value) + break; + to_read= j * sector_size - i - from_lba; + skip_reading= !!first_value; + if(skip_reading) + quality= Xorriso_read_quality_valiD; + } + + if(skip_reading) { + pre_read_time= post_read_time= Sfile_microtime(0); + } else { + data_count= 0; + pre_read_time= Sfile_microtime(0); + ret= burn_read_data(drive, ((off_t) (i + from_lba)) * (off_t) 2048, data, + to_read * (off_t) 2048, &data_count, 4 * !retry); + post_read_time= Sfile_microtime(0); + time_diff= post_read_time - pre_read_time; + total_time_diff+= time_diff; + total_count++; + if(ret <= 0) { + Xorriso_process_msg_queues(xorriso,0); + if(data_count / 2048 < to_read) { + if(data_count > 0 && retry) { + if(prev_quality >= 0) { + ret= Spotlist_add_item(spotlist, start_lba, + i + from_lba - start_lba, prev_quality, 0); + if(ret <= 0) + goto ex; + } + ret= Spotlist_add_item(spotlist, i + from_lba, data_count / 2048, + Xorriso_read_quality_partiaL, 0); + if(ret <= 0) + goto ex; + start_lba= i + from_lba + data_count / 2048; + prev_quality= Xorriso_read_quality_unreadablE; + } + quality= Xorriso_read_quality_unreadablE; + if(retry) + to_read= data_count / 2048 + 1; + } else + quality= Xorriso_read_quality_partiaL; + fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); + if(fret<0) + goto ex; + } else { + quality= Xorriso_read_quality_gooD; + + /* >>> find better threshold than 1.0 */ + + if(time_diff > 1.0 && i > 0) + quality= Xorriso_read_quality_sloW; + } + + write_amount= data_count; + if(data_count > 0) { + read_count+= data_count; + if(job->data_to_limit >= 0 && read_count > job->data_to_limit) + write_amount-= (read_count - job->data_to_limit); + } + if(write_amount > 0) { + if(job->data_to_fd >= 0) { + ret= lseek(job->data_to_fd, + ((off_t) (i + from_lba)) * (off_t) 2048 + job->data_to_offset, + SEEK_SET); + if(ret == -1) { +failed_to_write:; + sprintf(xorriso->info_text, "Cannot write %d bytes to lba %d of %s", + (int) data_count, i + from_lba, + Text_shellsafe(job->data_to_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, + "FAILURE", 0); + {ret= 0; goto ex;} + } + ret= write(job->data_to_fd, data, write_amount); + if(ret == -1) + goto failed_to_write; + } + } + } + if(quality != prev_quality) { + if(prev_quality >= 0) { + ret= Spotlist_add_item(spotlist, start_lba, i + from_lba - start_lba, + prev_quality, 0); + if(ret <= 0) + goto ex; + } + start_lba= i + from_lba; + prev_quality= quality; + } + if(!(flag & 2)) { + xorriso->pacifier_count+= to_read; + if(post_read_time - xorriso->last_update_time >= + xorriso->pacifier_interval) + Xorriso_pacifier_callback(xorriso, "sectors examined", + xorriso->pacifier_count, xorriso->pacifier_total, "", 0); + } + } + if(prev_quality >= 0) { + ret= Spotlist_add_item(spotlist, start_lba, + block_count + from_lba - start_lba, prev_quality, 0); + if(ret <= 0) + goto ex; + } + + /* <<< for calibration of quality */ + if(total_count > 0) { + sprintf(xorriso->info_text, "Xorriso_check_interval: %.1f s / %d = %f", + total_time_diff, total_count, total_time_diff / total_count); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + } + + ret= 1; +ex: + return(ret); +} + + +int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist, + struct CheckmediajoB *job, int flag) +{ + int media_blocks= 0, read_chunk= 16, ret, mode, start_lba= 0; + int blocks, os_errno, i, j, last_track_end= -1, track_blocks, track_lba; + int num_sessions, num_tracks, declare_untested= 0; + char *toc_info= NULL; + struct burn_drive *drive; + struct burn_drive_info *dinfo; + struct isoburn_toc_disc *isoburn_disc= NULL; + struct isoburn_toc_session **isoburn_sessions; + struct isoburn_toc_track **iso_burn_tracks; + struct burn_toc_entry isoburn_entry; + struct stat stbuf; + struct burn_multi_caps *caps= NULL; + + *spotlist= NULL; + + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to check media readability", + 2 * !!job->use_dev); + if(ret<=0) + goto ex; + + /* >>> determine media type dependent blocking factor: + 32 kB for CD (with 2kB retry) and DVD, 64 kB for BD + eventually adjust read_chunk + */; + + ret= Spotlist_new(spotlist, 0); + if(ret <= 0) + {ret= -1; goto ex;} + + if(job->sector_map_path[0]) { + Sectorbitmap_destroy(&(job->sector_map), 0); + if(stat(job->sector_map_path, &stbuf) != -1) { + ret= Sectorbitmap_from_file(&(job->sector_map), job->sector_map_path, + xorriso->info_text, &os_errno, 0); + if(ret <= 0) { + if(xorriso->info_text[0]) + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, os_errno, + "FAILURE", 0); + goto ex; + } + } + Xorriso_toc_to_string(xorriso, &toc_info, 4 * !job->map_with_volid); + } + ret= Xorriso_open_job_data_to(xorriso, job, 0); + if(ret <= 0) + goto ex; + Xorriso_pacifier_reset(xorriso, 0); + job->start_time= time(NULL); + mode= job->mode; + if(job->min_lba > 0) { + start_lba= job->min_lba; + ret= Spotlist_add_item(*spotlist, 0, job->min_lba, + Xorriso_read_quality_untesteD, 0); + if(ret <= 0) + goto ex; + } + if(job->max_lba >= 0) { + blocks= job->max_lba + 1 - start_lba; + xorriso->pacifier_total= blocks; + ret= Xorriso_check_interval(xorriso, *spotlist, job, start_lba, blocks, + read_chunk, 0); + if(ret <= 0) + goto ex; + + } else if(mode == 0) { /* track by track */ + isoburn_disc= isoburn_toc_drive_get_disc(drive); + if(isoburn_disc == NULL) + goto no_content_visible; + isoburn_sessions= + isoburn_toc_disc_get_sessions(isoburn_disc, &num_sessions); + for(i= 0; i < num_sessions; i++) { + iso_burn_tracks= isoburn_toc_session_get_tracks(isoburn_sessions[i], + &num_tracks); + for(j= 0; j < num_tracks; j++) { + isoburn_toc_track_get_entry(iso_burn_tracks[j], &isoburn_entry); + if(!(isoburn_entry.extensions_valid & 1)) /* should not happen */ + continue; + track_lba= isoburn_entry.start_lba; + track_blocks= isoburn_entry.track_blocks; + if(i == 0 && j == 0) { + if(track_lba == 32) { + ret= burn_disc_get_multi_caps(drive, BURN_WRITE_NONE, &caps, 0); + if(ret > 0) { + if(caps->start_adr) { + /* block 0 to 31 are the overall mount entry of overwriteable */ + track_lba= 0; + track_blocks+= 32; + } + } + } + } + if(last_track_end >= 0 && last_track_end < track_lba && + last_track_end >= start_lba) { + ret= Spotlist_add_item(*spotlist, last_track_end, + track_lba - last_track_end, + Xorriso_read_quality_off_tracK, 0); + if(ret <= 0) + goto ex; + xorriso->pacifier_count+= track_lba - last_track_end; + } + last_track_end= track_lba + track_blocks; + + if(track_lba < start_lba) { + track_blocks-= start_lba - track_lba; + track_lba= start_lba; + } + if(track_blocks <= 0) + continue; + if(declare_untested) { + ret= Spotlist_add_item(*spotlist, track_lba, track_blocks, + Xorriso_read_quality_untesteD, 0); + if(ret <= 0) + goto ex; + } else { + ret= Xorriso_check_interval(xorriso, *spotlist, job, track_lba, + track_blocks, read_chunk, i > 0); + if(ret <= 0) + goto ex; + if(ret == 2) + declare_untested= 1; + } + } + } + + } else if(mode == 1) { /* isoburn disc capacity */ + isoburn_disc= isoburn_toc_drive_get_disc(drive); + if(isoburn_disc == NULL) { +no_content_visible:; + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, "No content detected on media"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + blocks= media_blocks= isoburn_toc_disc_get_sectors(isoburn_disc); + if(start_lba >= 0) + blocks-= start_lba; + if(media_blocks <= 0) + goto no_content_visible; + xorriso->pacifier_total= blocks; + ret= Xorriso_check_interval(xorriso, *spotlist, job, start_lba, blocks, + read_chunk, 0); + if(ret <= 0) + goto ex; + } else if(mode == 2) { + + /* >>> single sweep over libburn media capacity */; + + } + + Xorriso_pacifier_callback(xorriso, "sectors examined", + xorriso->pacifier_count, xorriso->pacifier_total, "", 1); + ret= 1; +ex:; + + if(job->data_to_fd != -1) + close(job->data_to_fd); + job->data_to_fd= -1; + + if(ret > 0) + ret= Xorriso_update_in_sector_map(xorriso, *spotlist, read_chunk, job, 0); + + if(ret > 0) { + ret= Xorriso_spotlist_to_sectormap(xorriso, *spotlist, read_chunk, + &(job->sector_map), 0); + if(ret > 0 && job->sector_map_path[0]) { + ret= Sectorbitmap_to_file(job->sector_map, job->sector_map_path, toc_info, + xorriso->info_text, &os_errno, 0); + if(ret <= 0) { + if(xorriso->info_text[0]) + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, os_errno, + "FAILURE", 0); + } + } + } + if(toc_info != NULL) + free(toc_info); + if(ret <= 0) + Spotlist_destroy(spotlist, 0); + if(caps!=NULL) + burn_disc_free_multi_caps(&caps); + return(ret); +} + + +/* @param flag bit1= for Xorriso_check_interval(): no pacifier messages +*/ +int Xorriso_read_file_data(struct XorrisO *xorriso, IsoNode *node, + char *img_path, char *disk_path, + off_t img_offset, off_t disk_offset, + off_t bytes, int flag) +{ + int ret, i, lba_count= 0, *start_lbas= NULL, *end_lbas= NULL, read_chunk= 16; + int lba, count, blocks, quality, spot, bad_extract= 0; + off_t size= 0, file_base_bytes= 0, file_processed_bytes= 0, img_adr; + off_t new_file_base_bytes, upto_file_bytes, start_byte= 0; + char sfe[5*SfileadrL]; + struct SpotlisT *spotlist= NULL; + struct CheckmediajoB *job= NULL; + + upto_file_bytes= img_offset + bytes; + + /* >>> make Xorriso_check_interval() ready for copying in byte granularity */ + if(img_offset % (off_t) 2048) { + sprintf(xorriso->info_text, + "Image address offset is not a multiple of 2048"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + + ret= Xorriso__start_end_lbas(node, &lba_count, &start_lbas, &end_lbas, &size, + 0); + if(ret <= 0) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "File object %s is currently not a data file from the loaded image", + Text_shellsafe(img_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + goto ex; + } + if(img_offset + bytes < size && bytes > 0) + size= img_offset + bytes; + + ret= Checkmediajob_new(&job, 0); + if(ret <= 0) + goto ex; + if(xorriso->check_media_default != NULL) + Checkmediajob_copy(xorriso->check_media_default, job, 0); + job->min_lba= -1; + job->max_lba= -1; + job->sector_map_path[0]= 0; + + ret= Spotlist_new(&spotlist, 0); + if(ret <= 0) + {ret= -1; goto ex;} + + if(Sfile_str(job->data_to_path, disk_path, 0) <= 0) + {ret= -1; goto ex;} + Xorriso_open_job_data_to(xorriso, job, 0); + if(ret <= 0) + goto ex; + + for(i= 0; i < lba_count && file_base_bytes < upto_file_bytes; i++) { + lba= start_lbas[i]; + count= end_lbas[i] + 1 - start_lbas[i]; + new_file_base_bytes= file_base_bytes + ((off_t) count) * (off_t) 2048; + + /* skip intervals before img_offset */ + if(new_file_base_bytes <= img_offset) { + file_base_bytes= new_file_base_bytes; + continue; + } + /* Eventually adjust first interval start */ + img_adr= ((off_t) lba) * (off_t) 2048; + if(file_base_bytes < img_offset) { + img_adr+= img_offset - file_base_bytes; + lba= img_adr / (off_t) 2048; + count= end_lbas[i] + 1 - lba; + file_base_bytes= img_offset; + } + + /* Eventually omit surplus blocks */ + if(new_file_base_bytes > upto_file_bytes) + count-= (new_file_base_bytes - upto_file_bytes) / (off_t) 2048; + /* Adjust job */ + job->data_to_offset= file_processed_bytes - img_adr + disk_offset; + job->data_to_limit= size - file_base_bytes; + + file_processed_bytes+= ((off_t) count) * (off_t) 2048; + ret= Xorriso_check_interval(xorriso, spotlist, job, lba, count, read_chunk, + (flag & 2)); + if(ret <= 0) + goto ex; + if (ret == 2) { + sprintf(xorriso->info_text, "Attempt aborted to extract data from %s", + Text_shellsafe(img_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + file_base_bytes= new_file_base_bytes; + } + + /* Use spotlist to evaluate damage */ + file_base_bytes= 0; + count= Spotlist_count(spotlist, 0); + for(spot= 0; spot < count; spot++) { + ret= Spotlist_get_item(spotlist, spot, &lba, &blocks, &quality, 0); + if(ret <= 0) + continue; + if(quality < Xorriso_read_quality_valiD) { + for(i= 0; i < lba_count; i++) { + if(start_lbas[i] <= lba && end_lbas[i] >= lba) { + start_byte= (lba - start_lbas[i]) * (off_t) 2048 + file_base_bytes; + break; + } + file_base_bytes+= ((off_t) (end_lbas[i] + 1 - start_lbas[i])) + * (off_t) 2048; + } + if(i < lba_count) { + sprintf(xorriso->info_text, "Bad extract : %14.f , %14.f , %s\n", + (double) start_byte, ((double) blocks) * 2048.0, + Text_shellsafe(disk_path, sfe, 0)); + Xorriso_info(xorriso, 0); + bad_extract= 1; + } + } + } + + ret= !bad_extract; +ex:; + if(start_lbas != NULL) + free((char *) start_lbas); + if(end_lbas != NULL) + free((char *) end_lbas); + Spotlist_destroy(&spotlist, 0); + Checkmediajob_destroy(&job, 0); + return(ret); +} + + +int Xorriso_extract_cut(struct XorrisO *xorriso, + char *img_path, char *disk_path, + off_t img_offset, off_t bytes, int flag) +{ + int ret, stbuf_ret; + double mem_lut= 0.0; + char eff_img_path[SfileadrL], eff_disk_path[SfileadrL]; + IsoImage *volume; + IsoNode *node; + + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(ret); + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, + img_path, eff_img_path, 0); + if(ret<=0) + return(ret); + ret= Xorriso_node_from_path(xorriso, volume, eff_img_path, &node, 0); + if(ret<=0) + return(ret); + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, + disk_path, eff_disk_path, 2 | 4); + if(ret<=0) + return(ret); + Xorriso_pacifier_reset(xorriso, 0); + mem_lut= xorriso->last_update_time; + + ret= Xorriso_handle_collision(xorriso, node, img_path, eff_disk_path, + disk_path, &stbuf_ret, 0); + if(ret<=0 || ret==3) + return(0); + ret= Xorriso_read_file_data(xorriso, node, eff_img_path, eff_disk_path, + img_offset, (off_t) 0, bytes, 0); + if(ret<=0) + return(ret); + ret= Xorriso_restore_properties(xorriso, eff_disk_path, node, 0); + if(ret<=0) + return(ret); + + if(mem_lut != xorriso->last_update_time) + Xorriso_pacifier_callback(xorriso, "sectors examined", + xorriso->pacifier_count, 0, "", 1); + return(1); +} + + +int Xorriso_get_local_charset(struct XorrisO *xorriso, char **name, int flag) +{ + (*name)= iso_get_local_charset(0); + return(1); +} + + +int Xorriso_set_local_charset(struct XorrisO *xorriso, char *name, int flag) +{ + int ret; + char *nl_charset, sfe[5 * SfileadrL]; + iconv_t iconv_ret= (iconv_t) -1; + + nl_charset= nl_langinfo(CODESET); + if(name == NULL) + name= nl_charset; + + if(name != NULL) { + iconv_ret= iconv_open(nl_charset, name); + if(iconv_ret == (iconv_t) -1) + goto cannot; + else + iconv_close(iconv_ret); + } + ret= iso_set_local_charset(name, 0); + if(ret <= 0) { +cannot:; + sprintf(xorriso->info_text, + "-local_charset: Cannot assume as local character set: %s", + Text_shellsafe(name, sfe, 0)); + return(0); + } + sprintf(xorriso->info_text, "Local character set is now assumed as: %s", + Text_shellsafe(name, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(1); +} + + +int Xorriso_relax_compliance(struct XorrisO *xorriso, char *mode, + int flag) +{ + char *npt, *cpt; + int l, was; + + was= xorriso->relax_compliance; + npt= cpt= mode; + for(; npt!=NULL; cpt= npt+1) { + npt= strchr(cpt,':'); + if(npt==NULL) + l= strlen(cpt); + else + l= npt-cpt; + if(l == 0) + continue; + if((l == 6 && strncmp(cpt, "strict", l) == 0) || + (l == 5 && strncmp(cpt, "clear", l) == 0)) { + xorriso->relax_compliance= 0; + } else if(l == 7 && strncmp(cpt, "default", l) == 0) { + xorriso->relax_compliance= Xorriso_relax_compliance_defaulT; + + } else if((l == 12 && strncmp(cpt, "omit_version", l) == 0) || + (l == 15 && strncmp(cpt, "omit_version_on", l) == 0) ) { + xorriso->relax_compliance|= isoburn_igopt_omit_version_numbers; + } else if((l == 16 && strncmp(cpt, "omit_version_off", l) == 0)) { + xorriso->relax_compliance&= ~isoburn_igopt_omit_version_numbers; + + } else if((l == 10 && strncmp(cpt, "deep_paths", l) == 0) || + (l == 13 && strncmp(cpt, "deep_paths_on", l) == 0)) { + xorriso->relax_compliance|= isoburn_igopt_allow_deep_paths; + } else if(l == 14 && strncmp(cpt, "deep_paths_off", l) == 0) { + xorriso->relax_compliance&= ~isoburn_igopt_allow_deep_paths; + + } else if((l == 10 && strncmp(cpt, "long_paths", l) == 0) || + (l == 13 && strncmp(cpt, "long_paths_on", l) == 0) ) { + xorriso->relax_compliance|= isoburn_igopt_allow_longer_paths; + } else if(l == 14 && strncmp(cpt, "long_paths_off", l) == 0) { + xorriso->relax_compliance&= ~isoburn_igopt_allow_longer_paths; + + } else if((l == 10 && strncmp(cpt, "long_names", l) == 0) || + (l == 13 && strncmp(cpt, "long_names_on", l) == 0)) { + xorriso->relax_compliance|= isoburn_igopt_max_37_char_filenames; + } else if(l == 14 && strncmp(cpt, "long_names_off", l) == 0) { + xorriso->relax_compliance&= ~isoburn_igopt_max_37_char_filenames; + + } else if((l == 13 && strncmp(cpt, "no_force_dots", l) == 0) || + (l == 16 && strncmp(cpt, "no_force_dots_on", l) == 0)) { + xorriso->relax_compliance|= isoburn_igopt_no_force_dots; + } else if(l == 17 && strncmp(cpt, "no_force_dots_off", l) == 0) { + xorriso->relax_compliance&= ~isoburn_igopt_no_force_dots; + + } else if((l == 9 && strncmp(cpt, "lowercase", l) == 0) || + (l == 12 && strncmp(cpt, "lowercase_on", l) == 0)) { + xorriso->relax_compliance|= isoburn_igopt_allow_lowercase; + } else if(l == 13 && strncmp(cpt, "lowercase_off", l) == 0) { + xorriso->relax_compliance&= ~isoburn_igopt_allow_lowercase; + + } else if((l == 10 && strncmp(cpt, "full_ascii", l) == 0) || + (l == 13 && strncmp(cpt, "full_ascii_on", l) == 0)) { + xorriso->relax_compliance|= isoburn_igopt_allow_full_ascii; + } else if(l == 14 && strncmp(cpt, "full_ascii_off", l) == 0) { + xorriso->relax_compliance&= ~isoburn_igopt_allow_full_ascii; + + } else if((l == 17 && strncmp(cpt, "joliet_long_paths", l) == 0) || + (l == 20 && strncmp(cpt, "joliet_long_paths_on", l) == 0)) { + xorriso->relax_compliance|= isoburn_igopt_joliet_longer_paths; + } else if(l == 21 && strncmp(cpt, "joliet_long_paths_off", l) == 0) { + xorriso->relax_compliance&= ~isoburn_igopt_joliet_longer_paths; + + } else if((l == 10 && strncmp(cpt, "always_gmt", l) == 0) || + (l == 13 && strncmp(cpt, "always_gmt_on", l) == 0)) { + xorriso->relax_compliance|= isoburn_igopt_always_gmt; + } else if(l == 14 && strncmp(cpt, "always_gmt_off", l) == 0) { + xorriso->relax_compliance&= ~isoburn_igopt_always_gmt; + + } else if((l == 6 && strncmp(cpt, "old_rr", l) == 0) || + (l == 9 && strncmp(cpt, "old_rr_on", l) == 0)) { + xorriso->relax_compliance|= isoburn_igopt_rrip_version_1_10; + } else if(l == 10 && strncmp(cpt, "old_rr_off", l) == 0) { + xorriso->relax_compliance&= ~isoburn_igopt_rrip_version_1_10; + + } else if((l == 9 && strncmp(cpt, "rec_mtime", l) == 0) || + (l == 12 && strncmp(cpt, "rec_mtime_on", l) == 0)) { + xorriso->relax_compliance|= isoburn_igopt_dir_rec_mtime; + } else if(l == 13 && strncmp(cpt, "rec_mtime_off", l) == 0) { + xorriso->relax_compliance&= ~isoburn_igopt_dir_rec_mtime; + + } else if((l == 8 && strncmp(cpt, "iso_9660", l) == 0) || + (l == 11 && strncmp(cpt, "iso_9660_on", l) == 0)) { + /* may have a meaning in future */; + } else if(l == 12 && strncmp(cpt, "iso_9660_off", l) == 0) { + /* may have a meaning in future */; + Xorriso_msgs_submit(xorriso, 0, + "-compliance -iso_9660_off : Cannot do anything else but ISO 9660", + 0, "FAILURE", 0); + + } else { + if(linfo_text, "-relax_compliance: unknown rule '%s'", + cpt); + else + sprintf(xorriso->info_text, + "-relax_compliance: oversized rule parameter (%d)", l); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + xorriso->relax_compliance= was; + return(0); + } + } + return(1); +} + + +/* @return 1=ok 2=ok, is default setting */ +int Xorriso_get_relax_text(struct XorrisO *xorriso, char mode[1024], + int flag) +{ + int r; + + r= xorriso->relax_compliance; + if(r == 0) { + strcpy(mode, "strict"); + return(1); + } + strcpy(mode, "clear"); + if(r & isoburn_igopt_omit_version_numbers) + strcat(mode, ":omit_version"); + if(r & isoburn_igopt_allow_deep_paths) + strcat(mode, ":deep_paths"); + if(r & isoburn_igopt_allow_longer_paths) + strcat(mode, ":long_paths"); + if(r & isoburn_igopt_max_37_char_filenames) + strcat(mode, ":long_names"); + if(r & isoburn_igopt_no_force_dots) + strcat(mode, ":no_force_dots"); + if(r & isoburn_igopt_allow_lowercase) + strcat(mode, ":lowercase"); + if(r & isoburn_igopt_allow_full_ascii) + strcat(mode, ":full_ascii"); + if(r & isoburn_igopt_joliet_longer_paths) + strcat(mode, ":joliet_long_paths"); + if(r & isoburn_igopt_always_gmt) + strcat(mode, ":always_gmt"); + if(r & isoburn_igopt_rrip_version_1_10) + strcat(mode, ":old_rr"); + if(r & isoburn_igopt_dir_rec_mtime) + strcat(mode, ":rec_mtime"); + return(1 + (r == Xorriso_relax_compliance_defaulT)); +} + + +/** + @param flag bit0= print mount command to result channel rather than + performing it + bit1= do not allow prefixes with cmd + bit2= interpret unprefixed cmd as shell: +*/ +int Xorriso_mount(struct XorrisO *xorriso, char *dev, int adr_mode, + char *adr_value, char *cmd, int flag) +{ + int ret, lba, track, session, params_flag= 0, is_safe= 0, is_extra_drive= 0; + int give_up= 0, mount_chardev= 0, status; + char volid[33], *devadr, mount_command[SfileadrL], adr_data[163], *adr_pt; + char *dev_path, libburn_adr[BURN_DRIVE_ADR_LEN + SfileadrL]; + char sfe[5 * SfileadrL], *dpt, *sysname= ""; + struct stat stbuf; + struct burn_drive_info *dinfo= NULL; + struct burn_drive *drive= NULL; + + devadr= dev; + adr_pt= adr_value; + if(strcmp(dev, "indev") == 0) { + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to perform -mount \"indev\"", 0); + if(ret<=0) + goto ex; + dev_path= devadr= xorriso->indev; + if(strncmp(dev_path, "stdio:", 6) == 0) + dev_path+= 6; + if(xorriso->in_drive_handle == xorriso->out_drive_handle) + give_up= 3; + else + give_up= 1; + } else if(strcmp(dev, "outdev") == 0) { + ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, + "on attempt to perform -mount \"outdev\"", + 2); + if(ret<=0) + goto ex; + dev_path= devadr= xorriso->outdev; + if(strncmp(dev_path, "stdio:", 6) == 0) + dev_path+= 6; + if(xorriso->in_drive_handle == xorriso->out_drive_handle) + give_up= 3; + else + give_up= 2; + } else { + is_extra_drive= 1; + dev_path= dev; + if(strncmp(dev_path, "stdio:", 6) == 0) + dev_path+= 6; + + /* do only accept regular files and block devices */ + ret= stat(dev_path, &stbuf); + if(ret == -1) { + sprintf(xorriso->info_text, "Cannot determine properties of file %s", + Text_shellsafe(dev_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + ret= System_uname(&sysname, NULL, NULL, NULL, 0); + if(ret > 0 && strcmp(sysname, "FreeBSD") == 0) + mount_chardev= 1; + if(!(S_ISREG(stbuf.st_mode) || (S_ISBLK(stbuf.st_mode) && !mount_chardev) + || (S_ISCHR(stbuf.st_mode) && !mount_chardev))) { + sprintf(xorriso->info_text, + "File object is not suitable as mount device: %s", + Text_shellsafe(dev_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + + /* Aquire drive as direct libburn address or via stdio: prefix */ + ret= burn_drive_convert_fs_adr(dev, libburn_adr); + Xorriso_process_msg_queues(xorriso,0); + if(ret < 0) + {ret= -1; goto ex;} + if(ret == 0 && strncmp(dev, "stdio:", 6) != 0) + sprintf(libburn_adr, "stdio:%s", dev); + ret= isoburn_drive_aquire(&dinfo, libburn_adr, 1); + Xorriso_process_msg_queues(xorriso,0); + if(ret <= 0) + {ret= 0; goto ex;} + drive= dinfo[0].drive; + } + + if(adr_mode == 4 && strlen(adr_pt) <= 80) { + ret= Xorriso__bourne_to_reg(adr_pt, adr_data, 0); + if(ret == 1) { + params_flag|= 4; + adr_pt= adr_data; + } + } + ret= isoburn_get_mount_params(drive, adr_mode, adr_pt, &lba, &track, + &session, volid, params_flag); + Xorriso_process_msg_queues(xorriso,0); + if(ret <= 0) + goto ex; + if(session <= 0 || track <= 0 || ret == 2) { + Xorriso_msgs_submit(xorriso, 0, + "-mount : Given address does not point to an ISO 9660 session", + 0, "FAILURE", 0); + ret= 0; goto ex; + } + if(strstr(devadr, "stdio:") == devadr) + devadr+= 6; + ret= Xorriso_make_mount_cmd(xorriso, cmd, lba, track, session, volid, devadr, + mount_command, flag & (2 | 4)); + if(ret <= 0) + goto ex; + if(ret == 2) + is_safe= 1; + + if(is_extra_drive) { + isoburn_drive_release(drive, 0); + burn_drive_info_free(dinfo); + drive= NULL; + } else if(give_up > 0 && !(flag & 1)) { + Xorriso_give_up_drive(xorriso, give_up); + if(ret <= 0) + goto ex; + } + Xorriso_process_msg_queues(xorriso,0); + + sprintf(xorriso->info_text, "Volume id : %s\n", + Text_shellsafe(volid, sfe, 0)); + Xorriso_info(xorriso, 0); + if(flag & 1) { + sprintf(xorriso->result_line, "%s\n", mount_command); + Xorriso_result(xorriso,0); + } else { + sprintf(xorriso->info_text, "Mount command: %s\n", mount_command); + Xorriso_info(xorriso, 0); + if(!is_safe) { + Xorriso_msgs_submit(xorriso, 0, + "-mount : Will not perform mount command which stems from command template.", + 0, "SORRY", 0); + sprintf(xorriso->result_line, "%s\n", mount_command); + Xorriso_result(xorriso,0); + +#ifdef NIX + + } else if(geteuid() != getuid() || getgid() != getegid()) { + Xorriso_msgs_submit(xorriso, 0, + "-mount : Detected own setuid/gid identity. Will not perform mount command.", + 0, "SORRY", 0); + sprintf(xorriso->result_line, "%s\n", mount_command); + Xorriso_result(xorriso,0); + } else { + /* >>> find safer way to perform command */; + ret= system(mount_command); + if(WIFEXITED(ret) && WEXITSTATUS(ret) != 0) { + sprintf(xorriso->info_text, + "-mount : mount command failed with exit value %d", + (int) WEXITSTATUS(ret)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + +#else + + } else { + ret= Xorriso_execv(xorriso, mount_command, "/bin:/sbin", &status, 1); + if(WIFEXITED(status) && WEXITSTATUS(status) != 0) { + sprintf(xorriso->info_text, + "-mount : mount command failed with exit value %d", + (int) WEXITSTATUS(ret)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + +#endif + + sprintf(xorriso->info_text, "\nMounted session %d of device %s", + session, Text_shellsafe(dev_path, sfe, 0)); + dpt= strchr(cmd, ':'); + if(dpt == NULL) + dpt= cmd ; + else + dpt++; + sprintf(xorriso->info_text + strlen(xorriso->info_text), + " as directory %s\n", Text_shellsafe(dpt, sfe, 0)); + Xorriso_info(xorriso, 0); + } + } + ret= 1; +ex:; + if(is_extra_drive && drive != NULL) { + isoburn_drive_release(drive, 0); + burn_drive_info_free(dinfo); + Xorriso_process_msg_queues(xorriso,0); + } + return(ret); +} + + +int Xorriso_auto_driveadr(struct XorrisO *xorriso, char *adr, char *result, + int flag) +{ + int ret, is_known_mmc= 0; + char *path_pt, libburn_adr[BURN_DRIVE_ADR_LEN + SfileadrL]; + char *abs_pt, abs_adr[SfileadrL]; + + path_pt= adr; + if(strncmp(adr, "stdio:", 6) == 0) + path_pt= adr + 6; + else if(strncmp(adr, "mmc:", 4) == 0) + path_pt= adr + 4; + + + /* <<< replace by Xorriso_normalize_img_path() ? */; + + if(path_pt[0] != '/') { + abs_pt= getcwd(abs_adr, SfileadrL - 1); + if(abs_pt == NULL) { + Xorriso_msgs_submit(xorriso, 0, + "Relative drive path given. Cannot determine working directory.", + errno, "FAILURE", 0); + return(-1); + } + ret= Sfile_add_to_path(abs_adr, path_pt, 0); + if(ret <= 0) + return(-1); + } + + + ret= Xorriso_is_in_patternlist(xorriso, xorriso->drive_whitelist, path_pt, 0); + if(ret > 0) + goto ok; + ret= Xorriso_is_in_patternlist(xorriso, xorriso->drive_blacklist, path_pt, 0); + if(ret < 0) + return(ret); + if(ret) { + strcpy(xorriso->info_text, "Drive address "); + Text_shellsafe(adr, xorriso->info_text, 1); + strcat(xorriso->info_text, + " rejected because: -drive_class 'banned' "); + Text_shellsafe(Xorriso_get_pattern(xorriso, xorriso->drive_blacklist, + ret - 1, 0), + xorriso->info_text, 1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + /* if in greylist and not MMC and not stdio prefix: reject */ + is_known_mmc= burn_drive_convert_fs_adr(path_pt, libburn_adr); + Xorriso_process_msg_queues(xorriso,0); + if(is_known_mmc < 0) + return(ret); + if(adr == path_pt && !is_known_mmc) { /* no prefix, no MMC */ + ret= Xorriso_is_in_patternlist(xorriso, xorriso->drive_greylist, path_pt,0); + if(ret < 0) + return(ret); + if(ret) { + strcpy(xorriso->info_text, "Drive address "); + Text_shellsafe(adr, xorriso->info_text, 1); + strcat(xorriso->info_text, + " rejected because: not MMC and -drive_class 'risky' "); + Text_shellsafe(Xorriso_get_pattern(xorriso,xorriso->drive_greylist, + ret - 1, 0), + xorriso->info_text, 1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + Xorriso_msgs_submit(xorriso, 0, + "If the address is a legitimate target, prepend \"stdio:\"", + 0, "HINT", 0); + return(0); + } + } +ok:; + if(strncmp(adr, "mmc:", 4) == 0) { + if(Sfile_str(result, path_pt, 0) <= 0) + return(0); + } else if(adr == path_pt && !is_known_mmc) { + Sfile_str(result, "stdio:", 0); + if(Sfile_str(result, adr, 1) <= 0) + return(0); + } else { + if(Sfile_str(result, adr, 0) <= 0) + return(0); + } + if(strncmp(result, "stdio:", 6)==0) { + if(xorriso->ban_stdio_write) { + strcpy(xorriso->info_text, "Drive address banned by -ban_stdio_write : "); + Text_shellsafe(result, xorriso->info_text, 1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + } + return(1); +} + diff --git a/libisoburn/branches/ZeroThreeTwo/xorriso/xorrisoburn.h b/libisoburn/branches/ZeroThreeTwo/xorriso/xorrisoburn.h new file mode 100644 index 00000000..f06111d2 --- /dev/null +++ b/libisoburn/branches/ZeroThreeTwo/xorriso/xorrisoburn.h @@ -0,0 +1,392 @@ + + +/* Adapter to libisoburn, libisofs and libburn for xorriso, + a command line oriented batch and dialog tool which creates, loads, + manipulates and burns ISO 9660 filesystem images. + + Copyright 2007-2008 Thomas Schmitt, + + Provided under GPL version 2. + + This file contains the inner isofs- and burn-library interface of xorriso. +*/ + +#ifndef Xorrisoburn_includeD +#define Xorrisoburn_includeD yes + + +/* The minimum version of libisoburn to be used with this version of xorriso +*/ +#define xorriso_libisoburn_req_major 0 +#define xorriso_libisoburn_req_minor 3 +#define xorriso_libisoburn_req_micro 1 + +int Xorriso_startup_libraries(struct XorrisO *xorriso, int flag); + +/* @param flag bit0= global shutdown of libraries */ +int Xorriso_detach_libraries(struct XorrisO *xorriso, int flag); + +int Xorriso_create_empty_iso(struct XorrisO *xorriso, int flag); + +/* @param flag bit0=aquire as isoburn input drive + bit1=aquire as libburn output drive (as isoburn drive if bit0) + @return <=0 failure , 1=success , 2=neither readable or writeable +*/ +int Xorriso_aquire_drive(struct XorrisO *xorriso, char *adr, int flag); + +int Xorriso_give_up_drive(struct XorrisO *xorriso, int flag); + +int Xorriso_write_session(struct XorrisO *xorriso, int flag); + +/* @param boss_iter Opaque handle to be forwarded to actions in ISO image + Set to NULL if calling this function from outside ISO world + @param flag bit0= mkdir: graft in as empty directory, not as copy from disk + bit1= do not report added files + @return <=0 = error , 1 = added simple node , 2 = added directory +*/ +int Xorriso_graft_in(struct XorrisO *xorriso, void *boss_iter, + char *disk_path, char *img_path, + off_t offset, off_t cut_size, int flag); + +int Xorriso__text_to_sev(char *severity_name, int *severity_number,int flag); + +/* @param flag bit0=report about output drive + bit1=short report form + bit2=do not try to read ISO heads + bit3=report to info channel (else to result channel) +*/ +int Xorriso_toc(struct XorrisO *xorriso, int flag); + +/* @param flag bit0= no output if no boot record was found + bit3= report to info channel (else to result channel) +*/ +int Xorriso_show_boot_info(struct XorrisO *xorriso, int flag); + +int Xorriso_show_devices(struct XorrisO *xorriso, int flag); + +int Xorriso_tell_media_space(struct XorrisO *xorriso, + int *media_space, int *free_space, int flag); + +/* @param flag bit0=fast , bit1=deformat + @return 0=failure, did not touch media , -1=failure, altered media + 1=success, altered media , 2=success, did not touch media +*/ +int Xorriso_blank_media(struct XorrisO *xorriso, int flag); + +/* @param flag bit0= try to achieve faster formatting + bit1= use parameter size (else use default size) + bit2= do not re-aquire drive + bit7= by_index mode: + bit8 to bit15 contain the index of the format to use. + @return 0=failure, did not touch media , -1=failure, altered media + 1=success, altered media , 2=success, did not touch media +*/ +int Xorriso_format_media(struct XorrisO *xorriso, off_t size, int flag); + +/* @return <=0 error, 1 success +*/ +int Xorriso_list_formats(struct XorrisO *xorriso, int flag); + +/* @param flag bit2= formatting rather than blanking + @return 0=failure, did not touch media , -1=failure, altered media + 1=success, altered media , 2=success, did not touch media +*/ +int Xorriso_blank_as_needed(struct XorrisO *xorriso, int flag); + + +/* @param boss_iter Opaque internal handle. Use NULL outside xorrisoburn.c : + If not NULL then this is an iterator suitable for + iso_dir_iter_remove() which is then to be used instead + of iso_node_remove(). + @param flag bit0= remove whole sub tree: rm -r + bit1= remove empty directory: rmdir + bit2= recursion: do not reassure in mode 2 "tree" + bit3= this is for overwriting and not for plain removal + @return <=0 = error + 1 = removed simple node + 2 = removed directory or tree + 3 = did not remove on user revocation +*/ +int Xorriso_rmi(struct XorrisO *xorriso, void *boss_iter, off_t boss_mem, + char *path, int flag); + +/* @param flag bit0= long format + bit1= do not print count of nodes + bit2= du format + bit3= print directories as themselves (ls -d) +*/ +int Xorriso_ls_filev(struct XorrisO *xorriso, char *wd, + int filec, char **filev, off_t boss_mem, int flag); + +/* This function needs less buffer memory than Xorriso_ls_filev() but cannot + perform structured pattern matching. + @param flag bit0= long format + bit1= only check for directory existence + bit2= do not apply search pattern but accept any file + bit3= just count nodes and return number +*/ +int Xorriso_ls(struct XorrisO *xorriso, int flag); + +/* @param wd Path to prepend in case img_path is not absolute + @param img_path Absolute or relative path to be normalized + @param eff_path returns resulting effective path. + Must provide at least SfileadrL bytes of storage. + @param flag bit0= do not produce problem events (unless faulty path format) + bit1= work purely literally, do not use libisofs + bit2= (with bit1) this is an address in the disk world + @return -1 = faulty path format, 0 = not found , + 1 = found simple node , 2 = found directory +*/ +int Xorriso_normalize_img_path(struct XorrisO *xorriso, char *wd, + char *img_path, char eff_path[], int flag); + +/* @param boss_iter Opaque handle to be forwarded to actions in ISO image + Set to NULL if calling this function from outside ISO world +*/ +int Xorriso_rename(struct XorrisO *xorriso, void *boss_iter, + char *origin, char *dest, int flag); + +/* @param flag bit0= do not produce info message on success + @return 1=success, 0=was already directory, -1=was other type, -2=bad path +*/ +int Xorriso_mkdir(struct XorrisO *xorriso, char *img_path, int flag); + +/* @param flag bit0= a match count !=1 is a SORRY event */ +int Xorriso_expand_pattern(struct XorrisO *xorriso, + int num_patterns, char **patterns, int extra_filec, + int *filec, char ***filev, off_t *mem, int flag); + +int Xorriso_set_st_mode(struct XorrisO *xorriso, char *path, + mode_t mode_and, mode_t mode_or, int flag); + +int Xorriso_set_uid(struct XorrisO *xorriso, char *in_path, uid_t uid, + int flag); + +int Xorriso_set_gid(struct XorrisO *xorriso, char *in_path, gid_t gid, + int flag); + +/* @parm flag bit0= atime, bit1= ctime, bit2= mtime, bit8=no auto ctime */ +int Xorriso_set_time(struct XorrisO *xorriso, char *in_path, time_t t, + int flag); + +/* @param flag bit0= recursion + bit1= do not count deleted files with rm and rm_r +*/ +int Xorriso_findi(struct XorrisO *xorriso, struct FindjoB *job, + void *boss_iter, off_t boss_mem, + void *dir_node_generic, char *dir_path, + struct stat *dir_stbuf, int depth, int flag); + +/* @param flag bit0= do not mark image as changed */ +int Xorriso_set_volid(struct XorrisO *xorriso, char *volid, int flag); + +int Xorriso_get_volid(struct XorrisO *xorriso, char volid[33], int flag); + +int Xorriso_set_abort_severity(struct XorrisO *xorriso, int flag); + +int Xorriso_report_lib_versions(struct XorrisO *xorriso, int flag); + +/* @return 0= stbuf content is valid , + -1 = path not found , -2 = severe error occured +*/ +int Xorriso_iso_lstat(struct XorrisO *xorriso, char *path, struct stat *stbuf, + int flag); + +/* @param flag bit0= -inq + bit1= -checkdrive +*/ +int Xorriso_atip(struct XorrisO *xorriso, int flag); + +/* @param write_start_address is valid if >=0 + @param tsize is valid if >0 + @param flag bit0= grow_overwriteable_iso + bit1= do_isosize +*/ +int Xorriso_burn_track(struct XorrisO *xorriso, off_t write_start_address, + char *track_source, off_t tsize, int flag); + +/* @param flag bit1= outdev rather than indev + @return <=0 = failure , 1= ok , 2= ok, is CD profile +*/ +int Xorriso_get_profile(struct XorrisO *xorriso, int *profile_number, + char profile_name[80], int flag); + +#ifdef NIX + +/* @param flag bit0= do not mark image as changed */ +int Xorriso_set_publisher(struct XorrisO *xorriso, char *name, int flag); + +/* @param flag bit0= do not mark image as changed */ +int Xorriso_set_application_id(struct XorrisO *xorriso, char *name, int flag); + +#endif /* NIX */ + +/* @param flag bit0= node_pt is a valid ISO object handle, ignore pathname +*/ +int Xorriso_iso_file_open(struct XorrisO *xorriso, char *pathname, + void *node_pt, void **stream, int flag); + +int Xorriso_iso_file_read(struct XorrisO *xorriso, void *stream, char *buf, + int count, int flag); + +int Xorriso_iso_file_close(struct XorrisO *xorriso, void **stream, int flag); + +/* @param bit0= copy link target properties rather than link properties +*/ +int Xorriso_copy_properties(struct XorrisO *xorriso, + char *disk_path, char *img_path, int flag); + +int Xorriso_cut_out(struct XorrisO *xorriso, char *disk_path, + off_t startbyte, off_t bytecount, char *iso_rr_path, int flag); + +int Xorriso_paste_in(struct XorrisO *xorriso, char *disk_path, + off_t startbyte, off_t bytecount, char *iso_rr_path, int flag); + +struct SplitparT; + +/* @param flag bit0= in_node is valid, do not resolve iso_adr +*/ +int Xorriso_identify_split(struct XorrisO *xorriso, char *iso_adr, + void *in_node, + struct SplitparT **parts, int *count, + struct stat *total_stbuf, int flag); + +/* @param flag bit0= node is valid, do not resolve path + bit1= insist in complete collection of part files +*/ +int Xorriso_is_split(struct XorrisO *xorriso, char *path, void *node, + int flag); + + +/* @param flag + >>> bit0= mkdir: graft in as empty directory, not as copy from iso + bit1= do not report copied files + bit2= -follow, -not_*: this is not a command parameter + bit3= use offset and cut_size for -paste_in + bit4= return 3 on rejection by exclusion or user + bit5= if directory then do not add sub tree + bit6= this is a copy action: do not fake times and ownership + @return <=0 = error , 1 = added leaf file object , 2 = added directory , + 3 = rejected +*/ +int Xorriso_restore(struct XorrisO *xorriso, + char *img_path, char *disk_path, + off_t offset, off_t cut_size, int flag); + + +/* @param flag bit0= in_node is valid, do not resolve img_path +*/ +int Xorriso_restore_is_identical(struct XorrisO *xorriso, void *in_node, + char *img_path, char *disk_path, + char type_text[5], int flag); + + +/* Return the official libburn address of an address string. This may fail + if the string does not constitute a valid drive address. + @param official_adr must offer SfileadrL bytes of reply buffer + @return 1 = success , 0 = failure , -1 = severe error +*/ +int Xorriso_libburn_adr(struct XorrisO *xorriso, char *address_string, + char official_adr[], int flag); + + +/* @param flag bit1= obtain info from outdev +*/ +int Xorriso_msinfo(struct XorrisO *xorriso, int *msc1, int *msc2, int flag); + +/* + @param flag bit0= obtain iso_lba from indev + bit1= head_buffer already contains a valid head + bit2= issue message about success + bit3= check whether source blocks are banned by in_sector_map +*/ +int Xorriso_update_iso_lba0(struct XorrisO *xorriso, int iso_lba, int isosize, + char *head_buffer, struct CheckmediajoB *job, + int flag); + +int Xorriso_get_local_charset(struct XorrisO *xorriso, char **name, int flag); + +int Xorriso_set_local_charset(struct XorrisO *xorriso, char *name, int flag); + + + +struct CheckmediajoB { + int use_dev; /* 0= use indev , 1= use outdev , 2= use sector map*/ + + int min_lba; /* if >=0 : begin checking at this address */ + int max_lba; /* if >=0 : read up to this address, else use mode */ + + int min_block_size; /* >>> not yet implemented: + granularity desired by user + */ + int mode; /* 0= track by track + 1= single sweep over libisoburn media capacity + >>> 2= single sweep over libburn media capacity + */ + time_t start_time; + int time_limit; /* Number of seconds after which to abort */ + + int item_limit; /* Maximum number of media check list items as result */ + + char abort_file_path[SfileadrL]; + + char data_to_path[SfileadrL]; + int data_to_fd; + off_t data_to_offset; /* usually 0 with image copy, negative with file copy */ + off_t data_to_limit; /* used with file copy */ + int patch_lba0; + int patch_lba0_msc1; + + char sector_map_path[SfileadrL]; + struct SectorbitmaP *sector_map; + int map_with_volid; /* 0=add quick toc to map file, + 1=read ISO heads for toc + */ + + int retry; /* -1= only try full read_chunk, 1=retry with 2k blocks + 0= retry with CD, full chunk else + */ + + int report_mode; /* 0= print MCL items + 1= print damaged files + */ + +}; + +int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist, + struct CheckmediajoB *job, int flag); + +int Xorriso_extract_cut(struct XorrisO *xorriso, + char *img_path, char *disk_path, + off_t img_offset, off_t bytes, int flag); + + +int Xorriso_relax_compliance(struct XorrisO *xorriso, char *mode, + int flag); + +/* @return 1=ok 2=ok, is default setting */ +int Xorriso_get_relax_text(struct XorrisO *xorriso, char mode[1024], + int flag); + + +/** + @param flag bit0= print mount command to result channel rather than + performing it +*/ +int Xorriso_mount(struct XorrisO *xorriso, char *dev, int adr_mode, + char *adr_value, char *cmd, int flag); + + + +int Xorriso_auto_driveadr(struct XorrisO *xorriso, char *adr, char *result, + int flag); + + +/* A pseudo file type for El-Torito bootsectors as in man 2 stat : + For now take the highest possible value. +*/ +#define Xorriso_IFBOOT S_IFMT + + +#endif /* Xorrisoburn_includeD */ +