Some svn admin magic

This commit is contained in:
Mario Danic 2008-03-11 19:34:19 +00:00
parent 1279cfc046
commit 451b7eb2aa
145 changed files with 68539 additions and 0 deletions

View File

@ -0,0 +1,3 @@
Thomas Schmitt
Vreixo Formoso Lopes

View File

@ -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

View File

@ -0,0 +1,23 @@
Mario Danic <mario.danic@gmail.com>,
Vreixo Formoso <metalpain2002@yahoo.es>
Thomas Schmitt <scdbackup@gmx.net>
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 as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
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

View File

@ -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.

View File

@ -0,0 +1,131 @@
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
xorriso_xorriso_CPPFLAGS = -Ilibisoburn
xorriso_xorriso_CFLAGS = -DXorriso_with_maiN -DXorriso_with_regeX $(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
## 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
# ts A80110 - A80210 : we need as minimal demo something better than test.c
# test/test
# test_test_CPPFLAGS = -Ilibisofs -Ilibburn -Ilibisoburn
# test_test_LDADD = $(libisoburn_libisoburn_la_OBJECTS) $(THREAD_LIBS) -lburn -lisofs
# test_test_SOURCES = test/test.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 $</* $(webhost):$(webpath)
all: doc
install-data-local:
if [ -f ./doc/doc.lock ]; then \
$(mkinstalldirs) $(docdir)/html; \
$(INSTALL_DATA) doc/html/* $(docdir)/html; \
fi
uninstall-local:
rm -rf $(docdir)
## ========================================================================= ##
# Indent source files
indent_files = \
$(libisoburn_libisoburn_la_SOURCES)
indent: $(indent_files)
indent -bad -bap -nbbb -nbbo -nbc -bli0 -br -bls \
-cdw -ce -cli0 -ncs -nbfda -i8 -l79 -lc79 \
-lp -saf -sai -nprs -npsl -saw -sob -ss -ut \
-sbi0 -nsc -ts8 -npcs -ncdb -fca \
$^
.PHONY: indent
## ========================================================================= ##
# Extra things
nodist_pkgconfig_DATA = \
libisoburn-1.pc
man_MANS = xorriso/xorriso.1
EXTRA_DIST = \
libisoburn-1.pc.in \
version.h.in \
README \
AUTHORS \
CONTRIBUTORS \
COPYRIGHT \
COPYING \
INSTALL \
xorriso/changelog.txt \
xorriso/README \
$(man_MANS)

View File

@ -0,0 +1,152 @@
------------------------------------------------------------------------------
libburnia-project.org
------------------------------------------------------------------------------
libisoburn. By Vreixo Formoso <metalpain2002@yahoo.es>
and Thomas Schmitt <scdbackup@gmx.net>
Integrated sub project of libburnia-project.org.
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 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 only supported on Linux with kernels >= 2.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.1.1 :
- libburn.so.4 , version libburn-0.4.2 or higher
- libisofs.so.6 , version libisofs-0.6.2 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.1.1.tar.gz, take it to a directory of your choice and do:
tar xzf libisoburn-0.1.1.tar.gz
cd libisoburn-0.1.1
Within that directory execute:
./configure --prefix=/usr
make
Then become superuser and execute
make install
which will make available libisoburn.so.1 .
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 includes 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 standlone tarball as first
preference for xorriso installation.
The installation described here produces a dynamically linked xorriso binary
as described in chapter "libisoburn" at the end of that text.
After installation documentation is available via
man xorriso
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 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 --
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 <mario.danic@gmail.com>,
Vreixo Formoso <metalpain2002@yahoo.es>
Thomas Schmitt <scdbackup@gmx.net>
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 <derek@signalmarketing.com> and
Ben Jansens <xor@orodu.net>
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens

View File

@ -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.

View File

@ -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])
])

View File

@ -0,0 +1,7 @@
#!/bin/sh -x
aclocal
libtoolize --copy --force
autoconf
automake --foreign --add-missing --copy --include-deps

View File

@ -0,0 +1,125 @@
AC_INIT([libisoburn], [0.1.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 The API version codes are now 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=1
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 A80215
dnl This is the developmen t version after stable release libisoburn.so.1.1.0
dnl LT_CURRENT++, LT_AGE++ has not happened yet.
dnl
dnl SONAME = 2 - 1 = 1 . Library name = libburn.so.1.1.1
LT_RELEASE=$ISOBURN_MAJOR_VERSION.$ISOBURN_MINOR_VERSION
LT_CURRENT=2
LT_AGE=1
LT_REVISION=1
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)
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= )
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.4.2
LIBISOFS_REQUIRED=0.6.2
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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -0,0 +1,892 @@
/*
cc -g -c \
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE \
burn_wrap.c
*/
/* libburn wrappers for libisoburn
Copyright 2007 Thomas Schmitt, <scdbackup@gmx.net>
*/
/* <<< 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 <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifndef Xorriso_standalonE
#include <libburn/libburn.h>
#include <libisofs/libisofs.h>
#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 */
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, &micro);
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, &micro);
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, &micro);
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);
}
/** Examine the media and sets appropriate emulation if needed.
@param flag bit0= pretent blank on overwriteable media
*/
static int isoburn_welcome_media(struct isoburn **o, struct burn_drive *d,
int flag)
{
int ret, lba, nwa;
struct burn_multi_caps *caps= NULL;
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;
ret= isoburn_new(o, 0);
if(ret<=0)
goto ex;
(*o)->drive= d;
#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;
if(flag&1) {
(*o)->nwa= 0;
(*o)->fabricated_disc_status= BURN_DISC_BLANK;
} else {
ret= isoburn_start_emulation(*o, 0);
if(ret<=0) {
(*o)->emulation_mode= -1;
goto ex;
}
}
} else {
/* >>> recognize unsuitable media (but allow read-only media) */;
#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
*/
int isoburn_drive_aquire(struct burn_drive_info *drive_infos[],
char *adr, int flag)
{
int ret, conv_ret, drive_grabbed= 0;
char libburn_drive_adr[BURN_DRIVE_ADR_LEN];
struct isoburn *o= NULL;
char msg[BURN_MSGS_MESSAGE_LEN+4096];
conv_ret= burn_drive_convert_fs_adr(adr, libburn_drive_adr);
if(conv_ret<=0) {
sprintf(msg, "Unsuitable drive address: '%s'\n",adr);
msg[BURN_MSGS_MESSAGE_LEN-1]= 0;
burn_msgs_submit(0x00060000, msg, 0, "FAILURE", NULL);
ret= 0; goto ex;
}
ret= burn_drive_scan_and_grab(drive_infos, libburn_drive_adr, flag&1);
if(ret<=0)
goto ex;
drive_grabbed= 1;
ret= isoburn_welcome_media(&o, (*drive_infos)[0].drive, !!(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) {
burn_msgs_submit(0x00060000,
"Unsuitable drive and media state", 0, "FAILURE", NULL);
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>0)
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;
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) {
ret= isoburn_invalidate_iso(o, 0);
if(ret<=0)
burn_drive_cancel(drive);
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;
off_t avail;
ret= isoburn_find_emulator(&o, d, 0);
if(ret>0 && o!=NULL)
if(o->emulation_mode!=0)
burn_write_opts_set_start_byte(opts, ((off_t) o->nwa) * (off_t) 2048);
avail= burn_disc_available_space(d, opts);
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) {
burn_msgs_submit(0x00060000,
"Media contains no recognizable data", 0, "SORRY",NULL);
return(0);
}
ret= isoburn_find_emulator(&o, d, 0);
if(ret<0)
return(0);
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));
}
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) {
burn_write_opts_set_start_byte(opts, ((off_t) o->nwa) * (off_t) 2048);
nwa= o->nwa;
}
}
}
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);
burn_msgs_submit(0x00060000, msg, 0, "FAILURE", NULL);
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);
fprintf(stderr, "isoburn_EXPERIMENTAL: write_type = %s\n",
(write_type == BURN_WRITE_SAO ? "SAO" :
(write_type == BURN_WRITE_TAO ? "TAO" : reasons)));
*/
#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) {
burn_msgs_submit(0x00060000,
"Cannot set start byte address with this type of media",
0, "FAILURE", NULL);
{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 alignment, round up to full 16 sector addresses */
if((o->nwa%16) && ((16*2048) % caps->start_alignment)==0 )
o->nwa+= 16 - (o->nwa%16);
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;
#ifdef Libisoburn_no_fifO
size_t hsize= 0, hfree_bytes= 0;
#endif
ret= isoburn_find_emulator(&o, d, 0);
if(ret<0)
return(-1);
#ifdef Libisoburn_no_fifO
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";
#else
if(o==NULL)
return(0);
if(o->fifo==NULL)
return(0);
ret= burn_fifo_inquire_status(o->fifo, size, free_bytes, status_text);
#endif /* ! Libisoburn_no_fifO */
return(ret);
}
#define Libisoburn_on_libisofs_after_0_6_2 yes
/* >>> todo: throw out the copies of libdax_msgs entrails */
/* <<< to be replaced by libburn-0.4.3 API call burn_sev_to_text().
This is a copy of libdax_msgs__sev_to_text() which is not exposed
by the API of of libburn-0.4.2 . As soon as xorriso gets based on
libburn-0.4.4 this redundancy is to be removed.
It is safe, nevertheless, because the severity codes are eternal.
*/
#define LIBDAX_MSGS_SEV_ALL 0x00000000
#define LIBDAX_MSGS_SEV_ERRFILE 0x08000000
#define LIBDAX_MSGS_SEV_DEBUG 0x10000000
#define LIBDAX_MSGS_SEV_UPDATE 0x20000000
#define LIBDAX_MSGS_SEV_NOTE 0x30000000
#define LIBDAX_MSGS_SEV_HINT 0x40000000
#define LIBDAX_MSGS_SEV_WARNING 0x50000000
#define LIBDAX_MSGS_SEV_SORRY 0x60000000
#define LIBDAX_MSGS_SEV_MISHAP 0x64000000
#define LIBDAX_MSGS_SEV_FAILURE 0x68000000
#define LIBDAX_MSGS_SEV_FATAL 0x70000000
#define LIBDAX_MSGS_SEV_ABORT 0x71000000
#define LIBDAX_MSGS_SEV_NEVER 0x7fffffff
/* @param flag bit0= -reserved-
bit1= this is a libburn severity
*/
int isoburn__sev_to_text(int severity, char **severity_name,
int flag)
{
#ifdef Libisoburn_on_libisofs_after_0_6_2
int ret;
#else
#ifdef Libisoburn_on__libburn_after_0_4_2
int ret;
#endif
#endif
#ifdef Libisoburn_on_libisofs_after_0_6_2
ret= iso_sev_to_text(severity, severity_name);
if(ret>0)
return(ret);
#endif /* Libisoburn_on_libisofs_after_0_6_2 */
#ifdef Libisoburn_on__libburn_after_0_4_2
ret= burn_sev_to_text(severity, severity_name, 0);
if(ret>0)
return(ret);
#endif
if(flag&1) {
*severity_name= "NEVER\nABORT\nFATAL\nFAILURE\nSORRY\nWARNING\nHINT\nNOTE\nUPDATE\nDEBUG\nERRFILE\nALL";
return(1);
}
*severity_name= "";
if(severity>=LIBDAX_MSGS_SEV_NEVER)
*severity_name= "NEVER";
else if(severity>=LIBDAX_MSGS_SEV_ABORT)
*severity_name= "ABORT";
else if(severity>=LIBDAX_MSGS_SEV_FATAL)
*severity_name= "FATAL";
else if(severity>=LIBDAX_MSGS_SEV_FAILURE)
*severity_name= "FAILURE";
else if(severity>=LIBDAX_MSGS_SEV_MISHAP)
*severity_name= "MISHAP";
else if(severity>=LIBDAX_MSGS_SEV_SORRY)
*severity_name= "SORRY";
else if(severity>=LIBDAX_MSGS_SEV_WARNING)
*severity_name= "WARNING";
else if(severity>=LIBDAX_MSGS_SEV_HINT)
*severity_name= "HINT";
else if(severity>=LIBDAX_MSGS_SEV_NOTE)
*severity_name= "NOTE";
else if(severity>=LIBDAX_MSGS_SEV_UPDATE)
*severity_name= "UPDATE";
else if(severity>=LIBDAX_MSGS_SEV_DEBUG)
*severity_name= "DEBUG";
else if(severity>=LIBDAX_MSGS_SEV_ERRFILE)
*severity_name= "ERRFILE";
else if(severity>=LIBDAX_MSGS_SEV_ALL)
*severity_name= "ALL";
else {
*severity_name= "";
return(0);
}
return(1);
}
int isoburn__text_to_sev(char *severity_name, int *severity_number, int flag)
{
int ret= 1;
#ifdef Libisoburn_on_libisofs_after_0_6_2
ret= iso_text_to_sev(severity_name, severity_number);
if(ret>0)
return(ret);
#endif /* Libisoburn_on_libisofs_after_0_6_2 */
#ifndef Libisoburn_on__libburn_after_0_4_2
if(severity_name[0]==0)
*severity_number= 0;
else if(strcmp(severity_name, "MISHAP")==0)
*severity_number= LIBDAX_MSGS_SEV_MISHAP;
else if(strcmp(severity_name, "ERRFILE")==0)
*severity_number= LIBDAX_MSGS_SEV_ERRFILE;
else
#endif /* ! Libisoburn_on__libburn_after_0_4_2 */
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;
#ifdef Libisoburn_on_libisofs_after_0_6_2
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);
#else
burn_text_to_sev(min_severity, &min_sev, 0);
/* <<< Tunnel MISHAP through libburn which knows no MISHAP
with libburn-0.4.4 this is not necessary */
if(iso_sev==LIBDAX_MSGS_SEV_MISHAP) {
iso_sev= LIBDAX_MSGS_SEV_SORRY;
error_code= 0x0005ff73;
} else if(iso_sev==LIBDAX_MSGS_SEV_ERRFILE) { /* same with ERRFILE */
iso_sev= LIBDAX_MSGS_SEV_DEBUG;
error_code= 0x00051001;
}
if(min_sev < iso_sev)
isoburn__sev_to_text(iso_sev, &sev_text_pt, 0);
ret= burn_msgs_submit(error_code, msg_text_pt, os_errno, sev_text_pt, NULL);
#endif /* ! Libisoburn_on_libisofs_after_0_6_2 */
return(ret);
}

View File

@ -0,0 +1,190 @@
/*
data source for libisoburn.
Copyright 2007 Vreixo Formoso Lopes <metalpain2002@yahoo.es>
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifndef Xorriso_standalonE
#include <libburn/libburn.h>
#include <libisofs/libisofs.h>
#else /* ! Xorriso_standalonE */
#include "../libisofs/libisofs.h"
#include "../libburn/libburn.h"
#endif /* Xorriso_standalonE */
#include "isoburn.h"
/* Cached reading of image tree data */
/* Current implementation : single tile 128 kB */
/* powers of 2 only ! */
#define Libisoburn_cache_blockS 64
struct isoburn_cached_drive {
struct burn_drive *drive;
char cache_data[Libisoburn_cache_blockS * 2048];
uint32_t cache_lba;
uint32_t last_error_lba;
uint32_t last_aligned_error_lba;
int cache_hits;
};
/* Debugging only: This reports cache loads on stderr.
#define Libisoburn_read_cache_reporT 1
*/
#define Libisoburn_use_read_cachE
#ifdef Libisoburn_use_read_cachE
int
ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
{
int ret;
struct burn_drive *d;
off_t count;
uint32_t aligned_lba;
char msg[80];
struct isoburn_cached_drive *icd;
if(src == NULL || buffer == NULL)
return -1;
icd = (struct isoburn_cached_drive *) src->data;
d = (struct burn_drive*) icd->drive;
aligned_lba= lba & ~(Libisoburn_cache_blockS - 1);
if(aligned_lba == icd->cache_lba && icd->cache_lba != 0xffffffff) {
(icd->cache_hits)++;
memcpy(buffer, icd->cache_data + (lba - aligned_lba) * 2048, 2048);
count= 2048;
return 1;
}
icd->cache_lba= 0xffffffff; /* invalidate cache */
if(icd->last_aligned_error_lba == aligned_lba) {
ret = 0;
} else {
ret = burn_read_data(d, (off_t) aligned_lba * (off_t) 2048,
(char *) icd->cache_data,
Libisoburn_cache_blockS * 2048, &count, 0);
}
if (ret <= 0 ) {
icd->last_aligned_error_lba = aligned_lba;
/* Read-ahead failure ? Try to read 2048 directly. */
if(icd->last_error_lba == lba)
ret = 0;
else
ret = burn_read_data(d, (off_t) lba * (off_t) 2048, (char *) buffer,
2048, &count, 0);
if (ret > 0)
return 1;
icd->last_error_lba = lba;
sprintf(msg, "ds_read_block(%lu) returns -1", (unsigned long) lba);
burn_msgs_submit(0x00060000, msg, 0, "DEBUG", NULL);
return -1;
}
#ifdef Libisoburn_read_cache_reporT
fprintf(stderr, "After %3d hits, new load from %8x , count= %d\n",
icd->cache_hits, aligned_lba, (int) count);
#endif
icd->cache_lba= aligned_lba;
icd->cache_hits= 1;
memcpy(buffer, icd->cache_data + (lba - aligned_lba) * 2048, 2048);
count= 2048;
return 1;
}
#else /* Libisoburn_use_read_cachE */
static int
ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
{
int ret;
struct burn_drive *d;
off_t count;
if(src == NULL || buffer == NULL)
return -1;
d = (struct burn_drive*) ((struct isoburn_cached_drive *) src->data)->drive;
ret = burn_read_data(d, (off_t) lba * (off_t) 2048, (char *) buffer,
2048, &count, 0);
if (ret <= 0 )
return -1;
return 1;
}
#endif /* ! Libisoburn_use_read_cachE */
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;
}
IsoDataSource *
isoburn_data_source_new(struct burn_drive *d)
{
IsoDataSource *ret;
struct isoburn_cached_drive *icd= NULL;
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->cache_lba = 0xffffffff;
icd->cache_hits = 0;
icd->last_error_lba = 0xffffffff;
icd->last_aligned_error_lba = 0xffffffff;
return ret;
}

View File

@ -0,0 +1,839 @@
/*
cc -g -c isoburn.c
*/
/*
Class core of libisoburn.
Copyright 2007 Vreixo Formoso Lopes <metalpain2002@yahoo.es>
and Thomas Schmitt <scdbackup@gmx.net>
*/
/* ( derived from stub generated by CgeN on Sat, 01 Sep 2007 12:04:36 GMT ) */
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#ifndef Xorriso_standalonE
#include <libburn/libburn.h>
#include <libisofs/libisofs.h>
#else /* ! Xorriso_standalonE */
#include "../libisofs/libisofs.h"
#include "../libburn/libburn.h"
#endif /* Xorriso_standalonE */
#include "libisoburn.h"
#include "isoburn.h"
/* No more: version numbers out of configure.ac
major.minor.micro now comes from libisoburn.h
#include "../version.h"
*/
/* -------------------------- 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) {
burn_msgs_submit(0x00060000,
"Cannot allocate memory for isoburn control object",
0, "FATAL", NULL);
return(-1);
}
o->drive= NULL;
o->emulation_mode= 0;
o->min_start_byte= 0;
o->nwa= 0;
o->truncate= 0;
#ifdef Libisoburn_no_fifO
o->iso_source= NULL;
#else
o->fifo= NULL;
#endif
o->wrote_well= -1;
o->fabricated_disc_status= BURN_DISC_UNREADY;
for(i=0;i<65536;i++)
o->target_iso_head[i]= 0;
o->image= NULL;
o->read_pacifier= NULL;
o->read_pacifier_handle= NULL;
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);
#ifdef Libisoburn_no_fifO
if(o->iso_source!=NULL)
burn_source_free(o->iso_source);
#else
if(o->fifo!=NULL)
burn_source_free(o->fifo);
#endif /* ! Libisoburn_no_fifO */
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;(i<abs_idx || (flag&1)) && *pt!=NULL;i++) {
if(idx>0)
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);
}
static
int isoburn_prepare_disc_aux(struct burn_drive *d, struct burn_disc **disc,
struct isoburn_imgen_opts *opts, int new_img)
{
struct burn_source *wsrc;
struct burn_session *session;
struct burn_track *track;
struct isoburn *o;
IsoWriteOpts *wopts= NULL;
enum burn_disc_status state;
int ret, fifo_chunks;
ret= isoburn_find_emulator(&o, d, 0);
if(ret<0 || o==NULL)
{ret= -1; goto ex;}
o->wrote_well= 0; /* early end will be registered as failure */
state = isoburn_disc_get_status(d);
if (state != BURN_DISC_BLANK && state != BURN_DISC_APPENDABLE
&& (state != BURN_DISC_FULL || ! new_img)) {
/* unsuitable status */
burn_msgs_submit(0x00060000, "Unsuitable media state", 0, "FAILURE", NULL);
{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_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);
#ifdef Libisoburn_no_fifO
iso_write_opts_set_fifo_size(wopts, fifo_chunks);
#endif /* Libisoburn_no_fifO */
if (new_img) {
iso_write_opts_set_ms_block(wopts, 0);
iso_write_opts_set_appendable(wopts, 0);
iso_write_opts_set_overwrite_buf(wopts, NULL);
} else {
int lba, nwa;
ret = isoburn_disc_track_lba_nwa(d, NULL, 0, &lba, &nwa);
if (ret != 1) {
burn_msgs_submit(0x00060000, "Cannot determine next writeable address", 0,
"FAILURE", NULL);
{ret= -3; goto ex;}
}
if (nwa == 0 && state == BURN_DISC_APPENDABLE) {
/* invalid nwa */
burn_msgs_submit(0x00060000, "Encountered 0 as next writeable address", 0,
"FAILURE", NULL);
{ret= -4; goto ex;}
}
iso_write_opts_set_ms_block(wopts, nwa);
iso_write_opts_set_appendable(wopts, 1);
iso_write_opts_set_overwrite_buf(wopts, o->target_iso_head);
}
ret = iso_image_create_burn_source(o->image, wopts, &wsrc);
if (ret < 0) {
isoburn_report_iso_error(ret, "Cannot create burn source", 0, "FAILURE", 0);
{ret= -1; goto ex;}
}
/* TODO check return values for failure. propertly clean-up on error */
#ifdef Libisoburn_no_fifO
o->iso_source= wsrc;
#else
o->fifo = burn_fifo_source_new(wsrc, 2048, fifo_chunks, 0);
burn_source_free(wsrc);
if (o->fifo == NULL) {
burn_msgs_submit(0x00060000, "Cannot attach fifo", 0, "FATAL", NULL);
{ret= -1; goto ex;}
}
#endif /* ! Libisoburn_no_fifO */
*disc = burn_disc_create();
session = burn_session_create();
burn_disc_add_session(*disc, session, BURN_POS_END);
track = burn_track_create();
#ifdef Libisoburn_no_fifO
burn_track_set_source(track, o->iso_source);
#else
burn_track_set_source(track, o->fifo);
#endif /* ! Libisoburn_no_fifO */
burn_session_add_track(session, track, BURN_POS_END);
/* give up local references */
burn_track_free(track);
burn_session_free(session);
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, 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;
struct isoburn *in_o, *out_o;
ret= isoburn_prepare_disc_aux(d, disc, opts, 1);
if (ret<=0)
return ret;
#ifdef Libisoburn_no_fifO
/* Hand over source reference for optional fifo status inquiry */
if(out_drive==NULL)
return 1;
ret= isoburn_find_emulator(&out_o, out_drive, 0);
if(ret<0 || out_o==NULL)
return 1;
ret= isoburn_find_emulator(&in_o, d, 0);
if(ret<0 || in_o==NULL)
return 1; /* then without fifo status inquiry */
if(out_o->iso_source!=NULL)
burn_source_free(out_o->iso_source);
out_o->iso_source= in_o->iso_source;
in_o->iso_source= NULL;
#endif /* Libisoburn_no_fifO */
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) {
burn_msgs_submit(0x00060000, "Cannot allocate memory for read options",
0, "FATAL", NULL);
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) {
burn_msgs_submit(0x00060000,
"Cannot allocate memory for image generation options",
0, "FATAL", NULL);
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->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= 0;
o->fifo_size= 4*1024*1024;
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);
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);
}

View File

@ -0,0 +1,325 @@
/*
Class struct of libisoburn.
Copyright 2007 Vreixo Formoso Lopes <metalpain2002@yahoo.es>
and Thomas Schmitt <scdbackup@gmx.net>
*/
#ifndef Isoburn_includeD
#define Isoburn_includeD
/* <<< transition macro */
#define Libisoburn_no_fifO 1
/* for uint8_t */
#include <stdint.h>
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;
/* 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;
#ifndef Libisoburn_no_fifO
/* The fifo which is installed between track and libisofs burn_source
*/
struct burn_source *fifo;
#endif /* ! Libisoburn_no_fifO */
/* 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[65536];
/* Libisofs image context */
IsoImage *image;
#ifdef Libisoburn_no_fifO
/* The burn source which transfers data from libisofs to libburn.
It has its own fifo.
*/
struct burn_source *iso_source;
#endif /* Libisoburn_no_fifO */
/* For iso_tree_set_report_callback() */
int (*read_pacifier)(IsoImage*, IsoFileSource*);
/* For iso_image_attach_data() */
void *read_pacifier_handle;
};
/* 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);
/** 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);
/** 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);
/**
* 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;
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;
};
#endif /* Isoburn_includeD */

View File

@ -0,0 +1,398 @@
/*
cc -g -c isofs_wrap.c
*/
/*
libisofs related functions of libisoburn.
Copyright 2007 Vreixo Formoso Lopes <metalpain2002@yahoo.es>
Thomas Schmitt <scdbackup@gmx.net>
*/
#include <stdlib.h>
#include <string.h>
#ifndef Xorriso_standalonE
#include <libburn/libburn.h>
#include <libisofs/libisofs.h>
#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; i<bytes; i++) {
ret += ((uint32_t) buf[i]) << (i*8);
}
return ret;
}
/* API function. See libisoburn.h
*/
IsoImage *isoburn_get_attached_image(struct burn_drive *d)
{
int ret;
struct isoburn *o= NULL;
ret = isoburn_find_emulator(&o, d, 0);
if (ret < 0)
return NULL;
if (o == NULL) {
return NULL;
}
iso_image_ref(o->image);
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;
IsoReadOpts *ropts= NULL;
IsoReadImageFeatures *features= NULL;
uint32_t ms_block;
enum burn_disc_status status= BURN_DISC_BLANK;
IsoDataSource *ds= NULL;
struct isoburn *o= NULL;
if(read_opts==NULL) {
burn_msgs_submit(0x00060000,
"Program error: isoburn_read_image: read_opts==NULL",
0, "FATAL", NULL);
return(-1);
}
if(d != NULL) {
ret = isoburn_find_emulator(&o, d, 0);
if (ret < 0 || o == NULL)
return 0;
status = isoburn_disc_get_status(d);
}
if (d == NULL || status == BURN_DISC_BLANK || read_opts->pretend_blank) {
/*
* Blank disc, we create a new image without files.
*/
if (d == NULL) {
/* New empty image without relation to a drive */
if (image==NULL) {
burn_msgs_submit(0x00060000,
"Program error: isoburn_read_image: image==NULL",
0, "FATAL", NULL);
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) {
burn_msgs_submit(0x00060000,
"Program error: isoburn_read_image: incorrect disc status",
0, "FATAL", NULL);
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;
/* 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);
ds = isoburn_data_source_new(d);
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);
iso_data_source_unref(ds);
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);
#ifdef NIX
read_opts->hasRR = features->hasRR;
read_opts->hasJoliet = features->hasJoliet;
read_opts->hasIso1999 = features->hasIso1999;
read_opts->hasElTorito = features->hasElTorito;
read_opts->size = features->size;
#endif
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;
if (image == NULL) {
burn_msgs_submit(0x00060000,
"Program error: isoburn_attach_image: image==NULL",
0, "FATAL", NULL);
return -1;
}
ret = isoburn_find_emulator(&o, d, 0);
if (ret < 0 || o == NULL)
return 0;
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_disc_status != BURN_DISC_APPENDABLE)
return 1;
ret = burn_random_access_write(drive, 0, (char*)o->target_iso_head,
32*2048, 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) {
burn_msgs_submit(0x00060000,
"Program error: isoburn_start_emulation: o==NULL",
0, "FATAL", NULL);
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,
sizeof(o->target_iso_head), &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 = sizeof(o->target_iso_head);
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, (off_t) 0, 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);
}

File diff suppressed because it is too large Load Diff

View File

@ -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, <scdbackup@gmx.net>
Provided under GPL version 2.
cc -g -o compare_file compare_file.c
*/
#include <ctype.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
/* @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<r1) {
if(r2==EOF)
r2= 0;
if(s2.st_size > 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; i<r1; i++) {
if(buf1[i]!=buf2[i]) {
if(first_diff<0)
first_diff= i;
diffcount++;
}
}
}
if(diffcount>0 || 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<argc; i++) {
if(strcmp(argv[i], "-no_ctime")==0)
with_ctime= 0;
else {
fprintf(stderr, "%s : Option not recognized: '%s'\n", argv[0], argv[i]);
exit(1);
}
}
if(strncmp(argv[1], argv[2], strlen(argv[2]))!=0) {
fprintf(stderr, "%s: path '%s' does not match prefix1 '%s'\n",
argv[0], argv[1], argv[2]);
exit(2);
}
strcpy(adr1, argv[1]);
strcpy(adrc, argv[1]+strlen(argv[2]));
sprintf(adr2, "%s%s%s",
argv[3], (adrc[0]=='/' || adrc[0]==0 ? "" : "/"), adrc);
ret= Compare_2_files(adr1, adr2, adrc, (with_ctime<<1));
exit(ret<=0);
}

View File

@ -0,0 +1,312 @@
/*
Little test program for libisoburn.
It grows an iso filesystem on a disc.
Copyright 2007 Vreixo Formoso Lopes <metalpain2002@yahoo.es>
and Thomas Schmitt <scdbackup@gmx.net>
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <err.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <libisofs/libisofs.h>
#include <libburn/libburn.h>
#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);
}

View File

@ -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@
*/

View File

@ -0,0 +1,201 @@
------------------------------------------------------------------------------
libburnia-project.org scdbackup.sourceforge.net/xorriso_eng.html
------------------------------------------------------------------------------
xorriso. By Thomas Schmitt <scdbackup@gmx.net>
Integrated sub project of libburnia-project.org but also published via:
http://scdbackup.sourceforge.net/xorriso_eng.html
http://scdbackup.sourceforge.net/xorriso-0.1.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.
Currently it is only supported on Linux with kernels >= 2.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.1.1.tar.gz, take it to a directory of your choice and do:
tar xzf xorriso-0.1.1.tar.gz
cd xorriso-0.1.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,
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.
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. The addresses of the disk files have to be preceded by "stdio:".
Like:
xorriso -dev stdio:/tmp/pseudo_drive ...more arguments...
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 --
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
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.1.1 :
- libburn.so.4 , version libburn-0.4.2 or higher
- libisofs.so.6 , version libisofs-0.6.2 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 <mario.danic@gmail.com>,
Vreixo Formoso <metalpain2002@yahoo.es>
Thomas Schmitt <scdbackup@gmx.net>
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 <derek@signalmarketing.com> and
Ben Jansens <xor@orodu.net>
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,155 @@
#!/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
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" = "-help" -o "$i" = "--help" -o "$i" = "-h"
then
echo \
"$xorr/compile_xorriso.sh : to be executed above top level directories"
echo "Options:"
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
timestamp="$(date -u '+%Y.%m.%d.%H%M%S')"
echo "Version timestamp : $(sed -e 's/#define Xorriso_timestamP "//' -e 's/"$//' "$xorr"/xorriso_timestamp.h)"
echo "Build timestamp : $timestamp"
echo "compiling program $xorr/xorriso.c $static_opts $debug_opts $def_opts"
cc -I. -DXorriso_with_maiN -DXorriso_with_regeX -DXorriso_with_readlinE \
$warn_opts \
$static_opts \
$debug_opts \
$def_opts \
$largefile_opts \
\
-DXorriso_build_timestamP='"'"$timestamp"'"' \
\
-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 \
\
-lreadline \
\
-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.'

View File

@ -0,0 +1,114 @@
AC_INIT([xorriso], [0.1.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=4
BURN_MICRO_VERSION=3
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=3
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 <time.h>])
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 <time.h>])
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 <unistd.h>])
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
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= )
AC_SUBST(READLINE_DEF)
AC_CONFIG_FILES([
Makefile
version.h
xorriso.pc
])
AC_OUTPUT

View File

@ -0,0 +1,107 @@
#!/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/<meta name="generator" content="groff -Thtml, see www.gnu.org">/<meta name="generator" content="groff -Thtml, via man -H, via xorriso\/convert_man_to_html.sh">/' \
-e 's/<meta name="Content-Style" content="text\/css">/<meta name="Content-Style" content="text\/css"><META NAME="description" CONTENT="man page of xorriso"><META NAME="keywords" CONTENT="man xorriso, manual, xorriso, CD, CD-RW, CD-R, burning, cdrecord, compatible"><META NAME="robots" CONTENT="follow">/' \
-e 's/<title>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>/\&nbsp;<BR><b>Overview of features:<\/b>/' \
-e 's/<b>General information paragraphs:<\/b>/\&nbsp;<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>/\&nbsp;<BR><b>Session model:<\/b>/' \
-e 's/<b>Media types and states:<\/b>/\&nbsp;<BR><b>Media types and states:<\/b>/' \
-e 's/<b>Creating, Growing, Modifying:<\/b>/\&nbsp;<BR><b>Creating, Growing, Modifying:<\/b>/' \
-e 's/<b>Libburn drives:<\/b>/\&nbsp;<BR><b>Libburn drives:<\/b>/' \
-e 's/^-dev /\&nbsp;\&nbsp;-dev /' \
-e 's/^-devices /\&nbsp;\&nbsp;-devices /' \
-e 's/<b>Rock Ridge, POSIX, X\/Open:<\/b>/\&nbsp;<BR><b>Rock Ridge, POSIX, X\/Open:<\/b>/' \
-e 's/<b>Command processing:<\/b>/\&nbsp;<BR><b>Command processing:<\/b>/' \
-e 's/<b>Dialog, Readline, Result pager:<\/b>/\&nbsp;<BR><b>Dialog, Readline, Result pager:<\/b>/' \
-e 's/<b>Aquiring source and target drive:<\/b>/\&nbsp;<BR><b>Aquiring source and target drive:<\/b><BR>\&nbsp;<BR>/' \
-e 's/<b>Data manipulations:<\/b>/\&nbsp;<BR><b>Data manipulations:<\/b><BR>\&nbsp;<BR>/' \
-e 's/^<p><b>&minus;iso_rr_pattern/<p>\&nbsp;<BR><b>\&minus;iso_rr_pattern/' \
-e 's/EXAMPLES):<br>/<A HREF="#EXAMPLES">EXAMPLES<\/A>):<br>/' \
-e 's/<b>Writing the result:<\/b>/\&nbsp;<BR><b>Writing the result:<\/b><BR>/' \
-e 's/^-find \/ /\&nbsp;\&nbsp;-find \/ /' \
-e 's/<b>Settings for data insertion:<\/b>/\&nbsp;<BR><b>Settings for data insertion:<\/b><BR>\&nbsp;<BR>/' \
-e 's/^$<\/b> ln -s/\&nbsp;\&nbsp;$<\/b> ln -s/' \
-e 's/<b>Settings for result writing:<\/b>/\&nbsp;<BR><b>Settings for result writing:<\/b><BR>\&nbsp;<BR>/' \
-e 's/^706k = 706kB/\&nbsp;\&nbsp;706k = 706kB/' \
-e 's/^5540k = 5540kB/\&nbsp;\&nbsp;5540k = 5540kB/' \
-e 's/<b>Exception processing:<\/b>/\&nbsp;<BR><b>Exception processing:<\/b><BR>\&nbsp;<BR>/' \
-e 's/<b>Dialog mode control:<\/b>/\&nbsp;<BR><b>Dialog mode control:<\/b><BR>\&nbsp;<BR>/' \
-e 's/<b>Drive and media related inquiry actions:<\/b>/\&nbsp;<BR><b>Drive and media related inquiry actions:<\/b><BR>\&nbsp;<BR>/' \
-e 's/<b>Navigation in ISO image/\&nbsp;<BR><b>Navigation in ISO image/' \
-e 's/^filesystem:<\/b>/filesystem:<\/b><BR>\&nbsp;<BR>/' \
-e 's/<b>Scripting, dialog and/\&nbsp;<BR><b>Scripting, dialog and/' \
-e 's/^features:<\/b>/features:<\/b><BR>\&nbsp;<BR>/' \
-e 's/<b>Support for frontend/\&nbsp;<BR><b>Support for frontend/' \
-e 's/^listening at stdout:<\/b>/listening at stdout:<\/b><BR>\&nbsp;<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 \\ \&rsquo;\/pictures\/\*private\*\&rsquo; \\/\/sounds\/indecent \&rsquo;\/pictures\/*private*\&rsquo; /' \
-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

View File

@ -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

View File

@ -0,0 +1,235 @@
#!/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.1.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
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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,452 @@
/* 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.
*/
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);
/** 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);
/* ---------------------------- 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 -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 -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);
/* >>> not yet implemented
/ * Option -cut_out * /
int Xorriso_option_cut_out(struct XorrisO *xorriso, char *disk_path,
off_t startbyte, off_t bytecount, 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 -iso_rr_pattern "on"|"ls"|"off" */
int Xorriso_option_iso_rr_pattern(struct XorrisO *xorriso, char *mode,
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 -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 -joliet "on"|"off" */
int Xorriso_option_joliet(struct XorrisO *xorriso, char *mode, 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 -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 -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 -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 -overwrite "on"|"nondir"|"off" */
int Xorriso_option_overwrite(struct XorrisO *xorriso, char *mode, 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 -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 -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 -reassure "on"|"tree"|"off" */
int Xorriso_option_reassure(struct XorrisO *xorriso, char *mode, 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 */
/* @return <=0 error , 1 success, 2 revoked by -reassure
*/
int Xorriso_option_rollback(struct XorrisO *xorriso, int flag);
/* Option -speed */
int Xorriso_option_speed(struct XorrisO *xorriso, char *speed, 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 -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 */

View File

@ -0,0 +1,431 @@
<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, recording, burning, CD-R, CD-RW, DVD-R, DVD-RW, DVD+RW, DVD+R, DVD+R/DL, scdbackup">
<META NAME="robots" CONTENT="follow">
<TITLE>xorriso homepage english</TITLE>
</HEAD>
<BODY BGCOLOR="#F5DEB3" TEXT=#000000 LINK=#0000A0 VLINK=#800000>
<FONT SIZE=+1>
<CENTER>
<P><H2> Homepage of </H2>
<H1> xorriso </H1>
<H2>ISO 9660 Rock Ridge Filesystem Manipulator for Linux</H2>
</CENTER>
<P>
<H2>Purpose:</H2>
xorriso 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.
</P>
<P>
<HR>
<A HREF="#download">Direct hop to download links -></A>
<P>
<H2>Hardware requirements:</H2>
A CD/DVD recorder suitable for
<A HREF="http://libburnia-project.org">http://libburnia-project.org</A> <BR>
(SCSI , ATA , USB , or SATA writers compliant to standard MMC-3 for CD
and to MMC-5 for DVD).
<BR>
</P>
<P>
<H2>Software requirements :</H2>
<DL>
<DT>Linux with kernel 2.4 or higher (and libc, of course) :</DT>
<DD>With kernel 2.4 an ATA drive has to be under ide-scsi emulation.</DD>
<DD>With kernel 2.6 the drive should not be under ide-scsi.</DD>
<DT>libpthread</DT>
<DD>is supposed to be a standard system component.</DD>
<DT>libreadline and libreadline-dev</DT>
<DD>are optional and eventually make dialog more convenient.</DD>
</DL>
</P>
<P>
<H2>
GPL software included:<BR>
</H2>
<DL>
<DT>libburn-0.4.3</DT>
<DD>reads and writes data from and to CD and DVD.</DD>
<DD>(founded by Derek Foreman and Ben Jansens,
furthered by team of libburnia-project.org)</DD>
<DT>libisofs-0.6.2</DT>
<DD>operates ISO 9660 images.</DD>
<DD>(By Vreixo Formoso and Mario Danic from team of libburnia-project.org)</DD>
<DT>libisoburn-0.1.0</DT>
<DD>coordinates libburn and libisofs, emulates multi-session where needed.</DD>
<DD>(By Vreixo Formoso and Thomas Schmitt
from team of libburnia-project.org)</DD>
</DL>
<DD>The source code of this software is independent of
cdrecord and mkisofs.</A>
</DD>
</P>
<P>
This program system has been tested on Intel/AMD Linux systems only.<BR>
For ports to other usable systems <A HREF="#contact">contact us</A>.
</P>
<HR>
<P>
<H2>Special features:</H2>
<UL>
<LI>
ISO 9660 formatter and burner for CD or DVD are fixely integrated.
</LI>
<LI>
Operates on an existing ISO image or creates a new one.
<LI>
</LI>
Copies files from filesystem into the ISO image.
<LI>
</LI>
Renames or deletes file objects in the ISO image.
<LI>
Changes file properties in the ISO image.
</LI>
<LI>
Can write result as completely new image to optical media or
filesystem objects.
</LI>
<LI>
Can write result as add-on session to appendable multi-session media,
to overwriteable media, to regular files, and to block devices.
</LI>
<LI>
Scans for optical drives, blanks re-useable optical media.
</LI>
<LI>
Suitable for: CD-R, CD-RW, DVD-R, DVD-RW, DVD+R, DVD+R/DL, DVD+RW, DVD-RAM.
</LI>
<LI>
Reads its instructions from command line arguments, dialog, and batch files.
</LI>
<LI>
Provides navigation commands for interactive ISO image manipulation.
</LI>
<LI>
Adjustable thresholds for abort, exit value, and problem reporting.
</LI>
</UL>
</P>
<P>
<H2>Command Examples:</H2>
<DL>
<DT>Get an overview of drives and their addresses</DT>
<DD>#<KBD>&nbsp;xorriso -devices</KBD></DD>
<DT>Being superuser avoids permission problems with /dev/srN resp. /dev/hdX .
</DT>
<DT>Ordinary users should then get granted rw access to the /dev files
as listed by option -devices.</DT>
<DT>&nbsp;</DT>
<DT>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.</DT>
<HR>
<DT>Get info about a particular drive and loaded media:</DT>
<DD>$<KBD>&nbsp;xorriso -indev /dev/sr0 -du / -- -toc 2>&amp;1 | less</KBD></DD>
<DT>Make re-usable media writable again, delete any ISO 9660 image:</DT>
<DD>$<KBD>&nbsp;xorriso -outdev /dev/sr0 -blank fast -eject all</KBD></DD>
<DT>
<HR>
</DT>
<DT>Write some directories into a new or existing ISO 9660 image:</DT>
<DD>$<KBD>&nbsp;xorriso -dev /dev/sr0 -add /home/me/sounds /home/me/pictures
</KBD></DD>
<DT>Check the result:</DT>
<DD>$<KBD>&nbsp;xorriso -indev /dev/sr0 -du / -- -toc 2>&amp;1 | less</KBD></DD>
<DT>
<HR>
</DT>
<DT>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.
</DT>
<DD>$<KBD>&nbsp;xorriso -outdev /dev/sr0 -blank fast -pathspecs on \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-add /sounds=/home/me/sounds \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/pictures=/home/me/pictures -- \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-rm_r /sounds/indecent '/pictures/*private*' -- \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-add /pictures/private/horses=/home/me/pictures/private/horses -- \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-chmod_r a+r,a-w / -- \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-find / -type d -exec chmod a+x -- \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-volid SOUNDS_PICS_2008_01_16 \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-commit_eject all</KBD></DD>
<DT>
<HR>
</DT>
<DT>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:</DT>
<DD>$<KBD>&nbsp;xorriso -dev /dev/sr0 -pathspecs on \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-rm_r /sounds -- \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-mv /pictures/private/horses /horse_show -- \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-add /sounds=/home/me/prepared_for_dvd/sounds_dummy \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /movies=/home/me/prepared_for_dvd/movies -- \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-chmod_r go-rwx / -- \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-volid SOUNDS_PICS_2008_01_17 \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-commit_eject all</KBD></DD>
<DT>
<HR>
</DT>
<DT>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.
<BR>
Important: -indev and -outdev have to be different drives.
</DT>
<DD>$<KBD>&nbsp;xorriso -indev /dev/dvd \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-alter_date a +0 / -- \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-outdev /dev/sr0 -blank fast \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-commit_eject all</KBD></DD>
<DT>
<HR>
</DT>
<DT>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.</DT>
<DD>$<KBD>&nbsp;xorriso -dialog on</KBD></DD>
<DD><KBD>enter option and arguments :</KBD></DD>
<DD><KBD><B>-dev /dev/sr0 -pathspecs on</B></KBD></DD>
<DD><KBD>enter option and arguments :</KBD></DD>
<DD><KBD><B>-add /sounds=/home/me/prepared_for_dvd/sounds_dummy /movies=/home/me/prepared_for_dvd/movies</B></KBD></DD>
<DD>Available navigation commands: -cd, -ls, -du, -find</DD>
<DD><KBD>enter option and arguments :</KBD></DD>
<DD><KBD><B>-commit</B></KBD></DD>
<DD>... perform further commands and finally do:</DD>
<DD><KBD>enter option and arguments :</KBD></DD>
<DD><KBD><B>-end</B></KBD></DD>
<DT>
<HR>
</DT>
<DT>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.</DT>
<DD>$<KBD>&nbsp;xorriso -outdev - ...other.options... | consumer</KBD></DD>
<DT>
<HR>
</DT>
<DT>Get overview of the options:</DT>
<DD>$<KBD>&nbsp;<A HREF="xorriso_help">xorriso -help</A></KBD></DD>
<DT>Read the detailed manual page:</DT>
<DD>$<KBD>&nbsp;<A HREF="man_1_xorriso.html">man xorriso</A></KBD></DD>
</DL>
Testers wanted who are willing to risk some double layer DVD media.
</P>
<HR>
<A NAME="download"></A>
<P>
<DL>
<DT>Download as source code (see README):</DT>
<DD><A HREF="xorriso-0.1.0.pl00.tar.gz">xorriso-0.1.0.pl00.tar.gz</A>
(900 KB).
</DD>
<!--
<DD>&nbsp;</DD>
<DT>Download as single x86 binaries (untar and move to /usr/bin/xorriso):</DT>
<DD><A HREF="xorriso_0.1.0.pl00-x86-suse9_0.tar.gz">
xorriso_0.1.0.pl00-x86-suse9_0.tar.gz</A>, ( KB),
<DL>
<DD>runs on SuSE 9.0 (2.4.21) , SuSE 10.2 (2.6.18.2) and others.</DD>
</DL>
<DD><A HREF="xorriso_0.1.0.pl00-x86-suse9_0-static.tar.gz">
xorriso_0.1.0.pl00-x86-suse9_0-static.tar.gz</A>, ( KB), -static compiled,
<DL>
<DD>runs on many other systems.</DD>
-->
</DL>
</DD>
</DL>
<DL><DT>Documentation:</DT>
<DD><A HREF="README_xorriso">README</A> about installation and drive setup</DD>
<DD><A HREF="xorriso_help">xorriso -help</A> gives an overview of options</DD>
<DD><A HREF="man_1_xorriso.html">man xorriso</A> is the manual page</DD>
</DL>
<A NAME="contact"></A>
<DL><DT>Contact:</DT>
<DD>Thomas Schmitt, <A HREF="mailto:scdbackup@gmx.net">scdbackup@gmx.net</A></DD>
<DD>libburn development mailing list,
<A HREF="mailto:libburn-hackers@pykix.org">libburn-hackers@pykix.org</A></DD>
</DL>
<DL><DT>License:</DT>
<DD><A HREF="COPYING_xorriso">GPL version 2</A>,
an <A HREF="http://www.opensource.org/">Open Source</A> approved license</DD>
<DD>&nbsp;</DD>
</DL>
</P>
<HR>
<P>
<DL>
<DT><H3>Development snapshot, version 0.1.1 :</H3></DT>
<DD>Bug fixes towards xorriso-0.1.0.pl00:
<UL>
<LI>-report_about HINT or higher did not report at all</LI>
<LI>speed=number without unit or media type letter was always CD speed</LI>
<LI>it was possible to write to appendable media which was not -indev</LI>
<LI>-follow param did not work for adding non-directory symbolic links</LI>
<!-- <LI>- none yet -</LI> -->
</UL>
</DD>
<DD>Enhancements towards stable version 0.1.0.pl00:
<UL>
<LI>Improved attribute transfer from disk for implicit target directories</LI>
<LI>New option -as "cdrecord" emulates a narrow set of cdrecord gestures</LI>
<LI>New option -as "mkisofs" emulates a narrow set of mkisofs gestures</LI>
<LI>New option -publisher</LI>
<LI>New option -errfile_log</LI>
<LI>Support for DVD+R/DL media</LI>
<!-- not complete yet
<LI>New options -compare , -compare_r and according -find -exec action</LI>
<LI>New options -update , -update_r and according -find -exec action</LI>
-->
<!-- <LI>- none yet -</LI> -->
</UL>
</DD>
<DD>&nbsp;</DD>
<DD><A HREF="README_xorriso_devel">README 0.1.1</A>
<DD><A HREF="xorriso_help_devel">xorriso_0.1.1 -help</A></DD>
<DD><A HREF="man_1_xorriso_devel.html">man xorriso (as of 0.1.1)</A></DD>
<DD>&nbsp;</DD>
<DT>The following download is intended for adventurous end users or
admins with full system souvereignty.</DT>
<DD>Source (./bootstrap is already applied, build tested,
installation see README)
</DD>
<DD>
<A HREF="xorriso-0.1.1.tar.gz">xorriso-0.1.1.tar.gz</A>
(900 KB).
</DD>
<DT>Maintainers of dynamically linked xorriso please use SVN of
<A HREF="http://libburnia-project.org"> libburnia-project.org</A>.
xorriso is part of libisoburn/trunk and will get built by its "make".</DT>
<DD>Download: <KBD><B>svn co http://svn.libburnia-project.org/libburn/trunk libburn</B>
</KBD></DD>
<DD>Install: <KBD><B>cd libburn ; ./bootstrap ; ./configure --prefix /usr ; make ; make install</B>
</KBD></DD>
<DD>Download: <KBD><B>bzr branch lp:libisofs</B></KBD></DD>
<DD>Install: <KBD><B>cd libisofs ; ./bootstrap ; ./configure --prefix /usr ; make ; make install</B>
</KBD></DD>
<DD>Download: <KBD><B>svn co http://svn.libburnia-project.org/libisoburn/trunk libisoburn</B>
</KBD></DD>
<DD>Install: <KBD><B>cd libisoburn ; ./bootstrap ; ./configure --prefix /usr ; make ; make install</B>
</KBD></DD>
<DD>Build of SVN versions needs <A HREF="http://sources.redhat.com/autobook/">
autotools</A> of at least version 1.7 installed.
But after the run of <KBD>./bootstrap</KBD>, only
vanilla tools like make and gcc are needed.</DD>
</DD>
<DD>&nbsp;</DD>
<!--
<DD>Binary (untar and move to /usr/bin/xorriso):</DD>
<DD><A HREF="xorriso_0.1.1-x86-suse9_0.tar.gz">
xorriso_0.1.1-x86-suse9_0.tar.gz</A>, ( KB).
</DD>
<DD><A HREF="xorriso_0.1.1-x86-suse9_0-static.tar.gz">
xorriso_0.1.1-x86-suse9_0-static.tar.gz</A>, ( KB)
</DD>
-->
</DL>
</P>
<HR>
<P>
Many thanks to Derek Foreman and Ben Jansens for starting libburn.
<BR>
Very special thanks to Andy Polyakov whose
<A HREF="http://fy.chalmers.se/~appro/linux/DVD+RW/tools">dvd+rw-tools</A>
provide the libburnia project with invaluable examples on how to deal
with DVD media and how to emulate multi-session on overwriteable media.
</P>
<HR>
<CENTER><FONT SIZE=+0>
<!-- <A NAME="bottom" HREF="main_ger.html#bottom">deutsch (german)</A>
<BR><BR>
-->
<BR><BR>
<FONT SIZE=+0>Enjoying free Open Source hosting by <A HREF="http://www.webframe.org">www.webframe.org</A><BR>
<A HREF="http://www.webframe.org">
<IMG SRC="msfree.gif" ALT="100 % Microsoft free" BORDER=0></A><BR>
and by <A HREF="http://sourceforge.net">sourceforge.net</A><BR>
<A href="http://sourceforge.net">
<IMG src="sflogo-88-1.png" BORDER="0" ALT="SourceForge Logo"></A>
<!-- on sourceforge use : <IMG src="http://sourceforge.net/sflogo.php?group_id=16010" width="88" height="31" border="0" alt="SourceForge Logo"></A> -->
</FONT></CENTER>
<HR>
<DL>
<DT>Links to my other published software projects :</DT>
<DD><A HREF=http://scdbackup.webframe.org/cdrskin_eng.html>
cdrskin, a cdrecord emulator</A></DD>
<DD><A HREF=http://scdbackup.webframe.org/main_eng.html>
scdbackup, multi volume CD backup</A></DD>
<DL><DD><A HREF=http://scdbackup.sourceforge.net/main_eng.html>
(a second source of above)</A></DD></DL>
<DD><A HREF=http://stic.sourceforge.net>Some Tools for Image Collectors</A></DD>
<DD><A HREF=http://scdbackup.webframe.org/pppoem>
pppoem, a DSL throughput monitor (mainly for Linux kernel 2.4)</A></DD>
</DL>
<BR><BR>
Legal statement: This website does not serve any commercial purpose.<BR>
</FONT>
</BODY>
</HTML>

View File

@ -0,0 +1,189 @@
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 -DXorriso_with_regeX $(READLINE_DEF)
xorriso_xorriso_LDADD = $(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 \
\
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 \
\
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
## ========================================================================= ##
# 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 \
$(man_MANS)

View File

@ -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:

View File

@ -0,0 +1,427 @@
/* 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 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.1.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 */
#ifndef Xorriso_build_timestamP
#define Xorriso_build_timestamP "-none-given-"
#endif
/* Because regex_t is mentioned in struct XorrisO */
#ifdef Xorriso_with_regeX
#include <regex.h>
#endif /* Xorriso_with_regeX */
#define Smem_malloC malloc
#define Smem_freE free
#define SfileadrL 4096
/* <<< ??? */
typedef int (*Cleanup_app_handler_T)();
struct LinkiteM;
/* 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
struct XorrisO { /* the global context of xorriso */
int libs_are_started;
/* source */
char progname[SfileadrL];
char initial_wdx[SfileadrL];
int no_rc;
/** 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;
/* >>> put libisofs aspects here <<< */
int do_joliet;
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 publisher[129];
/* >>> put libburn/isoburn aspects here */
char indev[SfileadrL];
void *in_drive_handle; /* interpreted only by xorrisoburn.c */
void *in_volset_handle; /* interpreted only by xorrisoburn.c */
int volset_change_pending; /* whether -commit would make sense */
char outdev[SfileadrL];
void *out_drive_handle; /* interpreted only by xorrisoburn.c */
int dev_fd_1; /* The fd which substitutes for /dev/fd/1 and is
connected to externaly perveived stdout.
*/
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 keep_boot_image;
int patch_isolinux_image;
/* XORRISO options */
int allow_graft_points;
int dialog;
/* 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;
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];
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;
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 */
#ifdef Xorriso_with_regeX
regex_t *re;
regmatch_t match[1];
#endif /* Xorriso_with_regeX */
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 */
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;
void *pacifier_fifo;
int find_compare_result; /* 1=everything matches , 0=mismatch , -1=error */
/* result (stdout, R: ) */
char result_line[5*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 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);
char *Text_shellsafe(char *in_text, char *out_text, int flag);
int Sort_argv(int argc, char **argv, 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;
/* @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_get_start_path(struct FindjoB *o, char **start_path, int flag);
#endif /* Xorriso_private_includeD */

View File

@ -0,0 +1 @@
#define Xorriso_timestamP "2008.03.08.104231"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,195 @@
/* 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, <scdbackup@gmx.net>
Provided under GPL version 2.
This file contains the inner isofs- and burn-library interface of xorriso.
*/
#ifndef Xorrisoburn_includeD
#define Xorrisoburn_includeD yes
struct XorrisO;
struct FindjoB;
/* The minimum version of libisoburn to be used with this version of xorriso
*/
#define xorriso_libisoburn_req_major 0
#define xorriso_libisoburn_req_minor 1
#define xorriso_libisoburn_req_micro 0
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, 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
*/
int Xorriso_toc(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);
int Xorriso_blank_media(struct XorrisO *xorriso, int flag);
int Xorriso_format_media(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 */
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);
int Xorriso_burn_track(struct XorrisO *xorriso, char *track_source, 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);
/* @param flag bit0= do not mark image as changed */
int Xorriso_set_publisher(struct XorrisO *xorriso, char *name, int flag);
int Xorriso_iso_file_open(struct XorrisO *xorriso, char *pathname,
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);
#endif /* Xorrisoburn_includeD */

View File

@ -0,0 +1,3 @@
Vreixo Formoso
Mario Danic
Thomas Schmitt

View File

@ -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

View File

@ -0,0 +1,19 @@
Vreixo Formoso <metalpain2002@yahoo.es>,
Mario Danic <mario.danic@gmail.com>,
Thomas Schmitt <scdbackup@gmx.net>
Copyright (C) 2007-2008 Vreixo Formoso, 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 as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
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

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,234 @@
Installation Instructions
*************************
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
2006 Free Software Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
Basic Installation
==================
Briefly, the shell commands `./configure; make; make install' should
configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
cache files.
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You need `configure.ac' if
you want to change it or regenerate `configure' using a newer version
of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system.
Running `configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that the
`configure' script does not know about. Run `./configure --help' for
details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
With a non-GNU `make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use `make distclean' before
reconfiguring for another architecture.
Installation Names
==================
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' cannot figure out automatically,
but needs to determine by the type of machine the package will run on.
Usually, assuming the package is built to be run on the _same_
architectures, `configure' can figure that out, but if it prints a
message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share, you
can create a site shell script called `config.site' that gives default
values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf bug. Until the bug is fixed you can use this workaround:
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================
`configure' recognizes the following options to control how it operates.
`--help'
`-h'
Print a summary of the options to `configure', and exit.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

View File

@ -0,0 +1,191 @@
pkgconfigdir=$(libdir)/pkgconfig
libincludedir=$(includedir)/libisofs
lib_LTLIBRARIES = libisofs/libisofs.la
## ========================================================================= ##
# Build libraries
libisofs_libisofs_la_LDFLAGS = \
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
libisofs_libisofs_la_SOURCES = \
libisofs/builder.h \
libisofs/builder.c \
libisofs/node.h \
libisofs/node.c \
libisofs/tree.h \
libisofs/tree.c \
libisofs/find.c \
libisofs/image.h \
libisofs/image.c \
libisofs/fsource.h \
libisofs/fsource.c \
libisofs/fs_local.c \
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/filter.h \
libisofs/filter.c \
libisofs/filters/xor_encrypt.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.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/iso1999.h \
libisofs/iso1999.c \
libisofs/data_source.c
libisofs_libisofs_la_LIBADD= \
$(THREAD_LIBS)
libinclude_HEADERS = \
libisofs/libisofs.h
## ========================================================================= ##
## Build demo applications
noinst_PROGRAMS = \
demo/lsl \
demo/cat \
demo/catbuffer \
demo/tree \
demo/find \
demo/ecma119tree \
demo/iso \
demo/isoread \
demo/isocat \
demo/isomodify \
demo/isoms \
demo/isogrow
demo_lsl_CPPFLAGS = -Ilibisofs
demo_lsl_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
demo_lsl_SOURCES = demo/lsl.c
demo_cat_CPPFLAGS = -Ilibisofs
demo_cat_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
demo_cat_SOURCES = demo/cat.c
demo_catbuffer_CPPFLAGS = -Ilibisofs
demo_catbuffer_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
demo_catbuffer_SOURCES = demo/cat_buffer.c
demo_tree_CPPFLAGS = -Ilibisofs
demo_tree_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
demo_tree_SOURCES = demo/tree.c
demo_find_CPPFLAGS = -Ilibisofs
demo_find_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
demo_find_SOURCES = demo/find.c
demo_ecma119tree_CPPFLAGS = -Ilibisofs
demo_ecma119tree_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
demo_ecma119tree_SOURCES = demo/ecma119_tree.c
demo_iso_CPPFLAGS = -Ilibisofs
demo_iso_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
demo_iso_SOURCES = demo/iso.c
demo_isoread_CPPFLAGS = -Ilibisofs
demo_isoread_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
demo_isoread_SOURCES = demo/iso_read.c
demo_isocat_CPPFLAGS = -Ilibisofs
demo_isocat_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
demo_isocat_SOURCES = demo/iso_cat.c
demo_isomodify_CPPFLAGS = -Ilibisofs
demo_isomodify_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
demo_isomodify_SOURCES = demo/iso_modify.c
demo_isoms_CPPFLAGS = -Ilibisofs
demo_isoms_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
demo_isoms_SOURCES = demo/iso_ms.c
demo_isogrow_CPPFLAGS = -Ilibisofs -Ilibburn
demo_isogrow_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS) -lburn
demo_isogrow_SOURCES = demo/iso_grow.c
## Build unit test
check_PROGRAMS = \
test/test
test_test_CPPFLAGS = -Ilibisofs
test_test_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS) -lcunit
test_test_LDFLAGS = -L.. -lm
test_test_SOURCES = \
test/test.h \
test/test.c \
test/test_node.c \
test/test_image.c \
test/test_tree.c \
test/test_util.c \
test/test_rockridge.c \
test/test_stream.c \
test/mocked_fsrc.h \
test/mocked_fsrc.c
## ========================================================================= ##
## Build documentation (You need Doxygen for this to work)
docdir = $(DESTDIR)$(prefix)/share/doc/$(PACKAGE)-$(VERSION)
doc: doc/html
doc/html: doc/doxygen.conf
$(RM) -r doc/html; \
doxygen doc/doxygen.conf;
install-data-local:
if [ -d doc/html ]; then \
$(mkinstalldirs) $(docdir)/html; \
$(INSTALL_DATA) doc/html/* $(docdir)/html; \
fi
uninstall-local:
rm -rf $(docdir)
## ========================================================================= ##
# Extra things
nodist_pkgconfig_DATA = \
libisofs-1.pc
EXTRA_DIST = \
libisofs-1.pc.in \
version.h.in \
doc/doxygen.conf.in \
doc/Tutorial \
README \
AUTHORS \
COPYRIGHT \
COPYING \
NEWS \
INSTALL \
TODO \
ChangeLog \
Roadmap

View File

@ -0,0 +1,20 @@
== unknown ==
Libisofs v0.6.4
===============
-
== Fri Feb 22 2008 ==
Libisofs v0.6.2.1
=================
- FIX: missing buffer.h in tarball
== Thu Feb 14 2008 ==
Libisofs v0.6.2
================
- Initial release

View File

@ -0,0 +1,341 @@
------------------------------------------------------------------------------
libisofs
------------------------------------------------------------------------------
Released under GPL (see COPYING file for details).
Copyright (C) 2008 Vreixo Formoso, Mario Danic, Thomas Schmitt
libisofs is part of the libburnia project (libburnia-project.org)
------------------------------------------------------------------------------
libisofs is a library to create an ISO-9660 filesystem, and supports extensions
like RockRidge or Joliet. It is also a full featured ISO-9660 editor, allowing
you to modify an ISO image or multisession disc, including file addition and
removal, change of file names and attributes, etc
Features:
---------
- Image creation
- Creates ISO-9660 images from local files.
- Support for RockRidge and Joliet extensions.
- Support for ISO-9660:1999 (version 2)
- Support for El-Torito bootable images.
- Full featured edition of file names and attributes on the image.
- Several options to relax ISO-9660 constraints.
- Special options for images intended for distribution (suitable default
modes for files, hiding of real timestamps...)
- Multisession
- Support for growing an existing image
- Full-featured edition of the image files, including: addition of new
files, removing of existent files, moving files, renaming files,
change file attributes (permissions, timestamps...)
- Support for "emulated multisession" or image growing, suitable for non
multisession media such as DVD+RW
- Image modification
- It can create a completely new image from files on another image.
- Full-featured edition of image contents
- Others
- Handling of different input and output charset
- Good integration with libburn for image burning.
- Reliable, good handling of different kind of errors.
Requirements:
-------------
- libburn 0.4.2 headers must be installed at compile time. It is not required
at runtime.
Know bugs:
----------
Multisession and image growing can lead to undesired results in several cases:
a) Images with unsupported features, such as:
- UDF.
- HSF/HFS+ or other Mac extensions.
- El-Torito with multiple entries.
- ECMA-119 with extended attributes, multiple extends per file.
- Non El-Torito boot info.
- zisofs compressed images.
- ...
In all these cases, the resulting new image (or new session) could lack some
features of the original image.
In some cases libisofs will issue warning messages, or even refuse to grow
or modify the image. Others remain undetected. Images created with libisofs
do not have this problems.
b) Bootable El-Torito images may have several problems, that result in a new
image that is not bootable, or that boots from an outdated session. In many
cases it is recommended to add boot info again in the new session.
- isolinux images won't be bootable after a modify. This is because
isolinux images need to have hardcoded the root dir lba. libisofs cannot
know whether an image is an isolinux image or not, so the user is
responsible to tell libisofs that it must patch the image, with the
el_torito_patch_isolinux_image() function. This problem could also exists
on other boot images.
- Most boot images are highly dependent of the image contents, so if the
user moves or removes some files on image it is possible they won't boot
anymore.
- There is no safer way to modify hidden boot images, as the size of the
boot image can't be figured out.
c) Generated images could have different ECMA-119 low level names, due to
different way to mangle names, to new files added that force old files to
be renamed, to different relaxed contraints... This only affect the
ISO-9660 info, not the RR names, so it shouldn't be a problem in most
cases. If your app. relies on low level ISO-9660 names, you will need to
ensure all node names are valid ISO names (maybe together with some
relaxed contraints), otherwise libisofs might arbitrarily change the names.
------------------------------------------------------------------------------
Download, Build and Installation
libisofs code is mantained in a Bazaar repository at Launchpad
(https://launchpad.net/libisofs/). You can download it with:
$ bzr branch lp:libisofs
Our build system is based on autotools. For preparing the build you will need
autotools of at least version 1.7. If you have download the code from the
repository, first of all you need to execute
./autogen.sh
on toplevel dir to execute autotools.
Alternatively you may unpack a release tarball for which you do not need
autotools installed.
To build libisofs it should be sufficient to go into its toplevel directory
and execute
./configure --prefix=/usr
make
To make the libraries accessible for running resp. developing applications
make install
See INSTALL file for further details.
------------------------------------------------------------------------------
Overview of libburnia-project.org
libburnia-project.org is an open-source software project for reading, mastering
and writing optical discs.
For now this means only CD media and all single layer DVD media except DVD+R.
The project comprises of several more or less interdependent parts which
together strive to be a usable foundation for application development.
These are libraries, language bindings, and middleware binaries which emulate
classical (and valuable) Linux tools.
Our scope is currently Linux 2.4 and 2.6 only. For ports to other systems
we would need : login on a development machine resp. a live OS on CD or DVD,
advise from a system person about the equivalent of Linux sg or FreeBSD CAM,
volunteers for testing of realistic use cases.
We have a workable code base for burning CD and most single layer DVD.
The burn API is quite comprehensively documented and can be used to build a
presentable application.
We have a functional binary which emulates parts of cdrecord in order to
prove that usability, and in order to allow you to explore libburnia's scope
by help of existing cdrecord frontends.
The project components (list subject to growth, hopefully):
- libburn is the library by which preformatted data get onto optical media.
It uses either /dev/sgN (e.g. on kernel 2.4 with ide-scsi) or
/dev/hdX (e.g. on kernel 2.6).
libburn is the foundation of our cdrecord emulation. Its code is
independent of cdrecord. Its DVD capabilities are learned from
studying the code of dvd+rw-tools and MMC-5 specs. No code but only
the pure SCSI knowledge has been taken from dvd+rw-tools, though.
- libisofs is the library to pack up hard disk files and directories into a
ISO 9660 disk image. This may then be brought to media via libburn.
libisofs is to be the foundation of our upcoming mkisofs emulation.
- cdrskin is a limited cdrecord compatibility wrapper for libburn.
Cdrecord is a powerful GPL'ed burn program included in Joerg
Schilling's cdrtools. cdrskin strives to be a second source for
the services traditionally provided by cdrecord. Additionally it
provides libburn's DVD capabilities, where only -sao is compatible
with cdrecord.
cdrskin does not contain any bytes copied from cdrecord's sources.
Many bytes have been copied from the message output of cdrecord
runs, though.
See cdrskin/README and man cdrskin/cdrskin.1 for more.
- test is a collection of application gestures and examples given by the
authors of the library features. The main API example for libburn
is test/libburner.c .
Explore these examples if you look for inspiration.
We plan to be a responsive upstream. Bear with us. We are still practicing.
------------------------------------------------------------------------------
Project history as far as known to me:
- Founded in 2002 as it seems. See mailing list archives
http://lists.freedesktop.org/archives/libburn/
The site of this founder team is reachable and offers download of a
(somewhat outdated) tarball and from CVS :
http://icculus.org/burn/
Copyright holders and most probably founders:
Derek Foreman and Ben Jansens.
- I came to using libburn in 2005. Founded the cdrskin project and submitted
necessary patches which were accepted or implemented better. Except one
remaining patch which prevented cdrskin from using vanilla libburn from CVS.
The cdrskin project site is reachable and offers download of the heavily
patched (elsewise outdated) tarball under the name cdrskin-0.1.2 :
http://scdbackup.sourceforge.net/cdrskin_eng.html
It has meanwhile moved to use vanilla libburn.pykix.org , though.
Version 0.1.4 constitutes the first release of this kind.
- In July 2006 our team mate Mario Danic announced a revival of libburn
which by about nearly everybody else was perceived as unfriendly fork.
Derek Foreman four days later posted a message which expressed his
discontent.
The situation first caused me to publically regret it and then - after i
got the opportunity to move in with cdrskin - gave me true reason to
personally apologize to Derek Foreman, Ben Jansens and the contibutors at
icculus.org/burn. Posted to both projects:
http://lists.freedesktop.org/archives/libburn/2006-August/000446.html
http://mailman-mail1.webfaction.com/pipermail/libburn-hackers/2006-August/000024.html
- Mid August 2006 project cdrskin established a branch office in
libburn.pykix.org so that all maintainers of our tools have one single place
to get the current (at least slightely) usable coordinated versions of
everything.
Project cdrskin will live forth independendly for a while but it is committed
to stay in sync with libburn.pykix.org (or some successor, if ever).
cdrskin is also committed to support icculus.org/burn if the pending fork
is made reality by content changes in that project. It will cease to maintain
a patched version of icculus.org/burn though. Precondition for a new
release of cdrskin on base of icculus.org/burn would be the pending
"whitelist patch" therefore.
I would rather prefer if both projects find consense and merge, or at least
cooperate. I have not given up hope totally, yet.
I, personally, will honor any approach.
- 2nd September 2006 the decision is made to strive for a consolidation of
copyright and a commitment to GPL in a reasonable and open minded way.
This is to avoid long term problems with code of unknown origin and
with finding consense among the not so clearly defined group of copyright
claimers and -holders.
libisofs is already claimed sole copyright Mario Danic.
cdrskin and libburner are already claimed sole copyright Thomas Schmitt.
Rewrites of other components will follow and concluded by claiming full
copyright within the group of libburn.pykix.org-copyright holders.
- 16th September 2006 feature freeze for release of libburn-0.2.2 .
- 20th September 2006 release of libburn-0.2.2 .
- 26th October 2006 feature freeze for cdrskin-0.2.4 based on libburn-0.2.3 .
This version of cdrskin is much more cdrecord compatible in repect
to drive addressing and audio features.
- 30th October 2006 release of cdrskin-0.2.4 .
- 13th November 2006 splitting releases of libburn+cdrskin from libisofs.
- 24th November 2006 release of libburn-0.2.6 and cdrskin-0.2.6 . cdrskin has
become suitable for unaware frontends as long as they perform only the core
of cdrecord use cases (including open-ended input streams, audio, and
multi-session).
- 28th November 2006 the umbrella project which encloses both, libisofs and
libburn, is now called libburnia. For the origin of this name, see
http://en.wikipedia.org/wiki/Liburnians .
- 16th January 2007 release of libburn-0.3.0 and cdrskin-0.3.0 . Now the scope
is widened to a first class of DVD media: overwriteable single layer types
DVD-RAM, DVD+RW, DVD-RW. This is not a cdrecord emulation but rather inspired
by dvd+rw-tools' "poor man" writing facility for this class of media.
Taking a bow towards Andy Polyakov.
- 11th February 2007 version 0.3.2 covers sequential DVD-RW and DVD-R with
multi-session and with DAO.
- 12th March 2007 version 0.3.4 supports DVD+R and thus covers all single layer
DVD media. Code for double layer DVD+/-R is implemented but awaits a tester
yet.
- 23th April 2007 version 0.3.6 follows the unanimous opinion of Linux kernel
people that one should not use /dev/sg on kernel 2.6.
- 31st July 2007 version 0.3.8 marks the first anniversary of libburn revival.
We look back on improved stability, a substantially extended list of media
and write modes, and better protection against typical user mishaps.
- 24th October 2007 version 0.4.0 is the foundation of new library libisoburn
and an upcomming integrated application for manipulating and writing
ISO 9660 + Rock Ridge images. cdrskin-0.4.0 got capabilities like growisofs
by these enhancements: growing of overwriteable media and disk files.
Taking again a bow towards Andy Polyakov.
- 26th Januar 2008 version 0.4.2 rectifies the version numbering so that we
reliably release libburn.so.4 as should have been done since libburn-0.3.2.
cdrskin now is by default linked dynamically and does a runtime check
to ensure not to be started with a libburn which is older than itself.
------------------------------------------------------------------------------
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation. To be exact: version 2 of that License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
Clarification in my name and in the name of Mario Danic, upcoming copyright
holders on toplevel of libburnia. To be fully in effect after the remaining
other copyrighted code has been replaced by ours and by copyright-free
contributions of our friends:
------------------------------------------------------------------------------
We, the copyright holders, agree on the interpretation that
dynamical linking of our libraries constitutes "use of" and
not "derivation from" our work in the sense of GPL, provided
those libraries are compiled from our unaltered code.
Thus you may link our libraries dynamically with applications
which are not under GPL. You may distribute our libraries and
application tools in binary form, if you fulfill the usual
condition of GPL to offer a copy of the source code -altered
or unaltered- under GPL.
We ask you politely to use our work in open source spirit
and with the due reference to the entire open source community.
If there should really arise the case where above clarification
does not suffice to fulfill a clear and neat request in open source
spirit that would otherwise be declined for mere formal reasons,
only in that case we will duely consider to issue a special license
covering only that special case.
It is the open source idea of responsible freedom which will be
decisive and you will have to prove that you exhausted all own
means to qualify for GPL.
For now we are firmly committed to maintain one single license: GPL.
signed: Mario Danic, Thomas Schmitt

View File

@ -0,0 +1,33 @@
>>>>>>>>>> RELEASE 0.6.1 (development) >>>>>>>>>>>>>>>>>>>>>
- Review error severities
OK - Prepare API for stability and compatibility check
- Documentation
>>>>>>>>>> RELEASE 0.6.2 (stable) >>>>>>>>>>>>>>>>>>>>>>>>>>
- Intensive testing and bug fixing
>>>>>>>>>> RELEASE 0.6.3 (development) >>>>>>>>>>>>>>>>>>>>>
- Improves to public tree
-> Expose node extended info. Always compile it.
(little memory cost)
-> Review builder / tree / node relation
-> Optimize storage of children in node?
-> Inode object?
- Expose Builder and Streams
- Implement filters: compression, encryption...
- Consider some kind of plugin system for Builders, Filesystems and Filters.
- ECMA-119, Joliet, and ISO-9660:1999 writers can share most of the code.
Create a new writer as a generalization of these.
- Update Java bindings
>>>>>>>>>>> ......
>>>>>>>>>>> RELEASE 1.0.0 (stable) >>>>>>>>>>>>>>>>>>>>>>>>>>
- UDF
- HFS

View File

@ -0,0 +1,35 @@
FEATURES
========
TODO
====
#00001 (node.h) -> consider adding new timestamps to IsoTreeNode
#00004 (libisofs.h) -> Add a get_mime_type() function.
#00005 (node.c) -> optimize iso_dir_iter_take.
#00006 (libisofs.h) -> define more replace values when adding a node to a dir
#00007 (libisofs.h) -> expose iso_tree_add_new_file
#00008 (data_dource.c) -> guard against partial reads
#00009 (ecma119_tree.c/h) -> add true support for harlinks and inode numbers
#00010 (buffer.c) -> optimize ring buffer
#00011 (ecma119.c) -> guard against bad path table usage with more than 65535 dirs
#00012 (fs_image.c) -> support follow symlinks on imafe filesystem
#00013 (fs_image.c) -> check for unsupported flags when reading a dir record
#00014 (fs_image.c) -> more sanity checks to ensure dir record info is valid
#00015 (fs_image.c) -> take care of CD-ROM XA discs when reading SP entry
#00016 (fs_image.c) -> handle non RR ER entries
#00017 (fs_image.c) -> take advantage of other atts of PVD
#00018 (fs_image.c) -> check if there are more entries in the boot catalog
#00019 (fs_image.c) -> set IsoImage attribs from Joliet SVD?
#00020 (fs_image.c) -> handle RR info in Joliet tree
#00021 (fs_image.c) -> handle RR info in ISO 9660:1999 tree
#00022 (joliet.c) -> support relaxed constraints in joliet filenames
#00024 (libisofs.h) -> option to convert names to lower case for iso reading
#00025 (libisofs.h) -> support for merging old image files
#00026 (libisofs.h) -> add support for "hidden" bootable images.
#00027 (iso1999.h) -> Follow ISO 9660:1999 specs when sorting files
FIXME
=====

View File

@ -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])
])

View File

@ -0,0 +1,10 @@
#!/bin/sh -x
aclocal
libtoolize --copy --force
autoconf
# ts A61101 : libburn is not prepared for config.h
# autoheader
automake --foreign --add-missing --copy --include-deps

View File

@ -0,0 +1,155 @@
AC_INIT([libisofs], [0.6.3], [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 A61101 This breaks Linux build (makes 32 bit off_t)
dnl http://sourceware.org/autobook/autobook/autobook_96.html says
dnl one must include some config.h and this was a pitfall.
dnl So why dig the pit at all ?
dnl AM_CONFIG_HEADER(config.h)
dnl
dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match
dnl
dnl CURRENT and AGE describe the binary compatibility interval of a
dnl dynamic library.
dnl See also http://www.gnu.org/software/libtool/manual.html#Interfaces
dnl
dnl The name of the library will be libisofs.so.$CURRENT-$AGE.$AGE.$REV
dnl In the terminology of this file:
dnl CURRENT = LT_CURRENT
dnl REV = LT_REVISION
dnl AGE = LT_AGE
dnl
dnl LT_CURRENT, LT_REVISION and LT_AGE get set directly now.
dnl
dnl SONAME of the emerging library is LT_CURRENT - LT_AGE.
dnl The linker will do no finer checks. Especially no age range check for
dnl the cdrskin binary. If SONAME matches, then the couple starts.
dnl
dnl Therefore a run time check is provided by libisofs function
dnl iso_lib_version(). It returns the major, minor and micro revision of the
dnl library. This means LIBISOFS_*_VERSION kept its second job which does not
dnl comply to the usual ways of configure.ac . I.e. now *officially* this is
dnl the source code release version as announced to the public. It has no
dnl conection to SONAME or libtool version numbering.
dnl It rather feeds the API function iso_lib_version().
dnl
dnl If LIBISOFS_*_VERSION changes, be sure to change AC_INIT above to match.
dnl
LIBISOFS_MAJOR_VERSION=0
LIBISOFS_MINOR_VERSION=6
LIBISOFS_MICRO_VERSION=3
LIBISOFS_VERSION=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION.$LIBISOFS_MICRO_VERSION
AC_SUBST(LIBISOFS_MAJOR_VERSION)
AC_SUBST(LIBISOFS_MINOR_VERSION)
AC_SUBST(LIBISOFS_MICRO_VERSION)
AC_SUBST(LIBISOFS_VERSION)
dnl Libtool versioning
LT_RELEASE=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION
# SONAME = 6 - 0 = 6 . Library name = libisofs.6.0.0
LT_CURRENT=6
LT_REVISION=0
LT_AGE=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_MSG_ERROR([Libisofs requires largefile support.])
fi
AC_PROG_LIBTOOL
AC_SUBST(LIBTOOL_DEPS)
LIBTOOL="$LIBTOOL --silent"
AC_PROG_INSTALL
AC_CHECK_HEADERS()
dnl Use GNU extensions if available
AC_DEFINE(_GNU_SOURCE, 1)
dnl Check for tm_gmtoff field in struct tm
AC_CHECK_MEMBER([struct tm.tm_gmtoff],
[AC_DEFINE(HAVE_TM_GMTOFF, 1,
[Define this if tm structure includes a tm_gmtoff entry.])],
,
[#include <time.h>])
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 <time.h>])
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 <unistd.h>])
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
dnl Verbose debug to make libisofs issue more debug messages
AC_ARG_ENABLE(verbose-debug,
[ --enable-verbose-debug Enable verbose debug messages [default=no]],
AC_DEFINE(LIBISOFS_VERBOSE_DEBUG, 1))
AC_CONFIG_FILES([
Makefile
doc/doxygen.conf
version.h
libisofs-1.pc
])
AC_OUTPUT

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2007 Vreixo Formoso
*
* This file is part of the libisofs project; 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. See COPYING file for details.
*/
#include "libisofs.h"
#include "fsource.h"
#include <stdio.h>
#include <stdlib.h>
/*
* Little test program to test filesystem implementations.
* Outputs file contents to stdout!
*/
int main(int argc, char **argv)
{
int res;
IsoFilesystem *fs;
IsoFileSource *file;
struct stat info;
if (argc != 2) {
fprintf(stderr, "Usage: cat /path/to/file\n");
return 1;
}
/* create filesystem object */
res = iso_local_filesystem_new(&fs);
if (res < 0) {
fprintf(stderr, "Can't get local fs object, err = %d\n", res);
return 1;
}
res = fs->get_by_path(fs, argv[1], &file);
if (res < 0) {
fprintf(stderr, "Can't get file, err = %d\n", res);
return 1;
}
res = iso_file_source_lstat(file, &info);
if (res < 0) {
fprintf(stderr, "Can't stat file, err = %d\n", res);
return 1;
}
if (S_ISDIR(info.st_mode)) {
fprintf(stderr, "Path refers to a directory!!\n");
return 1;
} else {
char buf[1024];
res = iso_file_source_open(file);
if (res < 0) {
fprintf(stderr, "Can't open file, err = %d\n", res);
return 1;
}
while ((res = iso_file_source_read(file, buf, 1024)) > 0) {
fwrite(buf, 1, res, stdout);
}
if (res < 0) {
fprintf(stderr, "Error reading, err = %d\n", res);
return 1;
}
iso_file_source_close(file);
}
iso_file_source_unref(file);
iso_filesystem_unref(fs);
return 0;
}

View File

@ -0,0 +1,127 @@
/*
* Copyright (c) 2007 Vreixo Formoso
*
* This file is part of the libisofs project; 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. See COPYING file for details.
*/
#include "libisofs.h"
#include "buffer.h"
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/*
* Little test program that reads a file and outputs it to stdout, using
* the libisofs ring buffer as intermediate memory
*/
struct th_data
{
IsoRingBuffer *rbuf;
char *path;
};
#define WRITE_CHUNK 2048
#define READ_CHUNK 2048
static
void *write_function(void *arg)
{
ssize_t bytes;
int res;
unsigned char tmp[WRITE_CHUNK];
struct th_data *data = (struct th_data *) arg;
int fd = open(data->path, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Writer thread error: Can't open file");
iso_ring_buffer_writer_close(data->rbuf, 1);
pthread_exit(NULL);
}
res = 1;
while ( (bytes = read(fd, tmp, WRITE_CHUNK)) > 0) {
res = iso_ring_buffer_write(data->rbuf, tmp, bytes);
if (res <= 0) {
break;
}
/* To test premature reader exit >>>>>>>>>>>
iso_ring_buffer_writer_close(data->rbuf);
pthread_exit(NULL);
<<<<<<<<<<<<<<<<<<<<<<<<< */
// if (rand() > 2000000000) {
// fprintf(stderr, "Writer sleeping\n");
// sleep(1);
// }
}
fprintf(stderr, "Writer finish: %d\n", res);
close(fd);
iso_ring_buffer_writer_close(data->rbuf, 0);
pthread_exit(NULL);
}
static
void *read_function(void *arg)
{
unsigned char tmp[READ_CHUNK];
int res = 1;
struct th_data *data = (struct th_data *) arg;
while ( (res = iso_ring_buffer_read(data->rbuf, tmp, READ_CHUNK)) > 0) {
write(1, tmp, READ_CHUNK);
/* To test premature reader exit >>>>>>>>>>>
iso_ring_buffer_reader_close(data->rbuf);
pthread_exit(NULL);
<<<<<<<<<<<<<<<<<<<<<<<<< */
// if (rand() > 2000000000) {
// fprintf(stderr, "Reader sleeping\n");
// sleep(1);
// }
}
fprintf(stderr, "Reader finish: %d\n", res);
iso_ring_buffer_reader_close(data->rbuf, 0);
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
int res;
struct th_data data;
pthread_t reader;
pthread_t writer;
if (argc != 2) {
fprintf(stderr, "Usage: catbuffer /path/to/file\n");
return 1;
}
res = iso_ring_buffer_new(1024, &data.rbuf);
if (res < 0) {
fprintf(stderr, "Can't create buffer\n");
return 1;
}
data.path = argv[1];
res = pthread_create(&writer, NULL, write_function, (void *) &data);
res = pthread_create(&reader, NULL, read_function, (void *) &data);
pthread_join(writer, NULL);
pthread_join(reader, NULL);
fprintf(stderr, "Buffer was %d times full and %d times empty.\n",
iso_ring_buffer_get_times_full(data.rbuf),
iso_ring_buffer_get_times_empty(data.rbuf));
free(data.rbuf);
return 0;
}

View File

@ -0,0 +1,136 @@
/*
* Little program that imports a directory to iso image, generates the
* ecma119 low level tree and prints it.
* Note that this is not an API example, but a little program for test
* purposes.
*/
#include "libisofs.h"
#include "ecma119.h"
#include "ecma119_tree.h"
#include "util.h"
#include "filesrc.h"
#include "node.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
static void
print_permissions(mode_t mode)
{
char perm[10];
//TODO suid, sticky...
perm[9] = '\0';
perm[8] = mode & S_IXOTH ? 'x' : '-';
perm[7] = mode & S_IWOTH ? 'w' : '-';
perm[6] = mode & S_IROTH ? 'r' : '-';
perm[5] = mode & S_IXGRP ? 'x' : '-';
perm[4] = mode & S_IWGRP ? 'w' : '-';
perm[3] = mode & S_IRGRP ? 'r' : '-';
perm[2] = mode & S_IXUSR ? 'x' : '-';
perm[1] = mode & S_IWUSR ? 'w' : '-';
perm[0] = mode & S_IRUSR ? 'r' : '-';
printf("[%s]",perm);
}
static void
print_dir(Ecma119Node *dir, int level)
{
int i;
char *sp = alloca(level * 2 + 1);
for (i = 0; i < level * 2; i += 2) {
sp[i] = '|';
sp[i+1] = ' ';
}
sp[level * 2-1] = '-';
sp[level * 2] = '\0';
for (i = 0; i < dir->info.dir->nchildren; i++) {
Ecma119Node *child = dir->info.dir->children[i];
if (child->type == ECMA119_DIR) {
printf("%s+[D] ", sp);
print_permissions(iso_node_get_permissions(child->node));
printf(" %s\n", child->iso_name);
print_dir(child, level+1);
} else if (child->type == ECMA119_FILE) {
printf("%s-[F] ", sp);
print_permissions(iso_node_get_permissions(child->node));
printf(" %s {%p}\n", child->iso_name, (void*)child->info.file);
} else if (child->type == ECMA119_SYMLINK) {
printf("%s-[L] ", sp);
print_permissions(iso_node_get_permissions(child->node));
printf(" %s -> %s\n", child->iso_name,
((IsoSymlink*)child->node)->dest);
} else if (child->type == ECMA119_SPECIAL) {
printf("%s-[S] ", sp);
print_permissions(iso_node_get_permissions(child->node));
printf(" %s\n", child->iso_name);
} else if (child->type == ECMA119_PLACEHOLDER) {
printf("%s-[RD] ", sp);
print_permissions(iso_node_get_permissions(child->node));
printf(" %s\n", child->iso_name);
} else {
printf("%s-[????] ", sp);
}
}
}
int main(int argc, char **argv)
{
int result;
IsoImage *image;
Ecma119Image *ecma119;
if (argc != 2) {
printf ("You need to specify a valid path\n");
return 1;
}
iso_init();
iso_set_msgs_severities("NEVER", "ALL", "");
result = iso_image_new("volume_id", &image);
if (result < 0) {
printf ("Error creating image\n");
return 1;
}
result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[1]);
if (result < 0) {
printf ("Error adding directory %d\n", result);
return 1;
}
ecma119 = calloc(1, sizeof(Ecma119Image));
iso_rbtree_new(iso_file_src_cmp, &(ecma119->files));
ecma119->iso_level = 1;
ecma119->rockridge = 1;
ecma119->image = image;
ecma119->input_charset = strdup("UTF-8");
/* create low level tree */
result = ecma119_tree_create(ecma119);
if (result < 0) {
printf ("Error creating ecma-119 tree: %d\n", result);
return 1;
}
printf("================= ECMA-119 TREE =================\n");
print_dir(ecma119->root, 0);
printf("\n\n");
ecma119_node_free(ecma119->root);
iso_rbtree_destroy(ecma119->files, iso_file_src_free);
free(ecma119->input_charset);
free(ecma119);
iso_image_unref(image);
iso_finish();
return 0;
}

View File

@ -0,0 +1,176 @@
/*
* Little program to show how to create an iso image from a local
* directory.
*/
#include "libisofs.h"
#include "libburn/libburn.h"
#include <stdio.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <err.h>
const char * const optstring = "JRIL:b:hV:";
extern char *optarg;
extern int optind;
void usage(char **argv)
{
printf("%s [OPTIONS] DIRECTORY OUTPUT\n", argv[0]);
}
void help()
{
printf(
"Options:\n"
" -J Add Joliet support\n"
" -R Add Rock Ridge support\n"
" -I Add ISO 9660:1999 support\n"
" -V label Volume Label\n"
" -L <num> Set the ISO level (1 or 2)\n"
" -b file Specifies a boot image to add to image\n"
" -h Print this message\n"
);
}
int callback(IsoFileSource *src)
{
char *path = iso_file_source_get_path(src);
printf("CALLBACK: %s\n", path);
free(path);
return 1;
}
int main(int argc, char **argv)
{
int result;
int c;
IsoImage *image;
struct burn_source *burn_src;
unsigned char buf[2048];
FILE *fd;
IsoWriteOpts *opts;
char *volid = "VOLID";
char *boot_img = NULL;
int rr = 0, j = 0, iso1999 = 0, level = 1;
while ((c = getopt(argc, argv, optstring)) != -1) {
switch(c) {
case 'h':
usage(argv);
help();
exit(0);
break;
case 'J':
j = 1;
break;
case 'R':
rr = 1;
break;
case 'I':
iso1999 = 1;
break;
case 'L':
level = atoi(optarg);
break;
case 'b':
boot_img = optarg;
break;
case 'V':
volid = optarg;
break;
case '?':
usage(argv);
exit(1);
break;
}
}
if (argc < 2) {
printf ("Please pass directory from which to build ISO\n");
usage(argv);
return 1;
}
if (argc < 3) {
printf ("Please supply output file\n");
usage(argv);
return 1;
}
fd = fopen(argv[optind+1], "w");
if (!fd) {
err(1, "error opening output file");
}
result = iso_init();
if (result < 0) {
printf ("Can't initialize libisofs\n");
return 1;
}
iso_set_msgs_severities("NEVER", "ALL", "");
result = iso_image_new(volid, &image);
if (result < 0) {
printf ("Error creating image\n");
return 1;
}
iso_tree_set_follow_symlinks(image, 0);
iso_tree_set_ignore_hidden(image, 0);
iso_tree_set_ignore_special(image, 0);
iso_set_abort_severity("SORRY");
/*iso_tree_set_report_callback(image, callback);*/
result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[optind]);
if (result < 0) {
printf ("Error adding directory %d\n", result);
return 1;
}
if (boot_img) {
/* adds El-Torito boot info. Tunned for isolinux */
ElToritoBootImage *bootimg;
result = iso_image_set_boot_image(image, boot_img, ELTORITO_NO_EMUL,
"/isolinux/boot.cat", &bootimg);
if (result < 0) {
printf ("Error adding boot image %d\n", result);
return 1;
}
el_torito_set_load_size(bootimg, 4);
el_torito_patch_isolinux_image(bootimg);
}
result = iso_write_opts_new(&opts, 0);
if (result < 0) {
printf ("Cant create write opts, error %d\n", result);
return 1;
}
iso_write_opts_set_iso_level(opts, level);
iso_write_opts_set_rockridge(opts, rr);
iso_write_opts_set_joliet(opts, j);
iso_write_opts_set_iso1999(opts, iso1999);
result = iso_image_create_burn_source(image, opts, &burn_src);
if (result < 0) {
printf ("Cant create image, error %d\n", result);
return 1;
}
iso_write_opts_free(opts);
while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
fwrite(buf, 1, 2048, fd);
}
fclose(fd);
burn_src->free_data(burn_src);
free(burn_src);
iso_image_unref(image);
iso_finish();
return 0;
}

View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2007 Vreixo Formoso
*
* This file is part of the libisofs project; 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. See COPYING file for details.
*/
#include <stdio.h>
#include <stdlib.h>
#include "libisofs.h"
/*
* Little test program that extracts a file form a given ISO image.
* Outputs file contents to stdout!
*/
int main(int argc, char **argv)
{
int res;
IsoFilesystem *fs;
IsoFileSource *file;
struct stat info;
IsoDataSource *src;
IsoReadOpts *opts;
if (argc != 3) {
fprintf(stderr, "Usage: isocat /path/to/image /path/to/file\n");
return 1;
}
res = iso_init();
if (res < 0) {
fprintf(stderr, "Can't init libisofs\n");
return 1;
}
res = iso_data_source_new_from_file(argv[1], &src);
if (res < 0) {
fprintf(stderr, "Error creating data source\n");
return 1;
}
res = iso_read_opts_new(&opts, 0);
if (res < 0) {
fprintf(stderr, "Error creating read options\n");
return 1;
}
res = iso_image_filesystem_new(src, opts, 1, &fs);
if (res < 0) {
fprintf(stderr, "Error creating filesystem\n");
return 1;
}
iso_read_opts_free(opts);
res = fs->get_by_path(fs, argv[2], &file);
if (res < 0) {
fprintf(stderr, "Can't get file, err = %d\n", res);
return 1;
}
res = iso_file_source_lstat(file, &info);
if (res < 0) {
fprintf(stderr, "Can't stat file, err = %d\n", res);
return 1;
}
if (S_ISDIR(info.st_mode)) {
fprintf(stderr, "Path refers to a directory!!\n");
return 1;
} else {
char buf[1024];
res = iso_file_source_open(file);
if (res < 0) {
fprintf(stderr, "Can't open file, err = %d\n", res);
return 1;
}
while ((res = iso_file_source_read(file, buf, 1024)) > 0) {
fwrite(buf, 1, res, stdout);
}
if (res < 0) {
fprintf(stderr, "Error reading, err = %d\n", res);
return 1;
}
iso_file_source_close(file);
}
iso_file_source_unref(file);
iso_filesystem_unref(fs);
iso_data_source_unref(src);
iso_finish();
return 0;
}

View File

@ -0,0 +1,257 @@
/*
* Very simple program to show how to grow an iso image.
*/
#include "libisofs.h"
#include "libburn/libburn.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <err.h>
static IsoDataSource *libburn_data_source_new(struct burn_drive *d);
void usage(char **argv)
{
printf("%s DISC DIRECTORY\n", argv[0]);
}
int main(int argc, char **argv)
{
int result;
IsoImage *image;
IsoDataSource *src;
struct burn_source *burn_src;
struct burn_drive_info *drives;
struct burn_drive *drive;
unsigned char buf[32 * 2048];
IsoWriteOpts *opts;
int ret = 0;
IsoReadImageFeatures *features;
uint32_t ms_block;
IsoReadOpts *ropts;
if (argc < 3) {
usage(argv);
return 1;
}
iso_init();
iso_set_msgs_severities("NEVER", "ALL", "");
/* create the image context */
result = iso_image_new("volume_id", &image);
if (result < 0) {
printf ("Error creating image\n");
return 1;
}
iso_tree_set_follow_symlinks(image, 0);
iso_tree_set_ignore_hidden(image, 0);
if (!burn_initialize()) {
err(1, "Can't init libburn");
}
burn_msgs_set_severities("NEVER", "SORRY", "libburner : ");
if (burn_drive_scan_and_grab(&drives, argv[1], 0) != 1) {
err(1, "Can't open device. Are you sure it is a valid drive?\n");
}
drive = drives[0].drive;
#ifdef ISO_GROW_CHECK_MEDIA
{
/* some check before going on */
enum burn_disc_status state;
int pno;
char name[80];
state = burn_disc_get_status(drive);
burn_disc_get_profile(drive, &pno, name);
/*
* my drives report BURN_DISC_BLANK on a DVD+RW with data.
* is that correct?
*/
if ( (pno != 0x1a) /*|| (state != BURN_DISC_FULL)*/ ) {
printf("You need to insert a DVD+RW with some data.\n");
printf("Profile: %x, state: %d.\n", pno, state);
ret = 1;
goto exit_cleanup;
}
}
#endif
/* create the data source to accesss previous image */
src = libburn_data_source_new(drive);
if (src == NULL) {
printf("Can't create data source.\n");
ret = 1;
goto exit_cleanup;
}
/* import previous image */
ret = iso_read_opts_new(&ropts, 0);
if (ret < 0) {
fprintf(stderr, "Error creating read options\n");
return 1;
}
result = iso_image_import(image, src, ropts, &features);
iso_data_source_unref(src);
if (result < 0) {
printf ("Error importing previous session %d\n", result);
return 1;
}
iso_read_opts_free(ropts);
iso_tree_set_replace_mode(image, ISO_REPLACE_IF_NEWER);
/* add new dir */
result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[2]);
if (result < 0) {
printf ("Error adding directory %d\n", result);
return 1;
}
/* generate a multisession image with new contents */
result = iso_write_opts_new(&opts, 1);
if (result < 0) {
printf("Cant create write opts, error %d\n", result);
return 1;
}
/* round up to 32kb aligment = 16 block */
ms_block = ((iso_read_image_features_get_size(features) + 15) / 16 ) * 16;
iso_write_opts_set_ms_block(opts, ms_block);
iso_write_opts_set_appendable(opts, 1);
iso_write_opts_set_overwrite_buf(opts, buf);
iso_read_image_features_destroy(features);
result = iso_image_create_burn_source(image, opts, &burn_src);
if (result < 0) {
printf("Cant create image, error %d\n", result);
return 1;
}
iso_write_opts_free(opts);
/* a. write the new image */
printf("Adding new data...\n");
{
struct burn_disc *target_disc;
struct burn_session *session;
struct burn_write_opts *burn_options;
struct burn_track *track;
struct burn_progress progress;
char reasons[BURN_REASONS_LEN];
target_disc = burn_disc_create();
session = burn_session_create();
burn_disc_add_session(target_disc, session, BURN_POS_END);
track = burn_track_create();
burn_track_set_source(track, burn_src);
burn_session_add_track(session, track, BURN_POS_END);
burn_options = burn_write_opts_new(drive);
burn_drive_set_speed(drive, 0, 0);
burn_write_opts_set_underrun_proof(burn_options, 1);
/* mmm, check for 32K alignment? */
burn_write_opts_set_start_byte(burn_options, ms_block * 2048);
if (burn_write_opts_auto_write_type(burn_options, target_disc,
reasons, 0) == BURN_WRITE_NONE) {
printf("Failed to find a suitable write mode:\n%s\n", reasons);
ret = 1;
goto exit_cleanup;
}
/* ok, write the new track */
burn_disc_write(burn_options, target_disc);
burn_write_opts_free(burn_options);
while (burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING)
usleep(1002);
while (burn_drive_get_status(drive, &progress) != BURN_DRIVE_IDLE) {
printf("Writing: sector %d of %d\n", progress.sector, progress.sectors);
sleep(1);
}
}
/* b. write the new vol desc */
printf("Writing the new vol desc...\n");
ret = burn_random_access_write(drive, 0, (char*)buf, 32*2048, 0);
if (ret != 1) {
printf("Ups, new vol desc write failed\n");
}
iso_image_unref(image);
exit_cleanup:;
burn_drive_release(drives[0].drive, 0);
burn_finish();
iso_finish();
exit(ret);
}
static int
libburn_ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
{
struct burn_drive *d;
off_t data_count;
d = (struct burn_drive*)src->data;
if ( burn_read_data(d, (off_t) lba * (off_t) 2048, (char*)buffer,
2048, &data_count, 0) < 0 ) {
return -1; /* error */
}
return 1;
}
static
int libburn_ds_open(IsoDataSource *src)
{
/* nothing to do, device is always opened */
return 1;
}
static
int libburn_ds_close(IsoDataSource *src)
{
/* nothing to do, device is always opened */
return 1;
}
static void
libburn_ds_free_data(IsoDataSource *src)
{
/* nothing to do */
}
static IsoDataSource *
libburn_data_source_new(struct burn_drive *d)
{
IsoDataSource *ret;
ret = malloc(sizeof(IsoDataSource));
ret->version = 0;
ret->refcount = 1;
ret->read_block = libburn_ds_read_block;
ret->open = libburn_ds_open;
ret->close = libburn_ds_close;
ret->free_data = libburn_ds_free_data;
ret->data = d;
return ret;
}

View File

@ -0,0 +1,109 @@
/*
* Little program to show how to modify an iso image.
*/
#include "libisofs.h"
#include "libburn/libburn.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <err.h>
void usage(char **argv)
{
printf("%s [OPTIONS] IMAGE DIRECTORY OUTPUT\n", argv[0]);
}
int main(int argc, char **argv)
{
int result;
IsoImage *image;
IsoDataSource *src;
struct burn_source *burn_src;
unsigned char buf[2048];
FILE *fd;
IsoWriteOpts *opts;
IsoReadOpts *ropts;
if (argc < 4) {
usage(argv);
return 1;
}
fd = fopen(argv[3], "w");
if (!fd) {
err(1, "error opening output file");
}
iso_init();
iso_set_msgs_severities("NEVER", "ALL", "");
/* create the data source to accesss previous image */
result = iso_data_source_new_from_file(argv[1], &src);
if (result < 0) {
printf ("Error creating data source\n");
return 1;
}
/* create the image context */
result = iso_image_new("volume_id", &image);
if (result < 0) {
printf ("Error creating image\n");
return 1;
}
iso_tree_set_follow_symlinks(image, 0);
iso_tree_set_ignore_hidden(image, 0);
/* import previous image */
result = iso_read_opts_new(&ropts, 0);
if (result < 0) {
fprintf(stderr, "Error creating read options\n");
return 1;
}
result = iso_image_import(image, src, ropts, NULL);
iso_read_opts_free(ropts);
iso_data_source_unref(src);
if (result < 0) {
printf ("Error importing previous session %d\n", result);
return 1;
}
/* add new dir */
result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[2]);
if (result < 0) {
printf ("Error adding directory %d\n", result);
return 1;
}
/* generate a new image with both previous and added contents */
result = iso_write_opts_new(&opts, 1);
if (result < 0) {
printf("Cant create write opts, error %d\n", result);
return 1;
}
/* for isolinux: iso_write_opts_set_allow_full_ascii(opts, 1); */
result = iso_image_create_burn_source(image, opts, &burn_src);
if (result < 0) {
printf ("Cant create image, error %d\n", result);
return 1;
}
iso_write_opts_free(opts);
while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
fwrite(buf, 1, 2048, fd);
}
fclose(fd);
burn_src->free_data(burn_src);
free(burn_src);
iso_image_unref(image);
iso_finish();
return 0;
}

View File

@ -0,0 +1,114 @@
/*
* Little program to show how to create a multisession iso image.
*/
#include "libisofs.h"
#include "libburn/libburn.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <err.h>
void usage(char **argv)
{
printf("%s LSS NWA DISC DIRECTORY OUTPUT\n", argv[0]);
}
int main(int argc, char **argv)
{
int result;
IsoImage *image;
IsoDataSource *src;
struct burn_source *burn_src;
unsigned char buf[2048];
FILE *fd;
IsoWriteOpts *opts;
IsoReadOpts *ropts;
uint32_t ms_block;
if (argc < 6) {
usage(argv);
return 1;
}
fd = fopen(argv[5], "w");
if (!fd) {
err(1, "error opening output file");
}
iso_init();
iso_set_msgs_severities("NEVER", "ALL", "");
/* create the data source to accesss previous image */
result = iso_data_source_new_from_file(argv[3], &src);
if (result < 0) {
printf ("Error creating data source\n");
return 1;
}
/* create the image context */
result = iso_image_new("volume_id", &image);
if (result < 0) {
printf ("Error creating image\n");
return 1;
}
iso_tree_set_follow_symlinks(image, 0);
iso_tree_set_ignore_hidden(image, 0);
/* import previous image */
result = iso_read_opts_new(&ropts, 0);
if (result < 0) {
fprintf(stderr, "Error creating read options\n");
return 1;
}
iso_read_opts_set_start_block(ropts, atoi(argv[1]));
result = iso_image_import(image, src, ropts, NULL);
iso_read_opts_free(ropts);
iso_data_source_unref(src);
if (result < 0) {
printf ("Error importing previous session %d\n", result);
return 1;
}
/* add new dir */
result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[4]);
if (result < 0) {
printf ("Error adding directory %d\n", result);
return 1;
}
/* generate a multisession image with new contents */
result = iso_write_opts_new(&opts, 1);
if (result < 0) {
printf("Cant create write opts, error %d\n", result);
return 1;
}
/* round up to 32kb aligment = 16 block */
ms_block = atoi(argv[2]);
iso_write_opts_set_ms_block(opts, ms_block);
iso_write_opts_set_appendable(opts, 1);
result = iso_image_create_burn_source(image, opts, &burn_src);
if (result < 0) {
printf ("Cant create image, error %d\n", result);
return 1;
}
iso_write_opts_free(opts);
while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
fwrite(buf, 1, 2048, fd);
}
fclose(fd);
burn_src->free_data(burn_src);
free(burn_src);
iso_image_unref(image);
iso_finish();
return 0;
}

View File

@ -0,0 +1,167 @@
/*
* Little program to output the contents of an iso image.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "libisofs.h"
static void
print_permissions(mode_t mode)
{
char perm[10];
//TODO suid, sticky...
perm[9] = '\0';
perm[8] = mode & S_IXOTH ? 'x' : '-';
perm[7] = mode & S_IWOTH ? 'w' : '-';
perm[6] = mode & S_IROTH ? 'r' : '-';
perm[5] = mode & S_IXGRP ? 'x' : '-';
perm[4] = mode & S_IWGRP ? 'w' : '-';
perm[3] = mode & S_IRGRP ? 'r' : '-';
perm[2] = mode & S_IXUSR ? 'x' : '-';
perm[1] = mode & S_IWUSR ? 'w' : '-';
perm[0] = mode & S_IRUSR ? 'r' : '-';
printf(" %s ",perm);
}
static void
print_type(mode_t mode)
{
switch(mode & S_IFMT) {
case S_IFSOCK: printf("[S] "); break;
case S_IFLNK: printf("[L] "); break;
case S_IFREG: printf("[R] "); break;
case S_IFBLK: printf("[B] "); break;
case S_IFDIR: printf("[D] "); break;
case S_IFIFO: printf("[F] "); break;
}
}
static void
print_file_src(IsoFileSource *file)
{
struct stat info;
char *name;
iso_file_source_lstat(file, &info);
print_type(info.st_mode);
print_permissions(info.st_mode);
//printf(" {%ld,%ld} ", (long)info.st_dev, (long)info.st_ino);
name = iso_file_source_get_name(file);
printf(" %s", name);
free(name);
if (S_ISLNK(info.st_mode)) {
char buf[PATH_MAX];
iso_file_source_readlink(file, buf, PATH_MAX);
printf(" -> %s\n", buf);
}
printf("\n");
}
static void
print_dir(IsoFileSource *dir, int level)
{
int ret, i;
IsoFileSource *file;
struct stat info;
char *sp = alloca(level * 2 + 1);
for (i = 0; i < level * 2; i += 2) {
sp[i] = '|';
sp[i+1] = ' ';
}
sp[level * 2-1] = '-';
sp[level * 2] = '\0';
ret = iso_file_source_open(dir);
if (ret < 0) {
printf ("Can't open dir %d\n", ret);
}
while ((ret = iso_file_source_readdir(dir, &file)) == 1) {
printf("%s", sp);
print_file_src(file);
ret = iso_file_source_lstat(file, &info);
if (ret < 0) {
break;
}
if (S_ISDIR(info.st_mode)) {
print_dir(file, level + 1);
}
iso_file_source_unref(file);
}
iso_file_source_close(dir);
if (ret < 0) {
printf ("Can't print dir\n");
}
}
int main(int argc, char **argv)
{
int result;
IsoImageFilesystem *fs;
IsoDataSource *src;
IsoFileSource *root;
IsoReadOpts *ropts;
if (argc != 2) {
printf ("You need to specify a valid path\n");
return 1;
}
iso_init();
iso_set_msgs_severities("NEVER", "ALL", "");
result = iso_data_source_new_from_file(argv[1], &src);
if (result < 0) {
printf ("Error creating data source\n");
return 1;
}
result = iso_read_opts_new(&ropts, 0);
if (result < 0) {
fprintf(stderr, "Error creating read options\n");
return 1;
}
result = iso_image_filesystem_new(src, ropts, 1, &fs);
iso_read_opts_free(ropts);
if (result < 0) {
printf ("Error creating filesystem\n");
return 1;
}
printf("\nVOLUME INFORMATION\n");
printf("==================\n\n");
printf("Vol. id: %s\n", iso_image_fs_get_volume_id(fs));
printf("Publisher: %s\n", iso_image_fs_get_publisher_id(fs));
printf("Data preparer: %s\n", iso_image_fs_get_data_preparer_id(fs));
printf("System: %s\n", iso_image_fs_get_system_id(fs));
printf("Application: %s\n", iso_image_fs_get_application_id(fs));
printf("Copyright: %s\n", iso_image_fs_get_copyright_file_id(fs));
printf("Abstract: %s\n", iso_image_fs_get_abstract_file_id(fs));
printf("Biblio: %s\n", iso_image_fs_get_biblio_file_id(fs));
printf("\nDIRECTORY TREE\n");
printf("==============\n");
result = fs->get_root(fs, &root);
if (result < 0) {
printf ("Can't get root %d\n", result);
return 1;
}
//print_file_src(root);
print_dir(root, 0);
iso_file_source_unref(root);
fs->close(fs);
iso_filesystem_unref((IsoFilesystem*)fs);
iso_data_source_unref(src);
iso_finish();
return 0;
}

View File

@ -0,0 +1,130 @@
/*
* Copyright (c) 2007 Vreixo Formoso
*
* This file is part of the libisofs project; 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. See COPYING file for details.
*/
#include "libisofs.h"
#include "fsource.h"
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
/*
* Little test program to test filesystem implementations.
*
*/
static void
print_permissions(mode_t mode)
{
char perm[10];
//TODO suid, sticky...
perm[9] = '\0';
perm[8] = mode & S_IXOTH ? 'x' : '-';
perm[7] = mode & S_IWOTH ? 'w' : '-';
perm[6] = mode & S_IROTH ? 'r' : '-';
perm[5] = mode & S_IXGRP ? 'x' : '-';
perm[4] = mode & S_IWGRP ? 'w' : '-';
perm[3] = mode & S_IRGRP ? 'r' : '-';
perm[2] = mode & S_IXUSR ? 'x' : '-';
perm[1] = mode & S_IWUSR ? 'w' : '-';
perm[0] = mode & S_IRUSR ? 'r' : '-';
printf(" %s ",perm);
}
static void
print_type(mode_t mode)
{
switch(mode & S_IFMT) {
case S_IFSOCK: printf("[S] "); break;
case S_IFLNK: printf("[L] "); break;
case S_IFREG: printf("[R] "); break;
case S_IFBLK: printf("[B] "); break;
case S_IFDIR: printf("[D] "); break;
case S_IFIFO: printf("[F] "); break;
}
}
static void
print_file_src(IsoFileSource *file)
{
struct stat info;
char *name;
iso_file_source_lstat(file, &info);
print_type(info.st_mode);
print_permissions(info.st_mode);
printf(" {%ld,%ld} ", (long)info.st_dev, (long)info.st_ino);
name = iso_file_source_get_name(file);
printf(" %s", name);
free(name);
if (S_ISLNK(info.st_mode)) {
char buf[PATH_MAX];
iso_file_source_readlink(file, buf, PATH_MAX);
printf(" -> %s\n", buf);
}
printf("\n");
}
int main(int argc, char **argv)
{
int res;
IsoFilesystem *fs;
IsoFileSource *dir;
IsoFileSource *file;
struct stat info;
if (argc != 2) {
fprintf(stderr, "Usage: lsl /path/to/file\n");
return 1;
}
/* create filesystem object */
res = iso_local_filesystem_new(&fs);
if (res < 0) {
fprintf(stderr, "Can't get local fs object, err = %d\n", res);
return 1;
}
res = fs->get_by_path(fs, argv[1], &dir);
if (res < 0) {
fprintf(stderr, "Can't get file, err = %d\n", res);
return 1;
}
res = iso_file_source_lstat(dir, &info);
if (res < 0) {
fprintf(stderr, "Can't stat file, err = %d\n", res);
return 1;
}
if (S_ISDIR(info.st_mode)) {
res = iso_file_source_open(dir);
if (res < 0) {
fprintf(stderr, "Can't open file, err = %d\n", res);
return 1;
}
while (iso_file_source_readdir(dir, &file) == 1) {
print_file_src(file);
iso_file_source_unref(file);
}
res = iso_file_source_close(dir);
if (res < 0) {
fprintf(stderr, "Can't close file, err = %d\n", res);
return 1;
}
} else {
print_file_src(dir);
}
iso_file_source_unref(dir);
iso_filesystem_unref(fs);
return 0;
}

View File

@ -0,0 +1,107 @@
/*
* Little program that import a directory and prints the resulting iso tree.
*/
#include "libisofs.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
static void
print_permissions(mode_t mode)
{
char perm[10];
//TODO suid, sticky...
perm[9] = '\0';
perm[8] = mode & S_IXOTH ? 'x' : '-';
perm[7] = mode & S_IWOTH ? 'w' : '-';
perm[6] = mode & S_IROTH ? 'r' : '-';
perm[5] = mode & S_IXGRP ? 'x' : '-';
perm[4] = mode & S_IWGRP ? 'w' : '-';
perm[3] = mode & S_IRGRP ? 'r' : '-';
perm[2] = mode & S_IXUSR ? 'x' : '-';
perm[1] = mode & S_IWUSR ? 'w' : '-';
perm[0] = mode & S_IRUSR ? 'r' : '-';
printf("[%s]",perm);
}
static void
print_dir(IsoDir *dir, int level)
{
int i;
IsoDirIter *iter;
IsoNode *node;
char *sp = alloca(level * 2 + 1);
for (i = 0; i < level * 2; i += 2) {
sp[i] = '|';
sp[i+1] = ' ';
}
sp[level * 2-1] = '-';
sp[level * 2] = '\0';
iso_dir_get_children(dir, &iter);
while (iso_dir_iter_next(iter, &node) == 1) {
if (ISO_NODE_IS_DIR(node)) {
printf("%s+[D] ", sp);
print_permissions(iso_node_get_permissions(node));
printf(" %s\n", iso_node_get_name(node));
print_dir(ISO_DIR(node), level+1);
} else if (ISO_NODE_IS_FILE(node)) {
printf("%s-[F] ", sp);
print_permissions(iso_node_get_permissions(node));
printf(" %s\n", iso_node_get_name(node) );
} else if (ISO_NODE_IS_SYMLINK(node)) {
printf("%s-[L] ", sp);
print_permissions(iso_node_get_permissions(node));
printf(" %s -> %s \n", iso_node_get_name(node),
iso_symlink_get_dest(ISO_SYMLINK(node)) );
} else {
printf("%s-[C] ", sp);
print_permissions(iso_node_get_permissions(node));
printf(" %s\n", iso_node_get_name(node) );
}
}
iso_dir_iter_free(iter);
}
int main(int argc, char **argv)
{
int result;
IsoImage *image;
if (argc != 2) {
printf ("You need to specify a valid path\n");
return 1;
}
iso_init();
iso_set_msgs_severities("NEVER", "ALL", "");
result = iso_image_new("volume_id", &image);
if (result < 0) {
printf ("Error creating image\n");
return 1;
}
result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[1]);
if (result < 0) {
printf ("Error adding directory %d\n", result);
return 1;
}
printf("================= IMAGE =================\n");
print_dir(iso_image_get_root(image), 0);
printf("\n\n");
iso_image_unref(image);
iso_finish();
return 0;
}

View File

@ -0,0 +1,506 @@
===============================================================================
LIBISOFS DEVELOPMENT TUTORIAL
===============================================================================
Creation date: 2008-Jan-27
Author: Vreixo Formoso
_______________________________________________________________________________
This is a little tutorial of how to use libisofs library for application
development.
Contents:
---------
1. Introduction
1.1 Library initialization
1.2 Image context
1.3 Error reporting
2. Creating an image
2.1 Image tree manipulation
2.2 Set the write options
2.3 Obtaining a burn_source
3. Image growing and modification
3.1 Growing vs Modification
3.2 Image import
3.3 Generating a new image
4. Bootable images
5. Advanced features
-------------------------------------------------------------------------------
1. Introduction
-------------------------------------------------------------------------------
[TODO some lines about refcounts]
-------------------------------------------------------------------------------
1.1. Library initialization
Before any usage of the library, you have to call
iso_init()
in the same way, when you have finished using the library, you should call
iso_finish()
to free all resources reserved by the library.
-------------------------------------------------------------------------------
1.2. Image context
Libisofs is image-oriented, the core of libisofs usage is the IsoImage object.
Thus, the first you need to do is to get your own IsoImage object:
IsoImage *my_image;
iso_image_new("NEW DISC", &my_image);
An IsoImage is a context for image creation. It holds the files that will be
added to image, other related information and several options to customize
the behavior of libisofs when working with such Image. i.e., an IsoImage is
a context for libisofs operations. As such, you can work with several image
contexts at a time.
-------------------------------------------------------------------------------
1.3. Error reporting
In libisofs error reporting is done in two ways: with the return value of
the functions and with the message queue.
Error codes are negative numbers, defined in "libisofs.h" header. An
error code is associated with a given severity, either "DEBUG", "UPDATE",
"NOTE", "HINT", "WARNING", "SORRY", "FAILURE" and "FATAL". For the meaning
of each severity take a look at private header "libiso_msgs.h". Errors
reported by function return value are always "FAILURE" or "FATAL". Other kind
of errors are only reported with the message queue. You can get the severity
of any error message with iso_error_get_severity() function.
First of all, most libisofs functions return an integer. If such integer is
a negative number, it means the function has returned an error. The error code
and its severity is encoded in the return value (take a look at error codes in
libisofs.h header).
Additionally, libisofs reports most of its errors in a message queue. Error
messages on that queue can be printed directly to stderr or programmatically
retrieved. First of all, you should set the severity threshold over which an
error is printed or enqueued, with function:
iso_set_msgs_severities()
Errors enqueued can be retrieved with function:
iso_obtain_msgs()
Together with the code error, a text message and its severity, this function
also returns the image id. This is an identifier that uniquely identifies a
given image context. You can get the identifier of each IsoImage with the
iso_image_get_msg_id()
and that way distinguish what image has issued the message.
-------------------------------------------------------------------------------
2. Creating an Image
-------------------------------------------------------------------------------
An image is built from a set of files that you want to store together in an
ISO-9660 volume. We call the "iso tree" to the file hierarchy that will be
written to image. The image context, IsoImage, holds that tree, together with
configuration options and other properties of the image, that provide info
about the volume (such as the identifier, author, etc...).
All configuration options and volume properties are set by its corresponding
setters (iso_image_set_volset_id(), iso_image_set_publisher_id()...)
To create an image, you have to follow the following steps:
* Obtain the image context.
See "1.2 Image context" for details of how to obtain the IsoImage.
* Set the desired properties
* Prepare the iso tree with the files you want to add to image.
See "2.1 Image tree manipulation" for details
* Select the options for image generation.
See "2.2 Set the write options"
* Get the burn_source used to actually write the image.
-------------------------------------------------------------------------------
2.1 Image tree manipulation
libisofs maintains in memory a file tree (usually called the iso tree), that
represents the files and directories that will be written later to image. You
are allowed to make whatever changes you want to that tree, just like you do
to any "real" filesystem, before actually write it to image.
Unlike other ISO-9660 mastering tools, you have full control over the file
hierarchy that will be written to image, via the libisofs API. You can add
new files, create any file in image, change its name, attributes, etc The iso
tree behaves just like any other POSIX filesystem.
The root of the iso tree is created automatically when the IsoImage is
allocated, and you can't replace it. To get a reference to it you can use the
function:
iso_image_get_root()
* Iso tree objects
Each file in the image or iso tree is represented by an IsoNode instance. In
the same way a POSIX filesystem has several file types (regular files,
directories, symlinks...), the IsoNode has several subtypes:
IsoNode
|
---------------------------------
| | | |
IsoDir IsoFile IsoSymlink IsoSpecial
where
- IsoDir represents a directory
- IsoFile represents a regular file
- IsoSymlink represents a symbolic linke
- IsoSpecial represents any other POSIX file, i.e. block and character
devices, FIFOs, sockets.
You can obtain the concrete type of an IsoNode with the iso_node_get_type()
function.
Many libisofs functions take or return an IsoNode. Many others, however,
require an specific type. You can safety cast any subtype to an IsoNode
object. In the same way, after ensuring you are dealing with the correct
subtype, you can downcast a given IsoNode to the specific subtype.
IsoDir *dir;
IsoNode *node;
node = (IsoNode*) dir;
if (iso_node_get_type(node) == LIBISO_DIR) {
dir = (IsoDir*) node;
...
}
or with the provided macros:
IsoDir *dir;
IsoNode *node;
node = ISO_NODE(dir);
if (ISO_NODE_IS_DIR(node)) {
dir = ISO_DIR(node);
...
}
* Adding files to the image
Files can be added to the image or iso tree either as new files or as files
from the filesystem.
In the first case, files are created directly on the image. They do not
correspond to any file in the filesystem. Provided functions are:
- iso_tree_add_new_dir()
- iso_tree_add_new_symlink()
- iso_tree_add_new_special()
On the other side, you can add local files to the image, either with the
iso_tree_add_node()
or with
iso_tree_add_dir_rec().
The first is intended to add a single file, while the last can be used to add,
recursively, a full directory (see below for details).
It is important to note that libisofs doesn't store any kind of link between
the IsoNode and the filesystem file it was created from. The above functions
just initialize a newly created IsoNode with the attributes of a given file in
the filesystem. After that, you can move the original file, change its
attributes or even delete it. The IsoNode in the image tree remains with the
original attributes. One exception to this rule are the contents of a regular
file. Libisofs does not make any copy of those contents until they're actually
written to image. Thus, you shouldn't modify, move or delete regular files
after adding them to the IsoImage.
* Recursive directory addition.
One common use case is to add a local directory to the image. While this can
be done with iso_tree_add_node(), handling the addition of directory children
in the application, libisofs provides a function suitable for this case:
iso_tree_add_dir_rec()
that takes care of adding all files inside a directory, recursing on directory
children. By default, this function adds all children. However, it is usual
that you don't want really this. For example, you may want to exclude some
kind of files (backup files, application sockets,...). Libisofs provides
several functions to customize the behavior of that function:
- iso_tree_set_follow_symlinks()
- iso_tree_set_ignore_hidden()
- iso_tree_set_ignore_special()
- iso_tree_add_exclude()
* Operations on iso tree
[TODO briefly explain how to add node, change attributes, ...]
* Replace mode
[TODO]
-------------------------------------------------------------------------------
2.2 Set the write options
Once you have prepared the iso tree, it is time to select the options for the
image writing.
These options affect the characteristics of the filesystem to create in the
image, but also can control how libisofs generates the image.
First of all you have to get an instance of IsoWriteOpts, with the function
iso_write_opts_new()
The several options available can be classified in:
- Extensions to add to the ISO-9660 image:
iso_write_opts_set_rockridge()
iso_write_opts_set_joliet()
iso_write_opts_set_iso1999()
RockRidge is highly recommended, in fact you should use it in all image. Joliet
is needed if you want to use your images in Windows system. Nowadays,
ISO-9660:1999 is no much useful, so in most cases you don't want such
extension.
- ISO-9660 options:
iso_write_opts_set_iso_level()
iso_write_opts_set_omit_version_numbers()
iso_write_opts_set_allow_deep_paths()
iso_write_opts_set_allow_longer_paths()
iso_write_opts_set_max_37_char_filenames()
iso_write_opts_set_no_force_dots()
iso_write_opts_set_allow_lowercase()
iso_write_opts_set_allow_full_ascii()
These control the options for the ISO-9660 filesystem. In most cases you won't
care about them, as it is the RockRidge or Joliet extensions what determine the
properties of the files once the image is mounted.
- File attributes options
iso_write_opts_set_replace_mode()
iso_write_opts_set_default_dir_mode()
iso_write_opts_set_default_file_mode()
iso_write_opts_set_default_uid()
iso_write_opts_set_default_gid()
iso_write_opts_set_replace_timestamps()
iso_write_opts_set_default_timestamp()
iso_write_opts_set_always_gmt()
They allow to set default attributes for files in image, despite of the real
attributes of the file on the local filesystem.
-------------------------------------------------------------------------------
2.3 Obtaining a burn_source
Finally, you get the burn_source used to write the image with the function:
iso_image_create_burn_source()
The returned burn_source is suitable for using with libburn, to directly burn
the image to a disc. Alternatively, you can use burn_source read() to get
the image contents (for example, to write them to a file, pipe...).
Before creating the burn_source, libisofs computes the size of the image, so
the get_size() function of the burn_source always returns the final image
size. It also starts a writing thread. All the operations needed to generate
the image are done by this thread, including read the original files contents.
The image is writing to a FIFO buffer, from which the burn_source will read.
The size of the buffer can be set in advanced with a property of the
IsoWriteOpts struct:
iso_write_opts_set_fifo_size()
You can get the state of the buffer in any moment, with the function:
iso_ring_buffer_get_status()
You can also cancel the writer thread at any time, with the cancel() function
of the burn_source.
-------------------------------------------------------------------------------
3. Image growing and modification
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
3.1 Growing vs Modification
Libisofs is not restricted only to create new images. It can also be used to
modify existing images. It supports two kind of image modifications, that we
have called image growing and image modification:
Image modification consists in generating a new image, based on the contents
of an existing image. In this mode, libisofs takes an image, the users modifies
its contents (adding new files, removing files, changing their names...), and
finally libisofs generates a completely new image.
On the other side, image growing is similar, with the difference that the new
image is dependent on the other, i.e., it refers to files of the other image.
Thus, it can't be mounted without the old image. The purpose of this kind of
images is to increment or add files to a multisession disc. The new image only
contains the new files. Old files are just references to the old image blocks.
The advantage of the growing approach is that the generated image is smaller,
as only the new files are written. This mode is suitable when you just want to
add some files to a very big image, or when dealing with write-once media, such
as CD-R. Both the time and space needed for the modification is much less than
with normal image modify.
The main problem of growing is that the new image needs to be recorded together
with the old image, in order to be mountable. The total size of the image
(old + new) is bigger (even much bigger) than a completely new image. So, if
you plan to distribute an image on Internet, or burn it to a disc, generate a
completely new image is usually a better alternative.
To be able to mount a grown image, the OS needs to now you have appended new
data to the original image. In multisession media (such as CD-R), the new data
is appended as a new session, so the OS can identify this and mount the image
propertly. However, when dealing with non-multisession media (such as DVD+RW)
or plain .iso files, the new data is just appended at the end of the old image,
and the OS has no way to know that the appended data is in fact a "new
session". The method introduced by Andy Polyakov in growisofs can be used in
those cases. It consists in overwrite the volume descriptors of the old image
with a new ones that refer to the newly appended contents.
-------------------------------------------------------------------------------
3.2 Image import
The first thing you need to do in order to modify or grow an image is to import
it, with the function:
iso_image_import()
It takes several arguments.
First, the image context, an IsoImage previously obtained with iso_image_new().
In most cases you will want to use an empty image. However, if you have already
added files to the image, they will be removed and replaced with the contents
of the image being imported.
The second parameter is an IsoDataSource instance. It abstracts the original
image, and it is used by libisofs to access its contents. You are free to
implement your own data source to access image contents. However, libisofs has
a simple implementation suitable for reading images on the local filesystem,
that can be used for import both .iso files and inserted media, via the block
device and POSIX functions. You can get it with
iso_data_source_new_from_file()
The third parameter of iso_image_import() is a pointer to an IsoReadOpts
struct. It holds the options for image reading. You get it with:
iso_read_opts_new()
and after calling iso_image_import() you should free it with
iso_read_opts_free()
Some options are related to select what extensions to read. Default options
are suitable for most users.
iso_read_opts_set_no_rockridge()
iso_read_opts_set_no_joliet()
iso_read_opts_set_no_iso1999()
iso_read_opts_set_preferjoliet()
If RockRidge extensions are not present, many files attributes can't be
obtained. In those cases libisofs uses default values. You have options to
configure what default values to use.
iso_read_opts_set_default_uid()
iso_read_opts_set_default_gid()
iso_read_opts_set_default_permissions()
If the original image has been created in another system with a different
charset, you may want to use:
iso_read_opts_set_input_charset()
to specify the encoding of the file names on image.
Finally, to import multisession images, you should tell libisofs that it must
read the last session. For that, you must set the block where the last session
starts:
iso_read_opts_set_start_block()
The last parameter for iso_image_import(), optional, is a pointer that will
be filled with a library-allocated IsoReadImageFeatures, that lets you access
some information about the image: size, extensions used,...
[TODO: explain that iso_image_import uses dir rec options]
-------------------------------------------------------------------------------
3.3 Generating a new image
After importing the image, the old image tree gets loaded. You are free to
make any changes to it: add new files, remove files, change names or
attributes... Refer to "2.1 Image tree manipulation" for details.
When it is ready, you can now create the new image. The process is the same as
explained in "2.2 Set the write options" and "2.3 Obtaining a burn_source".
However, there are some write options that should be taken into account.
First of all, you must select whether you want to grow or modify the image
(read "3.1 Growing vs Modification" for details). You must call
iso_write_opts_set_appendable()
An appendable image leads to image growing, and a non-appendable image leads
to a completelly new image (modification). An appendable image will be appended
after the old image (in a new session, for example). Thus, in those cases, the
first block of the image is not 0. You should set the correct lba of the first
block with:
iso_write_opts_set_ms_block()
That is usually the "Next Writable Address" on a multisession media, and a
value slightly greater than the old image size on .iso files or DVD+RW media.
You can obtain the old image size with the iso_read_image_features_get_size()
function.
In this last case (i.e., on a non multisession media), you will need to
overwrite the volume descriptors of the old image with the new ones. To do
this you need:
- Allocate a buffer of at least 64 KiBs.
- Initialize it with the first 64 KiBs of the original image.
- Pass the buffer to libisofs with the iso_write_opts_set_overwrite_buf()
option.
- After appending the new image, you have to overwrite the first 64 KiBs of
the original image with the new content of the buffer.
-------------------------------------------------------------------------------
4. Bootable images
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
5. Advanced features
-------------------------------------------------------------------------------

View File

@ -0,0 +1,32 @@
= libisofs =
libisofs is a library to create an ISO-9660 filesystem, and supports extensions like RockRidge and Joliet. It is also a full featured ISO-9660 editor, allowing you to modify an ISO image or multisession disc, including file addition/removal, change of file names and attributes, and similar.
The old libisofs.so.5 has been declarated deprecated and frozen, leaving it unmaintained. A full refactoring of the design has been done during the last months, and the next generation libisofs.so.6 of the library will be released in the following days.
== Source Code ==
The code is maintained in a [http://bazaar-vcs.org/ Bazaar] repository at Launchpad (https://launchpad.net/libisofs/). You can download it with:
{{{
$ bzr branch lp:libisofs
}}}
To report any bug or suggest enchantments, [http://libburnia-project.org/register register] yourself and submit a new ticket. Bug and enchantments reports for nglibisofs can be found at http://libburnia-project.org/report/9.
== Usage tutorial ==
Coming soon... For now check [http://codebrowse.launchpad.net/~mario-danic/libisofs/mainline/annotate/metalpain2002%40yahoo.es-20080201154704-xqyzc57vki97iv3y?file_id=tutorial-20080127170757-cwmomu7oz9eh7fcz-1 "doc/Tutorial"] in the source tree.
=== Applications ===
Comming soon:
[http://libburnia-project.org/browser/libisoburn/trunk libisoburn]:
emulates ISO 9660 multi-session on overwriteable media, coordinates libisofs and libburn.
[http://libburnia-project.org/browser/libisoburn/trunk/xorriso/xorriso_eng.html?format=raw xorriso]:
creates, loads, manipulates and writes ISO 9660 filesystem images with Rock Ridge extensions.

View File

@ -0,0 +1,193 @@
FEATURES
========
Contents:
2.0 Operations on image tree
2.1 ECMA-119
2.2 Rock Ridge
2.3 Joliet
2.4 El-Torito
2.5 UDF
2.6 HFS/HFS+
2.7 Others
===============================================================================
2.0 Operations on image tree
-----------------------------
Basic:
- We HAVE TO Support addition of directories
- From filesystem
- From filesystem recursively
- New on image
- We HAVE TO support addition of files
- From local filesystem
- From previous/ms images
- We HAVE TO support addition of other POSIX file types
- From filesystem
- New on image
- Types: symlinks, block/char devices, fifos, sockets...
- We HAVE TO support modification of file names on image
- We HAVE TO support modification of POSIX attributes:
- Uid/Gid
- Permissions (we DON'T HAVE TO support full mode modification,
as we don't want a dir to be changed to a reg file!!)
- Timestamps
- We HAVE TO support deletion of nodes.
- We HAVE TO support iteration of directory tree.
- We WANT TO support direct getting (without iteration) of the number of
nodes in a directory.
Extras:
- We WANT TO support on-the-fly modification of file contents, to
allow things like compression and encryption.
Notes: many operations will need RR extensions to be actually reflected on
the image.
===============================================================================
2.1 ECMA-119
------------
Support for ECMA-119 (ISO-9660) specification.
2.1.1 Creation
--------------
We HAVE TO support creation of new images.
General:
- We HAVE TO support single volume images
- We DON'T NEED TO support multiple volume images.
It seems multiple volume images are not used.
- We HAVE TO support bootable volumes (see 2.4 in this doc)
Conformance:
- We HAVE TO support Level 1 restrictions (ECMA-119 10.1)
- We HAVE TO support Level 2 restrictions (ECMA-119 10.2)
Single Section files have a theoric size limit of 4GB (data length
is a 32-bit number, see ECMA-119 9.1.4). However I think I have
read that only files up to 2GB are supported.
- We MAY support full Level 3 (ECMA-119 10.3)
Multiple file sections are useful to support files higher than
level 2 limit. However, it seems it's a feature not supported in
most O.S. nowadays, so it's not very useful.
- We DON'T WANT TO support files recording in interleaved mode
(ECMA-119 6.4.3)
It seems a feature that it's not used.
- We DON'T WANT TO support associated files (ECMA-119 6.5.4)
What is that? Is it used?
- We DON'T WANT TO support Volume Partitions (ECMA-119 8.6)
What is that? Is it used?
- We DON'T WANT TO support extended attribute records (ECMA-119 9.5)
It seems an unused feature. RR is a better alternative.
- We DON'T NEED TO support file versions other than 1.
Restrictions:
- We HAVE TO provide a way to relax iso restrictions related to
filenames, allowing:
- Higher filename length, up to 37 chars (ECMA-119 7.5.1/7.6.3)
- Omit version number (ECMA-119 7.5.1)
- Directory hierarchy deeper than 8 levels / 255 path length
(ECMA-119 6.8.2.1)
- More characters in filenames, not only d-characters
2.2.2 Reading
-------------
General
- We HAVE TO support the reading of iso images
- We DON'T NEED TO support reading of features we don't support in
creation (see 2.2.1 above)
- We HAVE TO support reading arbitray file contents inside image
2.2.3 Modification/growing
--------------------------
General
- We HAVE TO support creation of new images from the contents of
an existing image
- We HAVE TO support multissession images
- We HAVE TO support growing of images
===============================================================================
2.2 Rock Ridge
--------------
- We HAVE TO support ALL Rock Ridge features, with these exceptions:
- We DON'T NEED TO support SF System User Entry (RRIP 4.1.7), used to
encode sparse files.
- We MIGHT support BACKUP timestamp (RRIP 4.1.6)
- We HAVE TO support any charset in RR filenames, and not only POSIX portable
filename character set (RRIP 3.4.1). Namely, UTF-8 SHOULD BE the default for
RR filenames.
- We MIGHT support Linux specific ZF extension, to allow transparent
compression.
===============================================================================
2.3 Joliet
----------
- We HAVE TO support ALL Joliet features, with these exceptions:
- We DON'T KNOW what to do with UCS-2 conformance level 1 and 2 (scape
sequences '%\@' and '%\C'). What's this???????
- We DON'T KNOW what to do with CD-XA extensions.
===============================================================================
2.4 El-Torito
-------------
- We HAVE TO El-Torito standard with a single boot image.
- We MAY support multiple boot images and boot entry selection.
- El Torito standard is not very clear about how to do that.
- We HAVE TO support both emulation and not emulation mode.
- We HAVE TO support 80x86 platform. We MAY support Power PC and Mac platforms.
- We HAVE TO provide improved support for isolinux boot images, namely patching
features.
- We HAVE TO support El-Torito in ms images.
===============================================================================
2.5 UDF
-------
===============================================================================
2.6 HFS/HFS+
------------
===============================================================================
2.7 Others
----------
- We HAVE TO support sorting of file contents on image
- We HAVE TO support inode caching to prevent the same file to be written
several times into the image
- We DON'T NEED TO support TRANS.TBL files
- We DON'T NEED TO support padding of images
- Padding should be part of the burning process

View File

@ -0,0 +1,193 @@
USE CASES FOR NG LIBISOFS
=========================
3.1 General Operations
======================
3.1.1 Creation of a new image
-----------------------------
Desc: Creation of a new ISO image from files on the local filesystem
Phases:
- User creates a new image context
- User get the root (empty) of the image
- User adds files to the image root (see 3.2.)
- User sets the options for the the new image (extension to use...)
- User gets a burn_source to write the image.
- The burn_source can be used by libburn to write the new image.
3.1.2 Image growing (multisession)
----------------------------------
Desc: An existing image can be grown with new files. New content is added
incrementally. Suitable for multisession. Growing support for
overwritteable media.
Phases:
- Uses reads an existing image to get the image context.
- User get the root of the image
- User modifies the image tree (see 3.2.)
- User sets the options for the the new image (extension to use...)
A required option will be the nwa for the image.
Optionally it can pass a pointer to a 64K buffer, that will be filled
with suitable volume descriptors to be used with overwrieable media.
- User gets a burn_source to write the image.
- The burn_source can be used by libburn to write an image that should be
appended to the previous image.
3.1.3 Image modification
------------------------
Desc: Creation of a new image from the contents of a previous image.
Phases:
- Uses reads an existing image to get the image context.
- User get the root of the image
- User modifies the image tree (see 3.2.)
- User sets the options for the the new image (extension to use...)
- User gets a burn_source to write the image.
- The burn_source can be used by libburn to write the image to another
device or file.
3.2 Tree operations
===================
3.2.1 Addition of contents
--------------------------
All addition operations take a parent dir. The functions check that the
node name is unique among all children. Image context options determine
what to do if a file with such name already exist.
3.2.1.1 Directories
--------------------
- Creation of new directories in image, given a parent dir. and a name.
Attributes are initialized to default values
- Addition of a dir from the filesystem, given a parent.
Dir contents are not added. Name and other attributes taken from
the dir on filesystem
- Recursive addition of a dir, given a parent. Directory contents are
recursivelly added to image.
3.2.1.2 Regular files
----------------------
- Addition of a local filesystem file. Name, attributes and contents to
be written taken from the filesystem file.
- Addition of files from the previous image. Files are automatically
added to the tree when the image is read. Name and attrbs taken from
previous image. When the image has no RR extensions, unavailable atts
are initialized to default values. The contents are only written to
img if we choose image modification.
- Addition of filtered files. Name and atts taken from the local
filesystem. A filter (see 3.3) is applied to the file contents before
written to image.
- Addition of splitted files. Like local filesystem files, but the file
is splitted in several files on a given size. Suitable for big (> 2GB)
files. Name of the splitted files automatically generated.
3.2.1.3 Symbolic links
----------------------
Simbolic links are only written to image if RR extensions are enabled.
- Addition of a simbolic link from local filesystem. Name, atts and
dest of a path are taken from the simbolic link.
- Addition of new link on image to a path. Name and dest specified,
the destination is specified as a path. Attributes initialized to
default values.
- Addition of new link on image to another node. Name and dest
specified, the dest is set to a node previously added to image.
When written, the destination path is computed as the relative path
from the link to the destination node. Attributes initialized to
default values.
3.2.1.4 Special files (block devices, fifos...)
-----------------------------------------------
Special files are only written to image if RR extensions are enabled.
- Addition of special files from filesystem.
- Creation of new special files on image.
3.2.2 Modification of contents
------------------------------
3.2.2.1 Deletion of nodes
-------------------------
- Any node can be deleted. When a dir is remove, all its contents
are also removed.
3.2.2.2 Move
------------
- Any node can be move to another dir..
3.2.2.3 Rename
--------------
- You can change the name of any node
3.2.2.4 Change of POSIX attributes
----------------------------------
- Following POSIX atts can be changed: owner (uid/gid), permissions,
timestamps.
3.2.3 Bootable information
--------------------------
- Addition of a boot image to a volume.
- In most cases, the catalog and the boot image itself is added to the
iso tree.
- Alternatively, user can select to add a hidden images, i.e., images
that don't appear in the iso tree.
- Modification of boot image attributes:
- bootable flag
- load segment
- load size
- Automatic patching of isolinux images. User needs to set whether to apply
this.
- Reading of El-Torito info from multisession images. Modification of its
attributes.
- Removing of El-Torito images
3.2.4 Other operations
----------------------
3.2.4.1 Set file sort weight
-----------------------------
- Any file can have a sort weight, that will determine the order in
which the files are written to image
3.2.4.2 Hidding of nodes
------------------------
- Files can be hidden in the RR or Joliet tree
3.3 Filters
===========
[TODO]
Support for:
- compression filter
- encryption filter
- external process filter

View File

@ -0,0 +1,7 @@
Index
=====
1. Overview
2. Features
3. Design
4. Implementation

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1,821 @@
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.6.0" class="java.beans.XMLDecoder">
<object class="com.horstmann.violet.SequenceDiagramGraph">
<void method="addNode">
<object id="LifelineNode0" class="com.horstmann.violet.ImplicitParameterNode">
<void property="name">
<void property="text">
<string>fs:Filesystem</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>160.0</double>
<double>73.0</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ActivationBarNode0" class="com.horstmann.violet.CallNode">
<void method="addChild">
<object id="LifelineNode1" class="com.horstmann.violet.ImplicitParameterNode">
<void property="name">
<void property="text">
<string>file:FileSource</string>
</void>
</void>
</object>
</void>
<void property="implicitParameter">
<object idref="LifelineNode0"/>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>192.0</double>
<double>209.0</double>
</void>
</object>
</void>
<void method="addNode">
<object idref="LifelineNode1"/>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>274.0</double>
<double>202.0</double>
</void>
</object>
</void>
<void method="addNode">
<object id="LifelineNode2" class="com.horstmann.violet.ImplicitParameterNode">
<void property="name">
<void property="text">
<string>User</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>34.86475730998367</double>
<double>0.0</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ActivationBarNode1" class="com.horstmann.violet.CallNode">
<void method="addChild">
<object idref="LifelineNode0"/>
</void>
<void method="addChild">
<object id="LifelineNode3" class="com.horstmann.violet.ImplicitParameterNode">
<void property="name">
<void property="text">
<string>b:TNBuilder</string>
</void>
</void>
</object>
</void>
<void method="addChild">
<object idref="ActivationBarNode0"/>
</void>
<void method="addChild">
<object id="ActivationBarNode2" class="com.horstmann.violet.CallNode">
<void method="addChild">
<object id="ActivationBarNode3" class="com.horstmann.violet.CallNode">
<void method="addChild">
<object id="ActivationBarNode4" class="com.horstmann.violet.CallNode">
<void property="implicitParameter">
<object idref="LifelineNode1"/>
</void>
</object>
</void>
<void method="addChild">
<object id="LifelineNode4" class="com.horstmann.violet.ImplicitParameterNode">
<void property="name">
<void property="text">
<string>ftn:FileTN</string>
</void>
</void>
</object>
</void>
<void method="addChild">
<object id="ActivationBarNode5" class="com.horstmann.violet.CallNode">
<void property="implicitParameter">
<object idref="LifelineNode4"/>
</void>
</object>
</void>
<void method="addChild">
<object id="LifelineNode5" class="com.horstmann.violet.ImplicitParameterNode">
<void property="name">
<void property="text">
<string>fs:FileStream</string>
</void>
</void>
</object>
</void>
<void method="addChild">
<object id="ActivationBarNode6" class="com.horstmann.violet.CallNode">
<void property="implicitParameter">
<object idref="LifelineNode4"/>
</void>
</object>
</void>
<void property="implicitParameter">
<object idref="LifelineNode3"/>
</void>
</object>
</void>
<void property="implicitParameter">
<object id="LifelineNode6" class="com.horstmann.violet.ImplicitParameterNode">
<void property="name">
<void property="text">
<string>d:DirTreeNode</string>
</void>
</void>
</object>
</void>
</object>
</void>
<void method="addChild">
<object id="ActivationBarNode7" class="com.horstmann.violet.CallNode">
<void property="implicitParameter">
<object idref="LifelineNode4"/>
</void>
</object>
</void>
<void property="implicitParameter">
<object idref="LifelineNode2"/>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>66.86475730998367</double>
<double>80.0</double>
</void>
</object>
</void>
<void method="addNode">
<object idref="LifelineNode3"/>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>539.756828460011</double>
<double>126.0</double>
</void>
</object>
</void>
<void method="addNode">
<object idref="LifelineNode6"/>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>651.0</double>
<double>0.0</double>
</void>
</object>
</void>
<void method="addNode">
<object idref="ActivationBarNode2"/>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>683.0</double>
<double>305.0</double>
</void>
</object>
</void>
<void method="addNode">
<object idref="ActivationBarNode3"/>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>571.756828460011</double>
<double>328.0</double>
</void>
</object>
</void>
<void method="addNode">
<object idref="ActivationBarNode4"/>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>306.0</double>
<double>351.0</double>
</void>
</object>
</void>
<void method="addNode">
<object idref="LifelineNode4"/>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>331.97135964975513</double>
<double>374.0</double>
</void>
</object>
</void>
<void method="addNode">
<object idref="ActivationBarNode5"/>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>363.97135964975513</double>
<double>457.0</double>
</void>
</object>
</void>
<void method="addNode">
<object idref="LifelineNode5"/>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>418.8259109283281</double>
<double>480.0</double>
</void>
</object>
</void>
<void method="addNode">
<object idref="ActivationBarNode6"/>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>363.97135964975513</double>
<double>563.0</double>
</void>
</object>
</void>
<void method="addNode">
<object class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>1. User wants to add a file to a dir in the iso node</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>143.89406091532933</double>
<double>16.868736840587744</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode0" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>2. It creates the source filesystem and the
custom builder</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>317.51829970572646</double>
<double>74.92004824517142</double>
</void>
</object>
</void>
<void method="addNode">
<object id="PointNode0" class="com.horstmann.violet.PointNode">
<void id="Rectangle2D$Double0" property="bounds">
<void method="setRect">
<double>570.819415201306</double>
<double>142.7048538003265</double>
<double>0.0</double>
<double>0.0</double>
</void>
</void>
<void property="bounds">
<object idref="Rectangle2D$Double0"/>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>570.819415201306</double>
<double>142.7048538003265</double>
</void>
</object>
</void>
<void method="addNode">
<object id="PointNode1" class="com.horstmann.violet.PointNode">
<void id="Rectangle2D$Double1" property="bounds">
<void method="setRect">
<double>218.81410916050066</double>
<double>114.16388304026121</double>
<double>0.0</double>
<double>0.0</double>
</void>
</void>
<void property="bounds">
<object idref="Rectangle2D$Double1"/>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>218.81410916050066</double>
<double>114.16388304026121</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode1" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>3. It gets the file from the filesystem
and add it to parent dir</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>379.1320632384976</double>
<double>217.4323774110454</double>
</void>
</object>
</void>
<void method="addNode">
<object id="PointNode2" class="com.horstmann.violet.PointNode">
<void id="Rectangle2D$Double2" property="bounds">
<void method="setRect">
<double>327.03195662574825</double>
<double>218.46075295682857</double>
<double>0.0</double>
<double>0.0</double>
</void>
</void>
<void property="bounds">
<object idref="Rectangle2D$Double2"/>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>327.03195662574825</double>
<double>218.46075295682857</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode2" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>4. The dir delegates in the builder.
5. The builder stat&apos;s the source file. In
this example it&apos;s a reg. file</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>767.038589176755</double>
<double>206.92203801047344</double>
</void>
</object>
</void>
<void method="addNode">
<object id="PointNode3" class="com.horstmann.violet.PointNode">
<void id="Rectangle2D$Double3" property="bounds">
<void method="setRect">
<double>694.4969551615891</double>
<double>312.7614712457156</double>
<double>0.0</double>
<double>0.0</double>
</void>
</void>
<void property="bounds">
<object idref="Rectangle2D$Double3"/>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>694.4969551615891</double>
<double>312.7614712457156</double>
</void>
</object>
</void>
<void method="addNode">
<object id="PointNode4" class="com.horstmann.violet.PointNode">
<void id="Rectangle2D$Double4" property="bounds">
<void method="setRect">
<double>314.9148790283507</double>
<double>359.23720542189034</double>
<double>0.0</double>
<double>0.0</double>
</void>
</void>
<void property="bounds">
<object idref="Rectangle2D$Double4"/>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>314.9148790283507</double>
<double>359.23720542189034</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode3" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>6. The conversion is not needed, so
the builder just creates a FileTreeNode</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>762.2817607167442</double>
<double>335.3564064307673</double>
</void>
</object>
</void>
<void method="addNode">
<object id="PointNode5" class="com.horstmann.violet.PointNode">
<void id="Rectangle2D$Double5" property="bounds">
<void method="setRect">
<double>522.2869299335649</double>
<double>399.9594286575042</double>
<double>0.0</double>
<double>0.0</double>
</void>
</void>
<void property="bounds">
<object idref="Rectangle2D$Double5"/>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>522.2869299335649</double>
<double>399.9594286575042</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode4" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>7. Sets the attributes from source</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>774.1738318667714</double>
<double>413.8440760209469</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode5" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>8 ...and a FileStream to read contents
from the FileSource</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>762.2817607167442</double>
<double>478.0612602310938</double>
</void>
</object>
</void>
<void method="addNode">
<object id="PointNode6" class="com.horstmann.violet.PointNode">
<void id="Rectangle2D$Double6" property="bounds">
<void method="setRect">
<double>534.9181953038541</double>
<double>453.1845675071054</double>
<double>0.0</double>
<double>0.0</double>
</void>
</void>
<void property="bounds">
<object idref="Rectangle2D$Double6"/>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>534.9181953038541</double>
<double>453.1845675071054</double>
</void>
</object>
</void>
<void method="addNode">
<object id="PointNode7" class="com.horstmann.violet.PointNode">
<void id="Rectangle2D$Double7" property="bounds">
<void method="setRect">
<double>482.368075796364</double>
<double>524.8261757327898</double>
<double>0.0</double>
<double>0.0</double>
</void>
</void>
<void property="bounds">
<object idref="Rectangle2D$Double7"/>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>482.368075796364</double>
<double>524.8261757327898</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode6" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>9. Finally, the FileTreeNode is added to
the parent dir, and returned to the user</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>757.5249322567332</double>
<double>556.5489298212734</double>
</void>
</object>
</void>
<void method="addNode">
<object id="PointNode8" class="com.horstmann.violet.PointNode">
<void id="Rectangle2D$Double8" property="bounds">
<void method="setRect">
<double>689.7401267015781</double>
<double>614.8200784564067</double>
<double>0.0</double>
<double>0.0</double>
</void>
</void>
<void property="bounds">
<object idref="Rectangle2D$Double8"/>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>689.7401267015781</double>
<double>614.8200784564067</double>
</void>
</object>
</void>
<void method="addNode">
<object idref="ActivationBarNode7"/>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>363.97135964975513</double>
<double>656.0</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode7" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>10. The user can change any attribute
on the FileTreeNode</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>735.3910524340093</double>
<double>659.0235200658623</double>
</void>
</object>
</void>
<void method="addNode">
<object id="PointNode9" class="com.horstmann.violet.PointNode">
<void id="Rectangle2D$Double9" property="bounds">
<void method="setRect">
<double>373.3523804664971</double>
<double>666.0945878777277</double>
<double>0.0</double>
<double>0.0</double>
</void>
</void>
<void property="bounds">
<object idref="Rectangle2D$Double9"/>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>373.3523804664971</double>
<double>666.0945878777277</double>
</void>
</object>
</void>
<void method="connect">
<object class="com.horstmann.violet.CallEdge">
<void property="middleLabel">
<string>«create»</string>
</void>
</object>
<object idref="ActivationBarNode0"/>
<object idref="LifelineNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.CallEdge">
<void property="middleLabel">
<string>«create»</string>
</void>
</object>
<object idref="ActivationBarNode1"/>
<object idref="LifelineNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ReturnEdge">
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="SOLID"/>
</void>
<void property="middleLabel">
<string>file</string>
</void>
</object>
<object idref="ActivationBarNode0"/>
<object idref="ActivationBarNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.CallEdge">
<void property="middleLabel">
<string>add_file(file,b)</string>
</void>
</object>
<object idref="ActivationBarNode1"/>
<object idref="ActivationBarNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.CallEdge">
<void property="middleLabel">
<string>create_file(file)</string>
</void>
</object>
<object idref="ActivationBarNode2"/>
<object idref="ActivationBarNode3"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.CallEdge">
<void property="middleLabel">
<string>lstat()</string>
</void>
</object>
<object idref="ActivationBarNode3"/>
<object idref="ActivationBarNode4"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ReturnEdge">
<void property="middleLabel">
<string>S_IFREG</string>
</void>
</object>
<object idref="ActivationBarNode4"/>
<object idref="ActivationBarNode3"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.CallEdge">
<void property="middleLabel">
<string>«create»</string>
</void>
</object>
<object idref="ActivationBarNode3"/>
<object idref="LifelineNode4"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.CallEdge">
<void property="middleLabel">
<string>set attributes</string>
</void>
</object>
<object idref="ActivationBarNode3"/>
<object idref="ActivationBarNode5"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ReturnEdge"/>
<object idref="ActivationBarNode5"/>
<object idref="ActivationBarNode3"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ReturnEdge">
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="SOLID"/>
</void>
<void property="middleLabel">
<string>ftn</string>
</void>
</object>
<object idref="ActivationBarNode3"/>
<object idref="ActivationBarNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.CallEdge">
<void property="middleLabel">
<string>«create»</string>
</void>
</object>
<object idref="ActivationBarNode3"/>
<object idref="LifelineNode5"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.CallEdge">
<void property="middleLabel">
<string>set stream (fs)</string>
</void>
</object>
<object idref="ActivationBarNode3"/>
<object idref="ActivationBarNode6"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ReturnEdge"/>
<object idref="ActivationBarNode6"/>
<object idref="ActivationBarNode3"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ReturnEdge">
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="SOLID"/>
</void>
<void property="middleLabel">
<string>ftn</string>
</void>
</object>
<object idref="ActivationBarNode2"/>
<object idref="ActivationBarNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.CallEdge">
<void property="middleLabel">
<string>«create»</string>
</void>
</object>
<object idref="ActivationBarNode1"/>
<object idref="LifelineNode3"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.CallEdge">
<void property="middleLabel">
<string>get(path)</string>
</void>
</object>
<object idref="ActivationBarNode1"/>
<object idref="ActivationBarNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="NoteNode0"/>
<object idref="PointNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="NoteNode0"/>
<object idref="PointNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="NoteNode1"/>
<object idref="PointNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="NoteNode2"/>
<object idref="PointNode3"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="NoteNode2"/>
<object idref="PointNode4"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="NoteNode3"/>
<object idref="PointNode5"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="NoteNode4"/>
<object idref="PointNode6"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="NoteNode5"/>
<object idref="PointNode7"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="NoteNode6"/>
<object idref="PointNode8"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.CallEdge">
<void property="middleLabel">
<string>set_permission()</string>
</void>
</object>
<object idref="ActivationBarNode1"/>
<object idref="ActivationBarNode7"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ReturnEdge"/>
<object idref="ActivationBarNode7"/>
<object idref="ActivationBarNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="NoteNode7"/>
<object idref="PointNode9"/>
</void>
</object>
</java>

View File

@ -0,0 +1,884 @@
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.6.0" class="java.beans.XMLDecoder">
<object class="com.horstmann.violet.ClassDiagramGraph">
<void method="addNode">
<object id="InterfaceNode0" class="com.horstmann.violet.InterfaceNode">
<void property="methods">
<void property="text">
<string>get_root()
get_from_path(char *)</string>
</void>
</void>
<void property="name">
<void property="text">
<string>«interface»
Filesystem</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>159.04005306497305</double>
<double>489.4913761627291</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode0" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>MountedFilesytem</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>56.38849919058573</double>
<double>630.9884605487425</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode1" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>IsoImage</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>258.8562868808994</double>
<double>766.3563832139356</double>
</void>
</object>
</void>
<void method="addNode">
<object id="InterfaceNode1" class="com.horstmann.violet.InterfaceNode">
<void property="methods">
<void property="text">
<string>lstat()
read()
close()
open()
readdir()</string>
</void>
</void>
<void property="name">
<void property="text">
<string>«interface»
SourceFile</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>481.55979910778467</double>
<double>464.84194569982117</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode2" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>TarFile</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>176.58261638364775</double>
<double>701.0593878047844</double>
</void>
</object>
</void>
<void method="addNode">
<object id="InterfaceNode2" class="com.horstmann.violet.InterfaceNode">
<void property="methods">
<void property="text">
<string>read()
size()
open()
close()</string>
</void>
</void>
<void property="name">
<void property="text">
<string>«interface»
Stream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>779.894860994415</double>
<double>340.36024540554786</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode3" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>FdStream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>907.9433913981195</double>
<double>505.6600343909271</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode4" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>FileStream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>646.2536512193697</double>
<double>514.5953286599063</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode5" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>TransformStream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>774.6238447615127</double>
<double>513.9203093177954</double>
</void>
</object>
</void>
<void method="addNode">
<object id="InterfaceNode3" class="com.horstmann.violet.InterfaceNode">
<void property="methods">
<void property="text">
<string>create_file()
create_symlink()
create_dir()</string>
</void>
</void>
<void property="name">
<void property="text">
<string>«interface»
TreeNodeBuilder</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>469.51180397870456</double>
<double>119.92057094444797</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode6" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>TreeNode</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>777.5164467644091</double>
<double>137.7586776694888</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode7" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>File</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>776.3272396494064</double>
<double>235.11044131455145</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode8" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>Dir</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>899.7797731623193</double>
<double>242.40651557378732</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode9" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>Symlink</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>658.5957352641371</double>
<double>237.4888555445569</double>
</void>
</object>
</void>
<void method="addNode">
<object id="InterfaceNode4" class="com.horstmann.violet.InterfaceNode">
<void property="name">
<void property="text">
<string>«interface»
FileBuilder</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>68.74900622278733</double>
<double>236.29964842955417</double>
</void>
</object>
</void>
<void method="addNode">
<object id="InterfaceNode5" class="com.horstmann.violet.InterfaceNode">
<void property="name">
<void property="text">
<string>«interface»
DirBuilder</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>190.04813195306485</double>
<double>236.2996484295542</double>
</void>
</object>
</void>
<void method="addNode">
<object id="InterfaceNode6" class="com.horstmann.violet.InterfaceNode">
<void property="name">
<void property="text">
<string>«interface»
SymlinkBuilder</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>304.21201499332614</double>
<double>236.29964842955417</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode0" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>POSIX inspired interface to files on different filesystems.
open/close act as a opendir/closedir if the file is a dir,
I think we don&apos;t need different function to open a dir.</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>154.8805850420814</double>
<double>333.9382491299707</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode1" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>&quot;Sources&quot; for file contents</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>587.0127806828101</double>
<double>358.755499461917</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode10" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>CutOutStream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>845.6997102991108</double>
<double>605.2834046956852</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode11" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>FilterStream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>721.2489168102784</double>
<double>605.2834046956852</double>
</void>
</object>
</void>
<void method="addNode">
<object id="InterfaceNode7" class="com.horstmann.violet.InterfaceNode">
<void property="name">
<void property="text">
<string>«interface»
Filter</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>715.5920625607861</double>
<double>705.6925676241749</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode2" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>Used for arbitray streams, not related to
filesystem high-level idea. Also used for
files like fifos, that can&apos;t be added directly as
regulat files via de Builder, because its size is
unknown. The need to be added as new_files
on image</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>906.5108934811542</double>
<double>328.0975464705584</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode3" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>Create the user-specified TreeNode from the
user-specified source. If the source type differs the
TreeNode type the use wants to create, it makes
the needed conversion, if possible. Each builder
implementation can do different conversions.</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>654.7808793787427</double>
<double>20.610173055266337</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode4" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>Together with the SourceFile encapsulates the
access to a given filesystem and abstracts it to
a POSIX interface.</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>20.610173055266422</double>
<double>403.050865276332</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode5" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>The TreeNodeBuilder can be created with
the combination of different interfaces for
each factory method</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>149.90663761154804</double>
<double>57.982756057296896</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode12" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>MountedSrc</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>373.3523804664971</double>
<double>634.9818895055197</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode13" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>TarSrc</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>479.4183976444791</double>
<double>695.7930726875627</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode14" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>IsoSrc</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>578.4133470105959</double>
<double>773.574818618083</double>
</void>
</object>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="InterfaceNode0"/>
<object idref="InterfaceNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode4"/>
<object idref="InterfaceNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode3"/>
<object idref="InterfaceNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode0"/>
<object idref="InterfaceNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode2"/>
<object idref="InterfaceNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode1"/>
<object idref="InterfaceNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
</object>
<object idref="ClassNode4"/>
<object idref="InterfaceNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
<void property="middleLabel">
<string>{{create}}</string>
</void>
</object>
<object idref="InterfaceNode3"/>
<object idref="ClassNode6"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
</object>
<object idref="ClassNode9"/>
<object idref="ClassNode6"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
</object>
<object idref="ClassNode7"/>
<object idref="ClassNode6"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
</object>
<object idref="ClassNode8"/>
<object idref="ClassNode6"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
</object>
<object idref="ClassNode7"/>
<object idref="InterfaceNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="startArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="BLACK_DIAMOND"/>
</void>
</object>
<object idref="InterfaceNode3"/>
<object idref="InterfaceNode6"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="startArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="BLACK_DIAMOND"/>
</void>
</object>
<object idref="InterfaceNode3"/>
<object idref="InterfaceNode5"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="startArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="BLACK_DIAMOND"/>
</void>
</object>
<object idref="InterfaceNode3"/>
<object idref="InterfaceNode4"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="InterfaceNode3"/>
<object idref="InterfaceNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="InterfaceNode1"/>
<object idref="NoteNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="InterfaceNode2"/>
<object idref="NoteNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
</object>
<object idref="ClassNode11"/>
<object idref="ClassNode5"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
</object>
<object idref="ClassNode10"/>
<object idref="ClassNode5"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
</object>
<object idref="ClassNode11"/>
<object idref="InterfaceNode7"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode3"/>
<object idref="NoteNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="InterfaceNode3"/>
<object idref="NoteNode3"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="InterfaceNode0"/>
<object idref="NoteNode4"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="InterfaceNode4"/>
<object idref="NoteNode5"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="InterfaceNode5"/>
<object idref="NoteNode5"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="InterfaceNode6"/>
<object idref="NoteNode5"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode5"/>
<object idref="InterfaceNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode12"/>
<object idref="InterfaceNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode13"/>
<object idref="InterfaceNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode14"/>
<object idref="InterfaceNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
</object>
<object idref="ClassNode12"/>
<object idref="ClassNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
</object>
<object idref="ClassNode13"/>
<object idref="ClassNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
</object>
<object idref="ClassNode14"/>
<object idref="ClassNode1"/>
</void>
</object>
</java>

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -0,0 +1,634 @@
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.6.0" class="java.beans.XMLDecoder">
<object class="com.horstmann.violet.ClassDiagramGraph">
<void method="addNode">
<object class="com.horstmann.violet.PackageNode">
<void method="addChild">
<object id="InterfaceNode0" class="com.horstmann.violet.InterfaceNode">
<void property="name">
<void property="text">
<string>«interface»
BurnSource</string>
</void>
</void>
</object>
</void>
<void property="name">
<string>libburn</string>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>600.0</double>
<double>50.0</double>
</void>
</object>
</void>
<void method="addNode">
<object idref="InterfaceNode0"/>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>612.4370214406964</double>
<double>81.3237865499184</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode0" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>Ecma119Source</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>604.1172144213822</double>
<double>242.59825146055505</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode1" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>WriterState</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>861.1034292438676</double>
<double>244.31119796826698</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode2" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>FilesWriterSt</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>984.2531292100068</double>
<double>359.95094883087904</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode3" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>VolDescWriterSt</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>717.2457054234224</double>
<double>357.4185959653686</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode4" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>DirInfoWriterSt</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>854.6043620021998</double>
<double>355.85097462036043</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode5" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>Ecma119Image</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>392.3294860655768</double>
<double>240.39714472372754</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode0" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>The context data for image burn sources, contains
references to the tree, creation options...</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>261.45257180386454</double>
<double>85.80450046553075</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode6" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>Ecma119Node</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>291.8219414851778</double>
<double>612.806815288254</double>
</void>
</object>
</void>
<void method="addNode">
<object id="InterfaceNode1" class="com.horstmann.violet.InterfaceNode">
<void property="methods">
<void property="text">
<string>init()
write_voldesc()
write_dir_info()</string>
</void>
</void>
<void property="name">
<void property="text">
<string>«interface»
ImageWriter</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>401.9520048709197</double>
<double>344.8700633507891</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode7" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>JolietNode</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>409.0872475609359</double>
<double>614.8200784564067</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode8" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>FileRegistry</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>718.2810974616434</double>
<double>459.0339463910502</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode9" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>Ecma119Writer</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>273.51763645062584</double>
<double>489.95333138112096</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode10" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>JolietWriter</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>404.3304191009253</double>
<double>485.1965029211101</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode11" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>ElToritoWriter</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>512.5482665661723</double>
<double>485.19650292111</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode12" class="com.horstmann.violet.ClassNode">
<void property="attributes">
<void property="text">
<string>size : off_t
block : uint32_t</string>
</void>
</void>
<void property="name">
<void property="text">
<string>IsoFile</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>720.659511691649</double>
<double>568.4410009713001</double>
</void>
</object>
</void>
<void method="addNode">
<object id="InterfaceNode2" class="com.horstmann.violet.InterfaceNode">
<void property="name">
<void property="text">
<string>«interface»
Stream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>909.7434429770816</double>
<double>580.3330721213274</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode1" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>ImageWriter goal is to encapsulate the output
of image blocks related to one &quot;specification&quot;,
i.e. we will have an implementation for ECMA-119/RR,
other for Joliet...
Note that having different implementations for things that
need to be written in the same block has no utility, i.e. RR
and ECMA-119 must share its Writer implementation.
Note also that while this provides considerable encapsulation
the provided abstraction is really partial: In the relation
with WriterState the encapsulation is quite good, each
concrete state know what method to call here (notice that
this interface is also quite coupled with state). However,
with respect to Ecma119Image the abstration only refers
to implementation, as the Ecma119Image needs to know
about the ImageWriter implementations. This can&apos;t be
avoided, as Ecma119Image has to be responsible of the
instantation in the correct order and following the user
needs.
</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>2.3784142300054896</double>
<double>160.54296052536733</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode2" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>The files are registered into the file registry, that will take care
about the written of content.</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>286.59891471565567</double>
<double>708.7674405416217</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode3" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>Each state will invoque property method in each of
the ImageWriters. Some writers can return without
outputting anything. It is possible that when dealing
with UDF or other specification we would need new
states and methods in ImageWriter</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>765.8493820617523</double>
<double>132.001989765302</double>
</void>
</object>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode0"/>
<object idref="InterfaceNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode3"/>
<object idref="ClassNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode4"/>
<object idref="ClassNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode2"/>
<object idref="ClassNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="startArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="DIAMOND"/>
</void>
</object>
<object idref="ClassNode0"/>
<object idref="ClassNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode5"/>
<object idref="NoteNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode0"/>
<object idref="ClassNode5"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode10"/>
<object idref="InterfaceNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode9"/>
<object idref="InterfaceNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode11"/>
<object idref="InterfaceNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="endLabel">
<string>*</string>
</void>
<void property="startArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="BLACK_DIAMOND"/>
</void>
</object>
<object idref="ClassNode5"/>
<object idref="InterfaceNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
</object>
<object idref="ClassNode9"/>
<object idref="ClassNode6"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
</object>
<object idref="ClassNode10"/>
<object idref="ClassNode7"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="endLabel">
<string>*</string>
</void>
</object>
<object idref="ClassNode8"/>
<object idref="ClassNode12"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
</object>
<object idref="ClassNode12"/>
<object idref="InterfaceNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode5"/>
<object idref="ClassNode8"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode2"/>
<object idref="ClassNode8"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="InterfaceNode1"/>
<object idref="ClassNode8"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="InterfaceNode1"/>
<object idref="NoteNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode6"/>
<object idref="NoteNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode7"/>
<object idref="NoteNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode8"/>
<object idref="NoteNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode1"/>
<object idref="NoteNode3"/>
</void>
</object>
</java>

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -0,0 +1,552 @@
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.6.0" class="java.beans.XMLDecoder">
<object class="com.horstmann.violet.ClassDiagramGraph">
<void method="addNode">
<object id="ClassNode0" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>Volume</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>479.2699858975891</double>
<double>226.94112549695433</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode1" class="com.horstmann.violet.ClassNode">
<void property="attributes">
<void property="text">
<string>block : uint32_t</string>
</void>
</void>
<void property="name">
<void property="text">
<string>ElToritoCatalog</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>472.58578643762684</double>
<double>344.73506473629425</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode2" class="com.horstmann.violet.ClassNode">
<void property="attributes">
<void property="text">
<string>bootable : bool
type : enum
partition_type : enum
load_seg : uint16
load_size : uint16
patch_isolinux : bool
block: uint32_t</string>
</void>
</void>
<void property="name">
<void property="text">
<string>BootImage</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>470.4142135623731</double>
<double>487.3919189857866</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode0" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>In a future we can support several boot
images</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>251.63542622468316</double>
<double>429.69343417595167</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode3" class="com.horstmann.violet.ClassNode">
<void property="attributes">
<void property="text">
<string>img : boolean</string>
</void>
</void>
<void property="name">
<void property="text">
<string>BootNode</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>193.07106781186545</double>
<double>334.49242404917493</double>
</void>
</object>
</void>
<void method="addNode">
<object class="com.horstmann.violet.PackageNode">
<void method="addChild">
<object id="ClassNode4" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>TreeNode</string>
</void>
</void>
</object>
</void>
<void property="name">
<string>iso_tree</string>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>180.0</double>
<double>40.0</double>
</void>
</object>
</void>
<void method="addNode">
<object idref="ClassNode4"/>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>193.0</double>
<double>69.0</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode1" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>The img field is an implementation detail, used
to distinguish between the catalog node and the image
node. This is needed when the image is written.</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>57.81118318204312</double>
<double>584.0458146424488</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode2" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>The support for growing or modify El-Torito images
is really hard to implement. The reason: when the
image is hidden, we don&apos;t know its size, so the best we
can do is just refer to the old image. When modify, all
we can do may be wrong.</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>748.978906441031</double>
<double>574.8973495522459</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode3" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>The block in both Catalog and BootImage is needed
for multissession images</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>629.3242465083424</double>
<double>441.1316647878586</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode5" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>File</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>188.09040379562163</double>
<double>172.5340546095176</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode6" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>CatalogStream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>851.105100475371</double>
<double>283.5127233261827</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode7" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>FileStream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>743.4055403867466</double>
<double>284.4253525880894</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode8" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>TransformStream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>958.5987801403015</double>
<double>279.8322618091961</double>
</void>
</object>
</void>
<void method="addNode">
<object id="InterfaceNode0" class="com.horstmann.violet.InterfaceNode">
<void property="name">
<void property="text">
<string>«interface»
Stream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>847.6728065449973</double>
<double>157.05765855361264</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode9" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>IsoLinuxPatch</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>968.73629022557</double>
<double>384.6660889654818</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode4" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>Generates the content of the catalog on-the-fly</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>517.6021638285529</double>
<double>107.48023074035522</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode5" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>To apply the needed patch to isolinux
images</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>923.4814562296309</double>
<double>509.1168824543143</double>
</void>
</object>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="endLabel">
<string>1 image</string>
</void>
<void property="startArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="BLACK_DIAMOND"/>
</void>
</object>
<object idref="ClassNode1"/>
<object idref="ClassNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode1"/>
<object idref="NoteNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="endLabel">
<string>0..1 boot_cat</string>
</void>
</object>
<object idref="ClassNode0"/>
<object idref="ClassNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="endLabel">
<string>0..1 node</string>
</void>
</object>
<object idref="ClassNode1"/>
<object idref="ClassNode3"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode3"/>
<object idref="NoteNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="endLabel">
<string>0..1 node</string>
</void>
</object>
<object idref="ClassNode2"/>
<object idref="ClassNode3"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
</object>
<object idref="ClassNode3"/>
<object idref="ClassNode5"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
</object>
<object idref="ClassNode5"/>
<object idref="ClassNode4"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode8"/>
<object idref="InterfaceNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode7"/>
<object idref="InterfaceNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="endLabel">
<string>1</string>
</void>
<void property="startArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="BLACK_DIAMOND"/>
</void>
</object>
<object idref="ClassNode8"/>
<object idref="InterfaceNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode6"/>
<object idref="InterfaceNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode1"/>
<object idref="NoteNode3"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode2"/>
<object idref="NoteNode3"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode2"/>
<object idref="NoteNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
</object>
<object idref="ClassNode5"/>
<object idref="InterfaceNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
</object>
<object idref="ClassNode9"/>
<object idref="ClassNode8"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
</object>
<object idref="ClassNode1"/>
<object idref="InterfaceNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
</object>
<object idref="ClassNode2"/>
<object idref="InterfaceNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode6"/>
<object idref="ClassNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode6"/>
<object idref="NoteNode4"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode9"/>
<object idref="NoteNode5"/>
</void>
</object>
</java>

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1,748 @@
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.6.0" class="java.beans.XMLDecoder">
<object class="com.horstmann.violet.ClassDiagramGraph">
<void method="addNode">
<object id="ClassNode0" class="com.horstmann.violet.ClassNode">
<void property="attributes">
<void property="text">
<string>volume_id : char*
publisher_id : char*
data_preparer_id : char*
system_id : char*
application_id : char*
copyright_file_id : char*
abstract_file_id : char*
biblio_file_id : char*</string>
</void>
</void>
<void property="name">
<void property="text">
<string>Volume</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>1160.4799402311673</double>
<double>240.649943764645</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode1" class="com.horstmann.violet.ClassNode">
<void property="attributes">
<void property="text">
<string>sort_weight : int
block : uint32_t</string>
</void>
</void>
<void property="name">
<void property="text">
<string>File</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>687.5479565719912</double>
<double>269.2931470368318</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode2" class="com.horstmann.violet.ClassNode">
<void property="attributes">
<void property="text">
<string>name : char *
attribs : struct stat
hidden : enum</string>
</void>
</void>
<void property="name">
<void property="text">
<string>TreeNode</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>706.83671056434</double>
<double>108.4726745515399</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode3" class="com.horstmann.violet.ClassNode">
<void property="methods">
<void property="text">
<string>add(XXX)
remove(Node)
children()</string>
</void>
</void>
<void property="name">
<void property="text">
<string>Directory</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>986.1687535943008</double>
<double>267.29314703683184</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode4" class="com.horstmann.violet.ClassNode">
<void property="attributes">
<void property="text">
<string>dest : char*</string>
</void>
</void>
<void property="name">
<void property="text">
<string>Symlink</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>571.9364350336367</double>
<double>273.31078127658077</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode5" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>Special</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>813.0651280884073</double>
<double>272.20749521231266</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode6" class="com.horstmann.violet.ClassNode">
<void property="attributes">
<void property="text">
<string>name : char*</string>
</void>
</void>
<void property="methods">
<void property="text">
<string>&lt;&lt;static&gt;&gt;new(id)
&lt;&lt;static&gt;&gt;read(src, opts)
create()
grow()</string>
</void>
</void>
<void property="name">
<void property="text">
<string>Image</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>1149.1980515339465</double>
<double>455.5218613006981</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode0" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>In addition to the dest as a path, it could
be a good idea to have a ref to tree node.
That way we can compute the dest on creation
time, and thus links to files on image are also valid
after moving or renaming those files</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>322.02220861890066</double>
<double>362.2044136147912</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode1" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>Image is a context for the creation of images. Its &quot;static&quot;
methods, new() and read() are used to create a new
image context, either from scratch or from an existing
image (for example, a ms disc). The methods create() and
grow() return an BurnSource suitable for libburn.
create() writes a full image, grow() only add to the image
the new files, thus it is suitable for a new session
</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>1212.7956394939486</double>
<double>697.0920982847697</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode7" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>Ecma119Source</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>1423.5617211564486</double>
<double>483.61244144432396</double>
</void>
</object>
</void>
<void method="addNode">
<object class="com.horstmann.violet.PackageNode">
<void method="addChild">
<object id="InterfaceNode0" class="com.horstmann.violet.InterfaceNode">
<void property="name">
<void property="text">
<string>«interface»
BurnSource</string>
</void>
</void>
</object>
</void>
<void property="name">
<string>Libburn</string>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>1420.0</double>
<double>280.0</double>
</void>
</object>
</void>
<void method="addNode">
<object idref="InterfaceNode0"/>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>1431.4906533445824</double>
<double>311.35760744838467</double>
</void>
</object>
</void>
<void method="addNode">
<object class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>Class diagram for the public tree. Note that getters and setters are not shown,
to improve readability. Note also that not all the attributes will have public getters
or/and setters.
El-Torito related information is shown in another diagram.
We don&apos;t show the several functions in Dir to manage the tree.</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>290.59037712396525</double>
<double>9.859316379054544</double>
</void>
</object>
</void>
<void method="addNode">
<object id="InterfaceNode1" class="com.horstmann.violet.InterfaceNode">
<void property="name">
<void property="text">
<string>«interface»
DataSource</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>1192.781692587207</double>
<double>608.8954677283948</double>
</void>
</object>
</void>
<void method="addNode">
<object class="com.horstmann.violet.PackageNode">
<void method="addChild">
<object id="InterfaceNode2" class="com.horstmann.violet.InterfaceNode">
<void property="name">
<void property="text">
<string>«interface»
Filters</string>
</void>
</void>
</object>
</void>
<void property="name">
<string>filters</string>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>260.0</double>
<double>710.0</double>
</void>
</object>
</void>
<void method="addNode">
<object idref="InterfaceNode2"/>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>265.45434264405947</double>
<double>743.9994422711634</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode8" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>TransformStream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>486.9335577265969</double>
<double>640.636302316303</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode9" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>CutOutStream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>555.9916340674516</double>
<double>750.220757440409</double>
</void>
</object>
</void>
<void method="addNode">
<object id="InterfaceNode3" class="com.horstmann.violet.InterfaceNode">
<void property="methods">
<void property="text">
<string>get_size()
read()
open()
close()
is_repeatable()</string>
</void>
</void>
<void property="name">
<void property="text">
<string>«interface»
Stream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>688.5487814157467</double>
<double>437.25152600545294</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode10" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>FdStream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>680.6673668471356</double>
<double>637.245696021424</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode11" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>FileStream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>828.9404615480411</double>
<double>642.40096597045</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode12" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>FilteredStream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>428.449880813367</double>
<double>747.5389646099015</double>
</void>
</object>
</void>
<void method="addNode">
<object id="InterfaceNode4" class="com.horstmann.violet.InterfaceNode">
<void property="name">
<void property="text">
<string>«interface»
SourceFile</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>1000.6667341519202</double>
<double>639.0812755928229</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode2" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>For files, we need to know whethe they come
from a previous session. That&apos;s the purpose of
the block field</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>818.829652614022</double>
<double>414.36457377531684</double>
</void>
</object>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="endLabel">
<string>1 volume</string>
</void>
<void property="startArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="BLACK_DIAMOND"/>
</void>
</object>
<object idref="ClassNode6"/>
<object idref="ClassNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode4"/>
<object idref="NoteNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode6"/>
<object idref="NoteNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode7"/>
<object idref="InterfaceNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
<void property="middleLabel">
<string>{create}</string>
</void>
</object>
<object idref="ClassNode6"/>
<object idref="ClassNode7"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="endLabel">
<string>0..1</string>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode6"/>
<object idref="InterfaceNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="endLabel">
<string>* children</string>
</void>
<void property="startArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="BLACK_DIAMOND"/>
</void>
</object>
<object idref="ClassNode3"/>
<object idref="ClassNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="endLabel">
<string>1 root</string>
</void>
<void property="startArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="BLACK_DIAMOND"/>
</void>
</object>
<object idref="ClassNode0"/>
<object idref="ClassNode3"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
</object>
<object idref="ClassNode4"/>
<object idref="ClassNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
</object>
<object idref="ClassNode1"/>
<object idref="ClassNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
</object>
<object idref="ClassNode5"/>
<object idref="ClassNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
</object>
<object idref="ClassNode3"/>
<object idref="ClassNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="endLabel">
<string>1 parent</string>
</void>
</object>
<object idref="ClassNode2"/>
<object idref="ClassNode3"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode8"/>
<object idref="InterfaceNode3"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode11"/>
<object idref="InterfaceNode3"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="endLabel">
<string>1</string>
</void>
<void property="startArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="BLACK_DIAMOND"/>
</void>
</object>
<object idref="ClassNode8"/>
<object idref="InterfaceNode3"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode10"/>
<object idref="InterfaceNode3"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
</object>
<object idref="ClassNode9"/>
<object idref="ClassNode8"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
</object>
<object idref="ClassNode12"/>
<object idref="ClassNode8"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
</object>
<object idref="ClassNode12"/>
<object idref="InterfaceNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
</object>
<object idref="ClassNode11"/>
<object idref="InterfaceNode4"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="endLabel">
<string>1 src</string>
</void>
</object>
<object idref="ClassNode1"/>
<object idref="InterfaceNode3"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode1"/>
<object idref="NoteNode2"/>
</void>
</object>
</java>

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,492 @@
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.6.0" class="java.beans.XMLDecoder">
<object class="com.horstmann.violet.ClassDiagramGraph">
<void method="addNode">
<object id="ClassNode0" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>TransformStream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>374.71280028618764</double>
<double>246.7337520453866</double>
</void>
</object>
</void>
<void method="addNode">
<object id="InterfaceNode0" class="com.horstmann.violet.InterfaceNode">
<void property="methods">
<void property="text">
<string>get_size()
read()
open()
close()
is_repeatable()</string>
</void>
</void>
<void property="name">
<void property="text">
<string>«interface»
Stream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>576.3280239753375</double>
<double>43.34897573453627</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode1" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>FileStream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>741.9465965652432</double>
<double>246.8166228690261</double>
</void>
</object>
</void>
<void method="addNode">
<object class="com.horstmann.violet.PackageNode">
<void method="addChild">
<object id="ClassNode2" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>CompressionFilter</string>
</void>
</void>
</object>
</void>
<void method="addChild">
<object id="ClassNode3" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>EncryptionFilter</string>
</void>
</void>
</object>
</void>
<void method="addChild">
<object id="ClassNode4" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>ExtAppFilter</string>
</void>
</void>
</object>
</void>
<void method="addChild">
<object id="InterfaceNode1" class="com.horstmann.violet.InterfaceNode">
<void property="methods">
<void property="text">
<string>filter(in, out)</string>
</void>
</void>
<void property="name">
<void property="text">
<string>«interface»
Filter</string>
</void>
</void>
</object>
</void>
<void property="name">
<string>Filters</string>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>270.0</double>
<double>480.0</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode0" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>A Stream to read data from an abstract
file represented by a SourceFile</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>781.6101730552666</double>
<double>137.2161620284267</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode1" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>A stream to get data from an arbitrary file
descritor. size must be know in advance.</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>580.8730162779191</double>
<double>392.3137084989848</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode5" class="com.horstmann.violet.ClassNode">
<void property="attributes">
<void property="text">
<string>fd : int
size : off_t</string>
</void>
</void>
<void property="name">
<void property="text">
<string>FdStream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>565.61818228198</double>
<double>253.24264068711926</double>
</void>
</object>
</void>
<void method="addNode">
<object idref="ClassNode2"/>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>281.2426406871193</double>
<double>620.6274169979695</double>
</void>
</object>
</void>
<void method="addNode">
<object idref="ClassNode3"/>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>429.51546936508925</double>
<double>624.9910026589843</double>
</void>
</object>
</void>
<void method="addNode">
<object idref="ClassNode4"/>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>568.2426406871186</double>
<double>624.6274169979695</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode2" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>A Filter do a tranformation on a stream of data.
The main difference with TransformSources is that
a Filter can be applied to several sources.
NOTES:
- filter() method still to define
- A filter_changes_size() method can be useful
</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>724.6274169979696</double>
<double>510.3015151901651</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode6" class="com.horstmann.violet.ClassNode">
<void property="name">
<void property="text">
<string>FilteredStream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>439.0</double>
<double>357.0</double>
</void>
</object>
</void>
<void method="addNode">
<object id="ClassNode7" class="com.horstmann.violet.ClassNode">
<void property="attributes">
<void property="text">
<string>size : off_t
lba: off_t</string>
</void>
</void>
<void property="name">
<void property="text">
<string>CutOutStream</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>321.0</double>
<double>358.0</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode3" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>This can be implemented as a Filter, but
it has no sense to have the same cut out
filter to several sources, so this is a better
place.</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>67.0</double>
<double>276.0</double>
</void>
</object>
</void>
<void method="addNode">
<object id="NoteNode4" class="com.horstmann.violet.NoteNode">
<void property="text">
<void property="text">
<string>A stream that applies some transformation
to the contents of another stream.</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>122.0</double>
<double>183.0</double>
</void>
</object>
</void>
<void method="addNode">
<object idref="InterfaceNode1"/>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>437.57046683437824</double>
<double>509.23933115391503</double>
</void>
</object>
</void>
<void method="addNode">
<object id="InterfaceNode2" class="com.horstmann.violet.InterfaceNode">
<void property="name">
<void property="text">
<string>«interface»
SourceFile</string>
</void>
</void>
</object>
<object class="java.awt.geom.Point2D$Double">
<void method="setLocation">
<double>920.6530291048848</double>
<double>248.90158697766475</double>
</void>
</object>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode0"/>
<object idref="InterfaceNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode1"/>
<object idref="InterfaceNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
<void property="endLabel">
<string>1</string>
</void>
<void property="startArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="BLACK_DIAMOND"/>
</void>
</object>
<object idref="ClassNode0"/>
<object idref="InterfaceNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode5"/>
<object idref="InterfaceNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode5"/>
<object idref="NoteNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
</object>
<object idref="ClassNode7"/>
<object idref="ClassNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
</object>
<object idref="ClassNode6"/>
<object idref="ClassNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode7"/>
<object idref="NoteNode3"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode0"/>
<object idref="NoteNode4"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode2"/>
<object idref="InterfaceNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode3"/>
<object idref="InterfaceNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="VHV"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
</void>
<void property="lineStyle">
<object class="com.horstmann.violet.LineStyle" field="DOTTED"/>
</void>
</object>
<object idref="ClassNode4"/>
<object idref="InterfaceNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
</object>
<object idref="ClassNode6"/>
<object idref="InterfaceNode1"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="InterfaceNode1"/>
<object idref="NoteNode2"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.NoteEdge"/>
<object idref="ClassNode1"/>
<object idref="NoteNode0"/>
</void>
<void method="connect">
<object class="com.horstmann.violet.ClassRelationshipEdge">
<void property="bentStyle">
<object class="com.horstmann.violet.BentStyle" field="HVH"/>
</void>
<void property="endArrowHead">
<object class="com.horstmann.violet.ArrowHead" field="V"/>
</void>
</object>
<object idref="ClassNode1"/>
<object idref="InterfaceNode2"/>
</void>
</object>
</java>

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="1">
<profile kind="CodeFormatterProfile" name="nglibisofs" version="1">
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.lineSplit" value="80"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.cdt.core.formatter.alignment_for_conditional_expression" value="16"/>
<setting id="org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header" value="false"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier" value="true"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header" value="false"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.tabulation.size" value="4"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.indent_empty_lines" value="false"/>
<setting id="org.eclipse.cdt.core.formatter.tabulation.char" value="space"/>
<setting id="org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.brace_position_for_method_declaration" value="next_line"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.brace_position_for_block_in_case" value="next_line_shifted"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<setting id="org.eclipse.cdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
<setting id="org.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation" value="18"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration" value="18"/>
<setting id="org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration" value="end_of_line"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.cdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.cdt.core.formatter.brace_position_for_block" value="end_of_line"/>
<setting id="org.eclipse.cdt.core.formatter.brace_position_for_type_declaration" value="next_line"/>
</profile>
</profiles>

View File

@ -0,0 +1,119 @@
===============================================================================
ISO/IEC 9660:1999 Cookbook
===============================================================================
Creation date: 2008-Jan-14
Author: Vreixo Formoso
_______________________________________________________________________________
Contents:
---------
1. References
2. General
3. Features
4. Implementation
5. Known implementation bugs and specification ambiguities/problems
-------------------------------------------------------------------------------
1. References:
ISO/IEC DIS 9660:1999(E) "Information processing. Volume and file structure of
CD­-ROM for Information Interchange"
-------------------------------------------------------------------------------
2. General
ISO 9660:1999, also known as ISO-9660 version 2 is an update of the old
ISO 9660:1988 standard for writing data images for CD.
In the same way Joliet does, it is based on a Secondary Volume Descriptor (that
is called Enhanced Volume Descriptor), that provides a second tree where the
new file information is recorded.
-------------------------------------------------------------------------------
3. Features
It makes some improvements with respect to ECMA-119, mainly related to relax
the constraints imposed by its predecessor.
- It removes the limit to the deep of the directory hierarchy (6.8.2.1).
However, it still keep a limit to the path length, of 255 characters as in
ECMA-119.
- File names don't need the version number (;1) anymore, and the "." and ";",
used as SEPARATORS for extension and version number, have no special meaning
now.
- The file name max length is incremented to 207 bytes.
- The file name is not restricted to d-characters.
-------------------------------------------------------------------------------
4. Implementation
ISO 9660:1999 is very similar to old ISO 9660:1988 (ECMA-119). It needs two
tree hierarchies: one, identified by the Primary Volume Descriptor, is recorded
in the same way that an ECMA-119 structure.
The second structure is identified by a Enhanced Volume Descriptor (8.5). The
structure is exactly like defined in ECMA-119, with the exceptions named above.
Thus, to write an ISO 9660:1999:
- First 16 blocks are set to 0.
- Block 16 identifies a PVD (8.4), associated with a directory structure
written following ECMA-119.
- It is needed a Enhanced Volume descriptor to describe the additional
structure. It is much like a SVD, with version number set to 2 to identify
this new version.
- We can also write boot records (El-Torito) and additional SVD (Joliet).
- We write a Volume Descriptor Set Terminator (8.3)
- We write directory structure and path tables (L and M) for both ECMA-119
tree and enhanced tree. Path table record and directory record format is
the same in both structures. However, ECMA-119 is constrained by the usual
restrictions.
- And write the contents of the files.
Interchange levels 1, 2 and 3 are also defined. For PVD tree, they have the
same meaning as in ECMA-119. For EVD tree, in levels 1 and 2 files are
restricted to one file section (i.e., 4 GB filesize limit). In level 3 we can
have more than one section per file. Level 1 does not impose other
restrictions than that in the EVD tree.
It seems that both El-Torito and Joliet can coexist in a ISO 9660:1999 image.
However, Joliet has no utility at all in this kind of images, as it has no
benefit over ISO 9660:1999, and it is more restrictive in filename length.
-------------------------------------------------------------------------------
5. Known implementation bugs and specification ambiguities/problems
- While the specification clearly states that the tree speficied by the Primary
Volume Descriptor should remain compatible with ISO-9660 (ECMA-119), i.e., it
should be constrained by ECMA-119 restrictions, some image generation
applications out there just make both Primary and Enhanced Volume Descriptors
to point to the same directory structure. That is a specification violation, as
for a) the directory hierarchy specified in the Primary Volume Descriptor
doesn't follow the restrictions specified in the specs, and b) the same
directories are part of two different hiearchies (6.8.3 "A directory shall not
be a part of more than one Directory Hierarchy.").
Thus, we should keep two trees as we do with Joliet. Or are there strong
reasons against this?
- It's not very clear what characters are allowed for files and dir names. For
the tree identified in the Enhanced Volume Descriptor, it seems that a
"sequence of characters rather than d-characters or d1-characters" is allowed.
It also seems that the charset is determined by the escape sequence in the
EVD. Anyway, leaving escape sequence to 0 and use any user-specified sequence
(such as UTF-8) seems a good solution and is what many other applications do.
Linux correctly mounts the images in this case.
- It is not clear if RR extensions are allowed in the tree identified by the
Enhanced Volume Descriptor. However, it seems not a good idea. With 207 bytes
filenames and XA extensions, there is no place for RR entries in the directory
records of the enhanced tree. In my opinion, RR extension should be attached to
the ECMA-119 tree that must also be written to image.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libisofs
Description: ISO9660 filesystem creation library
Version: @VERSION@
Requires:
Libs: -L${libdir} -lisofs
Cflags: -I${includedir}/libisofs

View File

@ -0,0 +1,328 @@
/*
* Copyright (c) 2007 Vreixo Formoso
*
* This file is part of the libisofs project; 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. See COPYING file for details.
*/
/*
* Synchronized ring buffer, works with a writer thread and a read thread.
*
* TODO #00010 : optimize ring buffer
* - write/read at the end of buffer requires a second mutex_lock, even if
* there's enought space/data at the beginning
* - pre-buffer for writes < BLOCK_SIZE
*
*/
#include "buffer.h"
#include "libburn/libburn.h"
#include "ecma119.h"
#include <pthread.h>
#include <string.h>
#ifndef MIN
# define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
struct iso_ring_buffer
{
uint8_t *buf;
/*
* Max number of bytes in buffer
*/
size_t cap;
/*
* Number of bytes available.
*/
size_t size;
/* position for reading and writing, offset from buf */
size_t rpos;
size_t wpos;
/*
* flags to report if read or writer threads ends execution
* 0 not finished, 1 finished ok, 2 finish with error
*/
unsigned int rend :2;
unsigned int wend :2;
/* just for statistical purposes */
unsigned int times_full;
unsigned int times_empty;
pthread_mutex_t mutex;
pthread_cond_t empty;
pthread_cond_t full;
};
/**
* Create a new buffer.
*
* The created buffer should be freed with iso_ring_buffer_free()
*
* @param size
* Number of blocks in buffer. You should supply a number >= 32, otherwise
* size will be ignored and 32 will be used by default, which leads to a
* 64 KiB buffer.
* @return
* 1 success, < 0 error
*/
int iso_ring_buffer_new(size_t size, IsoRingBuffer **rbuf)
{
IsoRingBuffer *buffer;
if (rbuf == NULL) {
return ISO_NULL_POINTER;
}
buffer = malloc(sizeof(IsoRingBuffer));
if (buffer == NULL) {
return ISO_OUT_OF_MEM;
}
buffer->cap = (size > 32 ? size : 32) * BLOCK_SIZE;
buffer->buf = malloc(buffer->cap);
if (buffer->buf == NULL) {
free(buffer);
return ISO_OUT_OF_MEM;
}
buffer->size = 0;
buffer->wpos = 0;
buffer->rpos = 0;
buffer->times_full = 0;
buffer->times_empty = 0;
buffer->rend = buffer->wend = 0;
/* init mutex and waiting queues */
pthread_mutex_init(&buffer->mutex, NULL);
pthread_cond_init(&buffer->empty, NULL);
pthread_cond_init(&buffer->full, NULL);
*rbuf = buffer;
return ISO_SUCCESS;
}
void iso_ring_buffer_free(IsoRingBuffer *buf)
{
if (buf == NULL) {
return;
}
free(buf->buf);
pthread_mutex_destroy(&buf->mutex);
pthread_cond_destroy(&buf->empty);
pthread_cond_destroy(&buf->full);
free(buf);
}
/**
* Write count bytes into buffer. It blocks until all bytes where written or
* reader close the buffer.
*
* @param buf
* the buffer
* @param data
* pointer to a memory region of at least coun bytes, from which data
* will be read.
* @param
* Number of bytes to write
* @return
* 1 succes, 0 read finished, < 0 error
*/
int iso_ring_buffer_write(IsoRingBuffer *buf, uint8_t *data, size_t count)
{
size_t len;
int bytes_write = 0;
if (buf == NULL || data == NULL) {
return ISO_NULL_POINTER;
}
while (bytes_write < count) {
pthread_mutex_lock(&buf->mutex);
while (buf->size == buf->cap) {
/*
* Note. There's only a writer, so we have no race conditions.
* Thus, the while(buf->size == buf->cap) is used here
* only to propertly detect the reader has been cancelled
*/
if (buf->rend) {
/* the read procces has been finished */
pthread_mutex_unlock(&buf->mutex);
return 0;
}
buf->times_full++;
/* wait until space available */
pthread_cond_wait(&buf->full, &buf->mutex);
}
len = MIN(count - bytes_write, buf->cap - buf->size);
if (buf->wpos + len > buf->cap) {
len = buf->cap - buf->wpos;
}
memcpy(buf->buf + buf->wpos, data + bytes_write, len);
buf->wpos = (buf->wpos + len) % (buf->cap);
bytes_write += len;
buf->size += len;
/* wake up reader */
pthread_cond_signal(&buf->empty);
pthread_mutex_unlock(&buf->mutex);
}
return ISO_SUCCESS;
}
/**
* Read count bytes from the buffer into dest. It blocks until the desired
* bytes has been read. If the writer finishes before outputting enought
* bytes, 0 (EOF) is returned, the number of bytes already read remains
* unknown.
*
* @return
* 1 success, 0 EOF, < 0 error
*/
int iso_ring_buffer_read(IsoRingBuffer *buf, uint8_t *dest, size_t count)
{
size_t len;
int bytes_read = 0;
if (buf == NULL || dest == NULL) {
return ISO_NULL_POINTER;
}
while (bytes_read < count) {
pthread_mutex_lock(&buf->mutex);
while (buf->size == 0) {
/*
* Note. There's only a reader, so we have no race conditions.
* Thus, the while(buf->size == 0) is used here just to ensure
* a reader detects the EOF propertly if the writer has been
* canceled while the reader was waiting
*/
if (buf->wend) {
/* the writer procces has been finished */
pthread_mutex_unlock(&buf->mutex);
return 0; /* EOF */
}
buf->times_empty++;
/* wait until data available */
pthread_cond_wait(&buf->empty, &buf->mutex);
}
len = MIN(count - bytes_read, buf->size);
if (buf->rpos + len > buf->cap) {
len = buf->cap - buf->rpos;
}
memcpy(dest + bytes_read, buf->buf + buf->rpos, len);
buf->rpos = (buf->rpos + len) % (buf->cap);
bytes_read += len;
buf->size -= len;
/* wake up the writer */
pthread_cond_signal(&buf->full);
pthread_mutex_unlock(&buf->mutex);
}
return ISO_SUCCESS;
}
void iso_ring_buffer_writer_close(IsoRingBuffer *buf, int error)
{
pthread_mutex_lock(&buf->mutex);
buf->wend = error ? 2 : 1;
/* ensure no reader is waiting */
pthread_cond_signal(&buf->empty);
pthread_mutex_unlock(&buf->mutex);
}
void iso_ring_buffer_reader_close(IsoRingBuffer *buf, int error)
{
pthread_mutex_lock(&buf->mutex);
if (buf->rend) {
/* reader already closed */
pthread_mutex_unlock(&buf->mutex);
return;
}
buf->rend = error ? 2 : 1;
/* ensure no writer is waiting */
pthread_cond_signal(&buf->full);
pthread_mutex_unlock(&buf->mutex);
}
/**
* Get the times the buffer was full.
*/
unsigned int iso_ring_buffer_get_times_full(IsoRingBuffer *buf)
{
return buf->times_full;
}
/**
* Get the times the buffer was empty.
*/
unsigned int iso_ring_buffer_get_times_empty(IsoRingBuffer *buf)
{
return buf->times_empty;
}
/**
* Get the status of the buffer used by a burn_source.
*
* @param b
* A burn_source previously obtained with
* iso_image_create_burn_source().
* @param size
* Will be filled with the total size of the buffer, in bytes
* @param free_bytes
* Will be filled with the bytes currently available in buffer
* @return
* < 0 error, > 0 state:
* 1="active" : input and consumption are active
* 2="ending" : input has ended without error
* 3="failing" : input had error and ended,
* 5="abandoned" : consumption has ended prematurely
* 6="ended" : consumption has ended without input error
* 7="aborted" : consumption has ended after input error
*/
int iso_ring_buffer_get_status(struct burn_source *b, size_t *size,
size_t *free_bytes)
{
int ret;
IsoRingBuffer *buf;
if (b == NULL) {
return ISO_NULL_POINTER;
}
buf = ((Ecma119Image*)(b->data))->buffer;
/* get mutex */
pthread_mutex_lock(&buf->mutex);
if (size) {
*size = buf->cap;
}
if (free_bytes) {
*free_bytes = buf->cap - buf->size;
}
ret = (buf->rend ? 4 : 0) + (buf->wend + 1);
pthread_mutex_unlock(&buf->mutex);
return ret;
}

View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2007 Vreixo Formoso
*
* This file is part of the libisofs project; 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. See COPYING file for details.
*/
#ifndef LIBISO_BUFFER_H_
#define LIBISO_BUFFER_H_
#include <stdlib.h>
#include <stdint.h>
#define BLOCK_SIZE 2048
typedef struct iso_ring_buffer IsoRingBuffer;
/**
* Create a new buffer.
*
* The created buffer should be freed with iso_ring_buffer_free()
*
* @param size
* Number of blocks in buffer. You should supply a number >= 32, otherwise
* size will be ignored and 32 will be used by default, which leads to a
* 64 KiB buffer.
* @return
* 1 success, < 0 error
*/
int iso_ring_buffer_new(size_t size, IsoRingBuffer **rbuf);
/**
* Free a given buffer
*/
void iso_ring_buffer_free(IsoRingBuffer *buf);
/**
* Write count bytes into buffer. It blocks until all bytes where written or
* reader close the buffer.
*
* @param buf
* the buffer
* @param data
* pointer to a memory region of at least coun bytes, from which data
* will be read.
* @param
* Number of bytes to write
* @return
* 1 succes, 0 read finished, < 0 error
*/
int iso_ring_buffer_write(IsoRingBuffer *buf, uint8_t *data, size_t count);
/**
* Read count bytes from the buffer into dest. It blocks until the desired
* bytes has been read. If the writer finishes before outputting enought
* bytes, 0 (EOF) is returned, the number of bytes already read remains
* unknown.
*
* @return
* 1 success, 0 EOF, < 0 error
*/
int iso_ring_buffer_read(IsoRingBuffer *buf, uint8_t *dest, size_t count);
/**
* Close the buffer (to be called by the writer).
* You have to explicity close the buffer when you don't have more data to
* write, otherwise reader will be waiting forever.
*
* @param error
* Writer has finished prematurely due to an error
*/
void iso_ring_buffer_writer_close(IsoRingBuffer *buf, int error);
/**
* Close the buffer (to be called by the reader).
* If for any reason you don't want to read more data, you need to call this
* to let the writer thread finish.
*
* @param error
* Reader has finished prematurely due to an error
*/
void iso_ring_buffer_reader_close(IsoRingBuffer *buf, int error);
/**
* Get the times the buffer was full.
*/
unsigned int iso_ring_buffer_get_times_full(IsoRingBuffer *buf);
/**
* Get the times the buffer was empty.
*/
unsigned int iso_ring_buffer_get_times_empty(IsoRingBuffer *buf);
#endif /*LIBISO_BUFFER_H_*/

View File

@ -0,0 +1,208 @@
/*
* Copyright (c) 2007 Vreixo Formoso
*
* This file is part of the libisofs project; 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. See COPYING file for details.
*/
#include "builder.h"
#include "node.h"
#include "fsource.h"
#include <stdlib.h>
#include <string.h>
#include <limits.h>
void iso_node_builder_ref(IsoNodeBuilder *builder)
{
++builder->refcount;
}
void iso_node_builder_unref(IsoNodeBuilder *builder)
{
if (--builder->refcount == 0) {
/* free private data */
builder->free(builder);
free(builder);
}
}
static
int default_create_file(IsoNodeBuilder *builder, IsoImage *image,
IsoFileSource *src, IsoFile **file)
{
int ret;
struct stat info;
IsoStream *stream;
IsoFile *node;
char *name;
if (builder == NULL || src == NULL || file == NULL) {
return ISO_NULL_POINTER;
}
ret = iso_file_source_stat(src, &info);
if (ret < 0) {
return ret;
}
/* this will fail if src is a dir, is not accessible... */
ret = iso_file_source_stream_new(src, &stream);
if (ret < 0) {
return ret;
}
name = iso_file_source_get_name(src);
ret = iso_node_new_file(name, stream, &node);
if (ret < 0) {
/* the stream has taken our ref to src, so we need to add one */
iso_file_source_ref(src);
iso_stream_unref(stream);
free(name);
return ret;
}
/* fill node fields */
iso_node_set_permissions((IsoNode*)node, info.st_mode);
iso_node_set_uid((IsoNode*)node, info.st_uid);
iso_node_set_gid((IsoNode*)node, info.st_gid);
iso_node_set_atime((IsoNode*)node, info.st_atime);
iso_node_set_mtime((IsoNode*)node, info.st_mtime);
iso_node_set_ctime((IsoNode*)node, info.st_ctime);
iso_node_set_uid((IsoNode*)node, info.st_uid);
*file = node;
return ISO_SUCCESS;
}
static
int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
IsoFileSource *src, IsoNode **node)
{
int ret;
struct stat info;
IsoNode *new;
char *name;
if (builder == NULL || src == NULL || node == NULL) {
return ISO_NULL_POINTER;
}
/* get info about source */
if (iso_tree_get_follow_symlinks(image)) {
ret = iso_file_source_stat(src, &info);
} else {
ret = iso_file_source_lstat(src, &info);
}
if (ret < 0) {
return ret;
}
name = iso_file_source_get_name(src);
new = NULL;
switch (info.st_mode & S_IFMT) {
case S_IFREG:
{
/* source is a regular file */
IsoStream *stream;
IsoFile *file;
ret = iso_file_source_stream_new(src, &stream);
if (ret < 0) {
break;
}
/* take a ref to the src, as stream has taken our ref */
iso_file_source_ref(src);
/* create the file */
ret = iso_node_new_file(name, stream, &file);
if (ret < 0) {
iso_stream_unref(stream);
}
new = (IsoNode*) file;
}
break;
case S_IFDIR:
{
/* source is a directory */
IsoDir *dir;
ret = iso_node_new_dir(name, &dir);
new = (IsoNode*)dir;
}
break;
case S_IFLNK:
{
/* source is a symbolic link */
char dest[PATH_MAX];
IsoSymlink *link;
ret = iso_file_source_readlink(src, dest, PATH_MAX);
if (ret < 0) {
break;
}
ret = iso_node_new_symlink(name, strdup(dest), &link);
new = (IsoNode*) link;
}
break;
case S_IFSOCK:
case S_IFBLK:
case S_IFCHR:
case S_IFIFO:
{
/* source is an special file */
IsoSpecial *special;
ret = iso_node_new_special(name, info.st_mode, info.st_rdev,
&special);
new = (IsoNode*) special;
}
break;
}
if (ret < 0) {
free(name);
return ret;
}
/* fill fields */
iso_node_set_permissions(new, info.st_mode);
iso_node_set_uid(new, info.st_uid);
iso_node_set_gid(new, info.st_gid);
iso_node_set_atime(new, info.st_atime);
iso_node_set_mtime(new, info.st_mtime);
iso_node_set_ctime(new, info.st_ctime);
iso_node_set_uid(new, info.st_uid);
*node = new;
return ISO_SUCCESS;
}
static
void default_free(IsoNodeBuilder *builder)
{
return;
}
int iso_node_basic_builder_new(IsoNodeBuilder **builder)
{
IsoNodeBuilder *b;
if (builder == NULL) {
return ISO_NULL_POINTER;
}
b = malloc(sizeof(IsoNodeBuilder));
if (b == NULL) {
return ISO_OUT_OF_MEM;
}
b->refcount = 1;
b->create_file_data = NULL;
b->create_node_data = NULL;
b->create_file = default_create_file;
b->create_node = default_create_node;
b->free = default_free;
*builder = b;
return ISO_SUCCESS;
}

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2007 Vreixo Formoso
*
* This file is part of the libisofs project; 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. See COPYING file for details.
*/
#ifndef LIBISO_BUILDER_H_
#define LIBISO_BUILDER_H_
/*
* Definitions for IsoNode builders.
*/
/*
* Some functions here will be moved to libisofs.h when we expose
* Builder.
*/
#include "libisofs.h"
#include "fsource.h"
typedef struct Iso_Node_Builder IsoNodeBuilder;
struct Iso_Node_Builder
{
/**
* Create a new IsoFile from an IsoFileSource. Name, permissions
* and other attributes are taken from src, but a regular file will
* always be created, even if src is another kind of file.
*
* In that case, if the implementation can't do the conversion, it
* should fail propertly.
*
* On sucess, the ref. to src will be owned by file, so you musn't
* unref it.
*
* @return
* 1 on success, < 0 on error
*/
int (*create_file)(IsoNodeBuilder *builder, IsoImage *image,
IsoFileSource *src, IsoFile **file);
/**
* Create a new IsoNode from a IsoFileSource. The type of the node to be
* created is determined from the type of the file source. Name,
* permissions and other attributes are taken from source file.
*
* Note that the src is never unref, so you need to free it.
*
* @return
* 1 on success, < 0 on error
*/
int (*create_node)(IsoNodeBuilder *builder, IsoImage *image,
IsoFileSource *src, IsoNode **node);
/**
* Free implementation specific data. Should never be called by user.
* Use iso_node_builder_unref() instead.
*/
void (*free)(IsoNodeBuilder *builder);
int refcount;
void *create_file_data;
void *create_node_data;
};
void iso_node_builder_ref(IsoNodeBuilder *builder);
void iso_node_builder_unref(IsoNodeBuilder *builder);
/**
* Create a new basic builder ...
*
* @return
* 1 success, < 0 error
*/
int iso_node_basic_builder_new(IsoNodeBuilder **builder);
#endif /*LIBISO_BUILDER_H_*/

View File

@ -0,0 +1,195 @@
/*
* Copyright (c) 2007 Vreixo Formoso
*
* This file is part of the libisofs project; 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. See COPYING file for details.
*/
#include "libisofs.h"
#include "util.h"
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/**
* Private data for File IsoDataSource
*/
struct file_data_src
{
char *path;
int fd;
};
/**
* Increments the reference counting of the given IsoDataSource.
*/
void iso_data_source_ref(IsoDataSource *src)
{
src->refcount++;
}
/**
* Decrements the reference counting of the given IsoDataSource, freeing it
* if refcount reach 0.
*/
void iso_data_source_unref(IsoDataSource *src)
{
if (--src->refcount == 0) {
src->free_data(src);
free(src);
}
}
static
int ds_open(IsoDataSource *src)
{
int fd;
struct file_data_src *data;
if (src == NULL || src->data == NULL) {
return ISO_NULL_POINTER;
}
data = (struct file_data_src*) src->data;
if (data->fd != -1) {
return ISO_FILE_ALREADY_OPENED;
}
fd = open(data->path, O_RDONLY);
if (fd == -1) {
return ISO_FILE_ERROR;
}
data->fd = fd;
return ISO_SUCCESS;
}
static
int ds_close(IsoDataSource *src)
{
int ret;
struct file_data_src *data;
if (src == NULL || src->data == NULL) {
return ISO_NULL_POINTER;
}
data = (struct file_data_src*) src->data;
if (data->fd == -1) {
return ISO_FILE_NOT_OPENED;
}
/* close can fail if fd is not valid, but that should never happen */
ret = close(data->fd);
/* in any case we mark file as closed */
data->fd = -1;
return ret == 0 ? ISO_SUCCESS : ISO_FILE_ERROR;
}
static int ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
{
struct file_data_src *data;
if (src == NULL || src->data == NULL || buffer == NULL) {
return ISO_NULL_POINTER;
}
data = (struct file_data_src*) src->data;
if (data->fd == -1) {
return ISO_FILE_NOT_OPENED;
}
/* goes to requested block */
if (lseek(data->fd, (off_t)lba * (off_t)2048, SEEK_SET) == (off_t) -1) {
return ISO_FILE_SEEK_ERROR;
}
/* TODO #00008 : guard against partial reads. */
if (read(data->fd, buffer, 2048) != 2048) {
return ISO_FILE_READ_ERROR;
}
return ISO_SUCCESS;
}
static
void ds_free_data(IsoDataSource *src)
{
struct file_data_src *data;
data = (struct file_data_src*)src->data;
/* close the file if needed */
if (data->fd != -1) {
close(data->fd);
}
free(data->path);
free(data);
}
/**
* Create a new IsoDataSource from a local file. This is suitable for
* accessing regular .iso images, or to acces drives via its block device
* and standard POSIX I/O calls.
*
* @param path
* The path of the file
* @param src
* Will be filled with the pointer to the newly created data source.
* @return
* 1 on success, < 0 on error.
*/
int iso_data_source_new_from_file(const char *path, IsoDataSource **src)
{
int ret;
struct file_data_src *data;
IsoDataSource *ds;
if (path == NULL || src == NULL) {
return ISO_NULL_POINTER;
}
/* ensure we have read access to the file */
ret = iso_eaccess(path);
if (ret < 0) {
return ret;
}
data = malloc(sizeof(struct file_data_src));
if (data == NULL) {
return ISO_OUT_OF_MEM;
}
ds = malloc(sizeof(IsoDataSource));
if (ds == NULL) {
free(data);
return ISO_OUT_OF_MEM;
}
/* fill data fields */
data->path = strdup(path);
if (data->path == NULL) {
free(data);
free(ds);
return ISO_OUT_OF_MEM;
}
data->fd = -1;
ds->version = 0;
ds->refcount = 1;
ds->data = data;
ds->open = ds_open;
ds->close = ds_close;
ds->read_block = ds_read_block;
ds->free_data = ds_free_data;
*src = ds;
return ISO_SUCCESS;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,476 @@
/*
* Copyright (c) 2007 Vreixo Formoso
*
* This file is part of the libisofs project; 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. See COPYING file for details.
*/
#ifndef LIBISO_ECMA119_H_
#define LIBISO_ECMA119_H_
#include "libisofs.h"
#include "util.h"
#include "buffer.h"
#include <stdint.h>
#include <pthread.h>
#define BLOCK_SIZE 2048
/**
* Holds the options for the image generation.
*/
struct iso_write_opts {
int level; /**< ISO level to write at. (ECMA-119, 10) */
/** Which extensions to support. */
unsigned int rockridge :1;
unsigned int joliet :1;
unsigned int iso1999 :1;
/* allways write timestamps in GMT */
unsigned int always_gmt :1;
/*
* 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 all characters to be part of Volume and Volset identifiers on
* the Primary Volume Descriptor. This breaks ISO-9660 contraints, but
* should work on modern systems.
*/
unsigned int relaxed_vol_atts :1;
/**
* Allow paths in the Joliet tree to have more than 240 characters.
*/
unsigned int joliet_longer_paths :1;
/** If files should be sorted based on their weight. */
unsigned int sort_files :1;
/**
* 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 setted 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. */
/**
* 0 to use IsoNode timestamps, 1 to use recording time, 2 to use
* values from timestamp field. This has only meaning if RR extensions
* are enabled.
*/
unsigned int replace_timestamps :2;
time_t timestamp;
/**
* Charset for the RR filenames that will be created.
* NULL to use default charset, the locale one.
*/
char *output_charset;
/**
* This flags control the type of the image to create. Libisofs support
* two kind of images: stand-alone and appendable.
*
* A stand-alone image is an image that is valid alone, and that can be
* mounted by its own. This is the kind of image you will want to create
* in most cases. A stand-alone image can be burned in an empty CD or DVD,
* or write to an .iso file for future burning or distribution.
*
* On the other side, an appendable image is not self contained, it refers
* to serveral files that are stored outside the image. Its usage is for
* multisession discs, where you add data in a new session, while the
* previous session data can still be accessed. In those cases, the old
* data is not written again. Instead, the new image refers to it, and thus
* it's only valid when appended to the original. Note that in those cases
* the image will be written after the original, and thus you will want
* to use a ms_block greater than 0.
*
* Note that if you haven't import a previous image (by means of
* iso_image_import()), the image will always be a stand-alone image, as
* there is no previous data to refer to.
*/
unsigned int appendable : 1;
/**
* Start block of the image. It is supposed to be the lba where the first
* block of the image will be written on disc. All references inside the
* ISO image will take this into account, thus providing a mountable image.
*
* For appendable images, that are written to a new session, you should
* pass here the lba of the next writable address on disc.
*
* In stand alone images this is usually 0. However, you may want to
* provide a different ms_block if you don't plan to burn the image in the
* first session on disc, such as in some CD-Extra disc whether the data
* image is written in a new session after some audio tracks.
*/
uint32_t ms_block;
/**
* When not NULL, it should point to a buffer of at least 64KiB, where
* libisofs will write the contents that should be written at the beginning
* of a overwriteable media, to grow the image. The growing of an image is
* a way, used by first time in growisofs by Andy Polyakov, to allow the
* appending of new data to non-multisession media, such as DVD+RW, in the
* same way you append a new session to a multisession disc, i.e., without
* need to write again the contents of the previous image.
*
* Note that if you want this kind of image growing, you will also need to
* set appendable to "1" and provide a valid ms_block after the previous
* image.
*
* You should initialize the buffer either with 0s, or with the contents of
* the first blocks of the image you're growing. In most cases, 0 is good
* enought.
*/
uint8_t *overwrite;
/**
* Size, in number of blocks, of the FIFO buffer used between the writer
* thread and the burn_source. You have to provide at least a 32 blocks
* buffer.
*/
size_t fifo_size;
};
typedef struct ecma119_image Ecma119Image;
typedef struct ecma119_node Ecma119Node;
typedef struct joliet_node JolietNode;
typedef struct iso1999_node Iso1999Node;
typedef struct Iso_File_Src IsoFileSrc;
typedef struct Iso_Image_Writer IsoImageWriter;
struct ecma119_image
{
IsoImage *image;
Ecma119Node *root;
unsigned int iso_level :2;
/* extensions */
unsigned int rockridge :1;
unsigned int joliet :1;
unsigned int eltorito :1;
unsigned int iso1999 :1;
/* allways write timestamps in GMT */
unsigned int always_gmt :1;
/* relaxed constraints */
unsigned int omit_version_numbers :1;
unsigned int allow_deep_paths :1;
unsigned int allow_longer_paths :1;
unsigned int max_37_char_filenames :1;
unsigned int no_force_dots :1;
unsigned int allow_lowercase :1;
unsigned int allow_full_ascii :1;
unsigned int relaxed_vol_atts : 1;
/** Allow paths on Joliet tree to be larger than 240 bytes */
unsigned int joliet_longer_paths :1;
/*
* Mode replace. If one of these flags is set, the correspodent values are
* replaced with values below.
*/
unsigned int replace_uid :1;
unsigned int replace_gid :1;
unsigned int replace_file_mode :1;
unsigned int replace_dir_mode :1;
unsigned int replace_timestamps :1;
uid_t uid;
gid_t gid;
mode_t file_mode;
mode_t dir_mode;
time_t timestamp;
/**
* if sort files or not. Sorting is based of the weight of each file
*/
int sort_files;
/**
* In the CD, each file must have an unique inode number. So each
* time we add a new file, this is incremented.
*/
ino_t ino;
char *input_charset;
char *output_charset;
unsigned int appendable : 1;
uint32_t ms_block; /**< start block for a ms image */
time_t now; /**< Time at which writing began. */
/** Total size of the output. This only includes the current volume. */
off_t total_size;
uint32_t vol_space_size;
/* Bytes already written, just for progress notification */
off_t bytes_written;
int percent_written;
/*
* Block being processed, either during image writing or structure
* size calculation.
*/
uint32_t curblock;
/*
* number of dirs in ECMA-119 tree, computed together with dir position,
* and needed for path table computation in a efficient way
*/
size_t ndirs;
uint32_t path_table_size;
uint32_t l_path_table_pos;
uint32_t m_path_table_pos;
/*
* Joliet related information
*/
JolietNode *joliet_root;
size_t joliet_ndirs;
uint32_t joliet_path_table_size;
uint32_t joliet_l_path_table_pos;
uint32_t joliet_m_path_table_pos;
/*
* ISO 9660:1999 related information
*/
Iso1999Node *iso1999_root;
size_t iso1999_ndirs;
uint32_t iso1999_path_table_size;
uint32_t iso1999_l_path_table_pos;
uint32_t iso1999_m_path_table_pos;
/*
* El-Torito related information
*/
struct el_torito_boot_catalog *catalog;
IsoFileSrc *cat; /**< location of the boot catalog in the new image */
IsoFileSrc *bootimg; /**< location of the boot image in the new image */
/*
* Number of pad blocks that we need to write. Padding blocks are blocks
* filled by 0s that we put between the directory structures and the file
* data. These padding blocks are added by libisofs to improve the handling
* of image growing. The idea is that the first blocks in the image are
* overwritten with the volume descriptors of the new image. These first
* blocks usually correspond to the volume descriptors and directory
* structure of the old image, and can be safety overwritten. However,
* with very small images they might correspond to valid data. To ensure
* this never happens, what we do is to add padding bytes, to ensure no
* file data is written in the first 64 KiB, that are the bytes we usually
* overwrite.
*/
uint32_t pad_blocks;
size_t nwriters;
IsoImageWriter **writers;
/* tree of files sources */
IsoRBTree *files;
/* Buffer for communication between burn_source and writer thread */
IsoRingBuffer *buffer;
/* writer thread descriptor */
pthread_t wthread;
pthread_attr_t th_attr;
};
#define BP(a,b) [(b) - (a) + 1]
/* ECMA-119, 8.4 */
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);
};
/* ECMA-119, 8.5 */
struct ecma119_sup_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 vol_flags 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 esc_sequences 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);
};
/* ECMA-119, 8.2 */
struct ecma119_boot_rec_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 boot_sys_id BP(8, 39);
uint8_t boot_id BP(40, 71);
uint8_t boot_catalog BP(72, 75);
uint8_t unused BP(76, 2048);
};
/* ECMA-119, 9.1 */
struct ecma119_dir_record
{
uint8_t len_dr BP(1, 1);
uint8_t len_xa BP(2, 2);
uint8_t block BP(3, 10);
uint8_t length BP(11, 18);
uint8_t recording_time BP(19, 25);
uint8_t flags BP(26, 26);
uint8_t file_unit_size BP(27, 27);
uint8_t interleave_gap_size BP(28, 28);
uint8_t vol_seq_number BP(29, 32);
uint8_t len_fi BP(33, 33);
uint8_t file_id BP(34, 34); /* 34 to 33+len_fi */
/* padding field (if len_fi is even) */
/* system use (len_dr - len_su + 1 to len_dr) */
};
/* ECMA-119, 9.4 */
struct ecma119_path_table_record
{
uint8_t len_di BP(1, 1);
uint8_t len_xa BP(2, 2);
uint8_t block BP(3, 6);
uint8_t parent BP(7, 8);
uint8_t dir_id BP(9, 9); /* 9 to 8+len_di */
/* padding field (if len_di is odd) */
};
/* ECMA-119, 8.3 */
struct ecma119_vol_desc_terminator
{
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 reserved BP(8, 2048);
};
#endif /*LIBISO_ECMA119_H_*/

View File

@ -0,0 +1,846 @@
/*
* Copyright (c) 2007 Vreixo Formoso
*
* This file is part of the libisofs project; 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. See COPYING file for details.
*/
#include "ecma119_tree.h"
#include "ecma119.h"
#include "node.h"
#include "util.h"
#include "filesrc.h"
#include "messages.h"
#include "image.h"
#include "stream.h"
#include "eltorito.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
static
int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name)
{
int ret, relaxed;
char *ascii_name;
char *isoname= NULL;
if (iso->name == NULL) {
/* it is not necessarily an error, it can be the root */
return ISO_SUCCESS;
}
ret = str2ascii(img->input_charset, iso->name, &ascii_name);
if (ret < 0) {
iso_msg_submit(img->image->id, ret, 0, "Can't convert %s", iso->name);
return ret;
}
if (img->allow_full_ascii) {
relaxed = 2;
} else {
relaxed = (int)img->allow_lowercase;
}
if (iso->type == LIBISO_DIR) {
if (img->max_37_char_filenames) {
isoname = iso_r_dirid(ascii_name, 37, relaxed);
} else if (img->iso_level == 1) {
if (relaxed) {
isoname = iso_r_dirid(ascii_name, 8, relaxed);
} else {
isoname = iso_1_dirid(ascii_name);
}
} else {
if (relaxed) {
isoname = iso_r_dirid(ascii_name, 8, relaxed);
} else {
isoname = iso_2_dirid(ascii_name);
}
}
} else {
if (img->max_37_char_filenames) {
isoname = iso_r_fileid(ascii_name, 36, relaxed,
img->no_force_dots ? 0 : 1);
} else if (img->iso_level == 1) {
if (relaxed) {
isoname = iso_r_fileid(ascii_name, 11, relaxed,
img->no_force_dots ? 0 : 1);
} else {
isoname = iso_1_fileid(ascii_name);
}
} else {
if (relaxed) {
isoname = iso_r_fileid(ascii_name, 30, relaxed,
img->no_force_dots ? 0 : 1);
} else {
isoname = iso_2_fileid(ascii_name);
}
}
}
free(ascii_name);
if (isoname != NULL) {
*name = isoname;
return ISO_SUCCESS;
} else {
/*
* only possible if mem error, as check for empty names is done
* in public tree
*/
return ISO_OUT_OF_MEM;
}
}
static
int create_ecma119_node(Ecma119Image *img, IsoNode *iso, Ecma119Node **node)
{
Ecma119Node *ecma;
ecma = calloc(1, sizeof(Ecma119Node));
if (ecma == NULL) {
return ISO_OUT_OF_MEM;
}
/* take a ref to the IsoNode */
ecma->node = iso;
iso_node_ref(iso);
/* TODO #00009 : add true support for harlinks and inode numbers */
ecma->nlink = 1;
ecma->ino = ++img->ino;
*node = ecma;
return ISO_SUCCESS;
}
/**
* Create a new ECMA-119 node representing a directory from a iso directory
* node.
*/
static
int create_dir(Ecma119Image *img, IsoDir *iso, Ecma119Node **node)
{
int ret;
Ecma119Node **children;
struct ecma119_dir_info *dir_info;
children = calloc(1, sizeof(void*) * iso->nchildren);
if (children == NULL) {
return ISO_OUT_OF_MEM;
}
dir_info = calloc(1, sizeof(struct ecma119_dir_info));
if (dir_info == NULL) {
free(children);
return ISO_OUT_OF_MEM;
}
ret = create_ecma119_node(img, (IsoNode*)iso, node);
if (ret < 0) {
free(children);
free(dir_info);
return ret;
}
(*node)->type = ECMA119_DIR;
(*node)->info.dir = dir_info;
(*node)->info.dir->nchildren = 0;
(*node)->info.dir->children = children;
return ISO_SUCCESS;
}
/**
* Create a new ECMA-119 node representing a regular file from a iso file
* node.
*/
static
int create_file(Ecma119Image *img, IsoFile *iso, Ecma119Node **node)
{
int ret;
IsoFileSrc *src;
off_t size;
size = iso_stream_get_size(iso->stream);
if (size > (off_t)0xffffffff) {
return iso_msg_submit(img->image->id, ISO_FILE_TOO_BIG, 0,
"File \"%s\" can't be added to image because "
"is greater than 4GB", iso->node.name);
}
ret = iso_file_src_create(img, iso, &src);
if (ret < 0) {
return ret;
}
ret = create_ecma119_node(img, (IsoNode*)iso, node);
if (ret < 0) {
/*
* the src doesn't need to be freed, it is free together with
* the Ecma119Image
*/
return ret;
}
(*node)->type = ECMA119_FILE;
(*node)->info.file = src;
return ret;
}
/**
* Create a new ECMA-119 node representing a regular file from an El-Torito
* boot catalog
*/
static
int create_boot_cat(Ecma119Image *img, IsoBoot *iso, Ecma119Node **node)
{
int ret;
IsoFileSrc *src;
ret = el_torito_catalog_file_src_create(img, &src);
if (ret < 0) {
return ret;
}
ret = create_ecma119_node(img, (IsoNode*)iso, node);
if (ret < 0) {
/*
* the src doesn't need to be freed, it is free together with
* the Ecma119Image
*/
return ret;
}
(*node)->type = ECMA119_FILE;
(*node)->info.file = src;
return ret;
}
/**
* Create a new ECMA-119 node representing a symbolic link from a iso symlink
* node.
*/
static
int create_symlink(Ecma119Image *img, IsoSymlink *iso, Ecma119Node **node)
{
int ret;
ret = create_ecma119_node(img, (IsoNode*)iso, node);
if (ret < 0) {
return ret;
}
(*node)->type = ECMA119_SYMLINK;
return ISO_SUCCESS;
}
/**
* Create a new ECMA-119 node representing a special file.
*/
static
int create_special(Ecma119Image *img, IsoSpecial *iso, Ecma119Node **node)
{
int ret;
ret = create_ecma119_node(img, (IsoNode*)iso, node);
if (ret < 0) {
return ret;
}
(*node)->type = ECMA119_SPECIAL;
return ISO_SUCCESS;
}
void ecma119_node_free(Ecma119Node *node)
{
if (node == NULL) {
return;
}
if (node->type == ECMA119_DIR) {
int i;
for (i = 0; i < node->info.dir->nchildren; i++) {
ecma119_node_free(node->info.dir->children[i]);
}
free(node->info.dir->children);
free(node->info.dir);
}
free(node->iso_name);
iso_node_unref(node->node);
free(node);
}
/**
*
* @return
* 1 success, 0 node ignored, < 0 error
*
*/
static
int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree,
int depth, int pathlen)
{
int ret;
Ecma119Node *node;
int max_path;
char *iso_name= NULL;
if (image == NULL || iso == NULL || tree == NULL) {
return ISO_NULL_POINTER;
}
if (iso->hidden & LIBISO_HIDE_ON_RR) {
/* file will be ignored */
return 0;
}
ret = get_iso_name(image, iso, &iso_name);
if (ret < 0) {
return ret;
}
max_path = pathlen + 1 + (iso_name ? strlen(iso_name) : 0);
if (!image->rockridge) {
if ((iso->type == LIBISO_DIR && depth > 8) && !image->allow_deep_paths) {
free(iso_name);
return iso_msg_submit(image->image->id, ISO_FILE_IMGPATH_WRONG, 0,
"File \"%s\" can't be added, because directory depth "
"is greater than 8.", iso->name);
} else if (max_path > 255 && !image->allow_longer_paths) {
free(iso_name);
return iso_msg_submit(image->image->id, ISO_FILE_IMGPATH_WRONG, 0,
"File \"%s\" can't be added, because path length "
"is greater than 255 characters", iso->name);
}
}
switch (iso->type) {
case LIBISO_FILE:
ret = create_file(image, (IsoFile*)iso, &node);
break;
case LIBISO_SYMLINK:
if (image->rockridge) {
ret = create_symlink(image, (IsoSymlink*)iso, &node);
} else {
/* symlinks are only supported when RR is enabled */
ret = iso_msg_submit(image->image->id, ISO_FILE_IGNORED, 0,
"File \"%s\" ignored. Symlinks need RockRidge extensions.",
iso->name);
}
break;
case LIBISO_SPECIAL:
if (image->rockridge) {
ret = create_special(image, (IsoSpecial*)iso, &node);
} else {
/* symlinks are only supported when RR is enabled */
ret = iso_msg_submit(image->image->id, ISO_FILE_IGNORED, 0,
"File \"%s\" ignored. Special files need RockRidge extensions.",
iso->name);
}
break;
case LIBISO_BOOT:
if (image->eltorito) {
ret = create_boot_cat(image, (IsoBoot*)iso, &node);
} else {
/* log and ignore */
ret = iso_msg_submit(image->image->id, ISO_FILE_IGNORED, 0,
"El-Torito catalog found on a image without El-Torito.",
iso->name);
}
break;
case LIBISO_DIR:
{
IsoNode *pos;
IsoDir *dir = (IsoDir*)iso;
ret = create_dir(image, dir, &node);
if (ret < 0) {
return ret;
}
pos = dir->children;
while (pos) {
int cret;
Ecma119Node *child;
cret = create_tree(image, pos, &child, depth + 1, max_path);
if (cret < 0) {
/* error */
ecma119_node_free(node);
ret = cret;
break;
} else if (cret == ISO_SUCCESS) {
/* add child to this node */
int nchildren = node->info.dir->nchildren++;
node->info.dir->children[nchildren] = child;
child->parent = node;
}
pos = pos->next;
}
}
break;
default:
/* should never happen */
return ISO_ASSERT_FAILURE;
}
if (ret <= 0) {
free(iso_name);
return ret;
}
node->iso_name = iso_name;
*tree = node;
return ISO_SUCCESS;
}
/**
* Compare the iso name of two ECMA-119 nodes
*/
static
int cmp_node_name(const void *f1, const void *f2)
{
Ecma119Node *f = *((Ecma119Node**)f1);
Ecma119Node *g = *((Ecma119Node**)f2);
return strcmp(f->iso_name, g->iso_name);
}
/**
* Sorts a the children of each directory in the ECMA-119 tree represented
* by \p root, acording to the order specified in ECMA-119, section 9.3.
*/
static
void sort_tree(Ecma119Node *root)
{
size_t i;
qsort(root->info.dir->children, root->info.dir->nchildren, sizeof(void*),
cmp_node_name);
for (i = 0; i < root->info.dir->nchildren; i++) {
if (root->info.dir->children[i]->type == ECMA119_DIR)
sort_tree(root->info.dir->children[i]);
}
}
/**
* Ensures that the ISO name of each children of the given dir is unique,
* changing some of them if needed.
* It also ensures that resulting filename is always <= than given
* max_name_len, including extension. If needed, the extension will be reduced,
* but never under 3 characters.
*/
static
int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
int max_dir_len)
{
int ret;
int i, nchildren;
Ecma119Node **children;
IsoHTable *table;
int need_sort = 0;
nchildren = dir->info.dir->nchildren;
children = dir->info.dir->children;
/* a hash table will temporary hold the names, for fast searching */
ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash,
(compare_function_t)strcmp, &table);
if (ret < 0) {
return ret;
}
for (i = 0; i < nchildren; ++i) {
char *name = children[i]->iso_name;
ret = iso_htable_add(table, name, name);
if (ret < 0) {
goto mangle_cleanup;
}
}
for (i = 0; i < nchildren; ++i) {
char *name, *ext;
char full_name[40];
int max; /* computed max len for name, without extension */
int j = i;
int digits = 1; /* characters to change per name */
/* first, find all child with same name */
while (j + 1 < nchildren && !cmp_node_name(children + i, children + j
+ 1)) {
++j;
}
if (j == i) {
/* name is unique */
continue;
}
/*
* A max of 7 characters is good enought, it allows handling up to
* 9,999,999 files with same name. We can increment this to
* max_name_len, but the int_pow() function must then be modified
* to return a bigger integer.
*/
while (digits < 8) {
int ok, k;
char *dot;
int change = 0; /* number to be written */
/* copy name to buffer */
strcpy(full_name, children[i]->iso_name);
/* compute name and extension */
dot = strrchr(full_name, '.');
if (dot != NULL && children[i]->type != ECMA119_DIR) {
/*
* File (not dir) with extension
* Note that we don't need to check for placeholders, as
* tree reparent happens later, so no placeholders can be
* here at this time.
*/
int extlen;
full_name[dot - full_name] = '\0';
name = full_name;
ext = dot + 1;
/*
* For iso level 1 we force ext len to be 3, as name
* can't grow on the extension space
*/
extlen = (max_file_len == 12) ? 3 : strlen(ext);
max = max_file_len - extlen - 1 - digits;
if (max <= 0) {
/* this can happen if extension is too long */
if (extlen + max > 3) {
/*
* reduce extension len, to give name an extra char
* note that max is negative or 0
*/
extlen = extlen + max - 1;
ext[extlen] = '\0';
max = max_file_len - extlen - 1 - digits;
} else {
/*
* error, we don't support extensions < 3
* This can't happen with current limit of digits.
*/
ret = ISO_ERROR;
goto mangle_cleanup;
}
}
/* ok, reduce name by digits */
if (name + max < dot) {
name[max] = '\0';
}
} else {
/* Directory, or file without extension */
if (children[i]->type == ECMA119_DIR) {
max = max_dir_len - digits;
dot = NULL; /* dots have no meaning in dirs */
} else {
max = max_file_len - digits;
}
name = full_name;
if (max < strlen(name)) {
name[max] = '\0';
}
/* let ext be an empty string */
ext = name + strlen(name);
}
ok = 1;
/* change name of each file */
for (k = i; k <= j; ++k) {
char tmp[40];
char fmt[16];
if (dot != NULL) {
sprintf(fmt, "%%s%%0%dd.%%s", digits);
} else {
sprintf(fmt, "%%s%%0%dd%%s", digits);
}
while (1) {
sprintf(tmp, fmt, name, change, ext);
++change;
if (change > int_pow(10, digits)) {
ok = 0;
break;
}
if (!iso_htable_get(table, tmp, NULL)) {
/* the name is unique, so it can be used */
break;
}
}
if (ok) {
char *new = strdup(tmp);
if (new == NULL) {
ret = ISO_OUT_OF_MEM;
goto mangle_cleanup;
}
iso_msg_debug(img->image->id, "\"%s\" renamed to \"%s\"",
children[k]->iso_name, new);
iso_htable_remove_ptr(table, children[k]->iso_name, NULL);
free(children[k]->iso_name);
children[k]->iso_name = new;
iso_htable_add(table, new, new);
/*
* if we change a name we need to sort again children
* at the end
*/
need_sort = 1;
} else {
/* we need to increment digits */
break;
}
}
if (ok) {
break;
} else {
++digits;
}
}
if (digits == 8) {
ret = ISO_MANGLE_TOO_MUCH_FILES;
goto mangle_cleanup;
}
i = j;
}
/*
* If needed, sort again the files inside dir
*/
if (need_sort) {
qsort(children, nchildren, sizeof(void*), cmp_node_name);
}
ret = ISO_SUCCESS;
mangle_cleanup : ;
iso_htable_destroy(table, NULL);
return ret;
}
static
int mangle_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
int max_dir_len)
{
int ret;
size_t i;
ret = mangle_single_dir(img, dir, max_file_len, max_dir_len);
if (ret < 0) {
return ret;
}
/* recurse */
for (i = 0; i < dir->info.dir->nchildren; ++i) {
if (dir->info.dir->children[i]->type == ECMA119_DIR) {
ret = mangle_dir(img, dir->info.dir->children[i], max_file_len,
max_dir_len);
if (ret < 0) {
/* error */
return ret;
}
}
}
return ISO_SUCCESS;
}
static
int mangle_tree(Ecma119Image *img, int recurse)
{
int max_file, max_dir;
if (img->max_37_char_filenames) {
max_file = max_dir = 37;
} else if (img->iso_level == 1) {
max_file = 12; /* 8 + 3 + 1 */
max_dir = 8;
} else {
max_file = max_dir = 31;
}
if (recurse) {
return mangle_dir(img, img->root, max_file, max_dir);
} else {
return mangle_single_dir(img, img->root, max_file, max_dir);
}
}
/**
* Create a new ECMA-119 node representing a placeholder for a relocated
* dir.
*
* See IEEE P1282, section 4.1.5 for details
*/
static
int create_placeholder(Ecma119Node *parent, Ecma119Node *real,
Ecma119Node **node)
{
Ecma119Node *ret;
ret = calloc(1, sizeof(Ecma119Node));
if (ret == NULL) {
return ISO_OUT_OF_MEM;
}
/*
* TODO
* If real is a dir, while placeholder is a file, ISO name restricctions
* are different, what to do?
*/
ret->iso_name = strdup(real->iso_name);
if (ret->iso_name == NULL) {
free(ret);
return ISO_OUT_OF_MEM;
}
/* take a ref to the IsoNode */
ret->node = real->node;
iso_node_ref(real->node);
ret->parent = parent;
ret->type = ECMA119_PLACEHOLDER;
ret->info.real_me = real;
ret->ino = real->ino;
ret->nlink = real->nlink;
*node = ret;
return ISO_SUCCESS;
}
static
size_t max_child_name_len(Ecma119Node *dir)
{
size_t ret = 0, i;
for (i = 0; i < dir->info.dir->nchildren; i++) {
size_t len = strlen(dir->info.dir->children[i]->iso_name);
ret = MAX(ret, len);
}
return ret;
}
/**
* Relocates a directory, as specified in Rock Ridge Specification
* (see IEEE P1282, section 4.1.5). This is needed when the number of levels
* on a directory hierarchy exceeds 8, or the length of a path is higher
* than 255 characters, as specified in ECMA-119, section 6.8.2.1
*/
static
int reparent(Ecma119Node *child, Ecma119Node *parent)
{
int ret;
size_t i;
Ecma119Node *placeholder;
/* replace the child in the original parent with a placeholder */
for (i = 0; i < child->parent->info.dir->nchildren; i++) {
if (child->parent->info.dir->children[i] == child) {
ret = create_placeholder(child->parent, child, &placeholder);
if (ret < 0) {
return ret;
}
child->parent->info.dir->children[i] = placeholder;
break;
}
}
/* just for debug, this should never happen... */
if (i == child->parent->info.dir->nchildren) {
return ISO_ASSERT_FAILURE;
}
/* keep track of the real parent */
child->info.dir->real_parent = child->parent;
/* add the child to its new parent */
child->parent = parent;
parent->info.dir->nchildren++;
parent->info.dir->children = realloc(parent->info.dir->children,
sizeof(void*) * parent->info.dir->nchildren);
parent->info.dir->children[parent->info.dir->nchildren - 1] = child;
return ISO_SUCCESS;
}
/**
* Reorder the tree, if necessary, to ensure that
* - the depth is at most 8
* - each path length is at most 255 characters
* This restriction is imposed by ECMA-119 specification (ECMA-119, 6.8.2.1).
*
* @param dir
* Dir we are currently processing
* @param level
* Level of the directory in the hierarchy
* @param pathlen
* Length of the path until dir, including it
* @return
* 1 success, < 0 error
*/
static
int reorder_tree(Ecma119Image *img, Ecma119Node *dir, int level, int pathlen)
{
int ret;
size_t max_path;
max_path = pathlen + 1 + max_child_name_len(dir);
if (level > 8 || max_path > 255) {
ret = reparent(dir, img->root);
if (ret < 0) {
return ret;
}
/*
* we are appended to the root's children now, so there is no
* need to recurse (the root will hit us again)
*/
} else {
size_t i;
for (i = 0; i < dir->info.dir->nchildren; i++) {
Ecma119Node *child = dir->info.dir->children[i];
if (child->type == ECMA119_DIR) {
int newpathlen = pathlen + 1 + strlen(child->iso_name);
ret = reorder_tree(img, child, level + 1, newpathlen);
if (ret < 0) {
return ret;
}
}
}
}
return ISO_SUCCESS;
}
int ecma119_tree_create(Ecma119Image *img)
{
int ret;
Ecma119Node *root;
ret = create_tree(img, (IsoNode*)img->image->root, &root, 1, 0);
if (ret <= 0) {
if (ret == 0) {
/* unexpected error, root ignored!! This can't happen */
ret = ISO_ASSERT_FAILURE;
}
return ret;
}
img->root = root;
iso_msg_debug(img->image->id, "Sorting the low level tree...");
sort_tree(root);
iso_msg_debug(img->image->id, "Mangling names...");
ret = mangle_tree(img, 1);
if (ret < 0) {
return ret;
}
if (img->rockridge && !img->allow_deep_paths) {
/* reorder the tree, acording to RRIP, 4.1.5 */
ret = reorder_tree(img, img->root, 1, 0);
if (ret < 0) {
return ret;
}
/*
* and we need to remangle the root directory, as the function
* above could insert new directories into the root.
* Note that recurse = 0, as we don't need to recurse.
*/
ret = mangle_tree(img, 0);
if (ret < 0) {
return ret;
}
}
return ISO_SUCCESS;
}

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2007 Vreixo Formoso
*
* This file is part of the libisofs project; 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. See COPYING file for details.
*/
#ifndef LIBISO_ECMA119_TREE_H_
#define LIBISO_ECMA119_TREE_H_
#include "libisofs.h"
#include "ecma119.h"
enum ecma119_node_type {
ECMA119_FILE,
ECMA119_DIR,
ECMA119_SYMLINK,
ECMA119_SPECIAL,
ECMA119_PLACEHOLDER
};
/**
* Struct with info about a node representing a directory
*/
struct ecma119_dir_info
{
/* Block where the directory entries will be written on image */
size_t block;
size_t nchildren;
Ecma119Node **children;
/*
* Size of the dir, i.e., sum of the lengths of all directory records.
* It is computed by calc_dir_size() [ecma119.c].
* Note that this don't include the length of any SUSP Continuation
* Area needed by the dir, but it includes the size of the SUSP entries
* than fit in the directory records System Use Field.
*/
size_t len;
/**
* Real parent if the dir has been reallocated. NULL otherwise.
*/
Ecma119Node *real_parent;
};
/**
* A node for a tree containing all the information necessary for writing
* an ISO9660 volume.
*/
struct ecma119_node
{
/**
* Name in ASCII, conforming to selected ISO level.
* Version number is not include, it is added on the fly
*/
char *iso_name;
Ecma119Node *parent;
IsoNode *node; /*< reference to the iso node */
/* TODO #00009 : add true support for harlinks and inode numbers */
ino_t ino;
nlink_t nlink;
/**< file, symlink, special, directory or placeholder */
enum ecma119_node_type type;
union
{
IsoFileSrc *file;
struct ecma119_dir_info *dir;
/** this field points to the relocated directory. */
Ecma119Node *real_me;
} info;
};
/**
*
*/
int ecma119_tree_create(Ecma119Image *img);
/**
* Free an Ecma119Node, and its children if node is a dir
*/
void ecma119_node_free(Ecma119Node *node);
#endif /*LIBISO_ECMA119_TREE_H_*/

View File

@ -0,0 +1,908 @@
/*
* Copyright (c) 2007 Vreixo Formoso
*
* This file is part of the libisofs project; 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. See COPYING file for details.
*/
#include "eltorito.h"
#include "stream.h"
#include "fsource.h"
#include "filesrc.h"
#include "image.h"
#include "messages.h"
#include "writer.h"
#include <stdlib.h>
#include <string.h>
/**
* This table should be written with accuracy values at offset
* 8 of boot image, when used ISOLINUX boot loader
*/
struct boot_info_table {
uint8_t bi_pvd BP(1, 4); /* LBA of primary volume descriptor */
uint8_t bi_file BP(5, 8); /* LBA of boot file */
uint8_t bi_length BP(9, 12); /* Length of boot file */
uint8_t bi_csum BP(13, 16); /* Checksum of boot file */
uint8_t bi_reserved BP(17, 56); /* Reserved */
};
/**
* Structure for each one of the four entries in a partition table on a
* hard disk image.
*/
struct partition_desc {
uint8_t boot_ind;
uint8_t begin_chs[3];
uint8_t type;
uint8_t end_chs[3];
uint8_t start[4];
uint8_t size[4];
};
/**
* Structures for a Master Boot Record of a hard disk image.
*/
struct hard_disc_mbr {
uint8_t code_area[440];
uint8_t opt_disk_sg[4];
uint8_t pad[2];
struct partition_desc partition[4];
uint8_t sign1;
uint8_t sign2;
};
/**
* Sets the load segment for the initial boot image. This is only for
* no emulation boot images, and is a NOP for other image types.
*/
void el_torito_set_load_seg(ElToritoBootImage *bootimg, short segment)
{
if (bootimg->type != ELTORITO_NO_EMUL)
return;
bootimg->load_seg = segment;
}
/**
* Sets the number of sectors (512b) to be load at load segment during
* the initial boot procedure. This is only for no emulation boot images,
* and is a NOP for other image types.
*/
void el_torito_set_load_size(ElToritoBootImage *bootimg, short sectors)
{
if (bootimg->type != ELTORITO_NO_EMUL)
return;
bootimg->load_size = sectors;
}
/**
* Marks the specified boot image as not bootable
*/
void el_torito_set_no_bootable(ElToritoBootImage *bootimg)
{
bootimg->bootable = 0;
}
/**
* Specifies that this image needs to be patched. This involves the writting
* of a 56 bytes boot information table at offset 8 of the boot image file.
* The original boot image file won't be modified.
* This is needed for isolinux boot images.
*/
void el_torito_patch_isolinux_image(ElToritoBootImage *bootimg)
{
bootimg->isolinux = 1;
}
static
int iso_tree_add_boot_node(IsoDir *parent, const char *name, IsoBoot **boot)
{
IsoBoot *node;
IsoNode **pos;
time_t now;
if (parent == NULL || name == NULL || boot == NULL) {
return ISO_NULL_POINTER;
}
if (boot) {
*boot = NULL;
}
/* check if the name is valid */
if (!iso_node_is_valid_name(name)) {
return ISO_WRONG_ARG_VALUE;
}
/* find place where to insert */
pos = &(parent->children);
while (*pos != NULL && strcmp((*pos)->name, name) < 0) {
pos = &((*pos)->next);
}
if (*pos != NULL && !strcmp((*pos)->name, name)) {
/* a node with same name already exists */
return ISO_NODE_NAME_NOT_UNIQUE;
}
node = calloc(1, sizeof(IsoBoot));
if (node == NULL) {
return ISO_OUT_OF_MEM;
}
node->node.refcount = 1;
node->node.type = LIBISO_BOOT;
node->node.name = strdup(name);
if (node->node.name == NULL) {
free(node);
return ISO_OUT_OF_MEM;
}
/* atributes from parent */
node->node.mode = S_IFREG | (parent->node.mode & 0444);
node->node.uid = parent->node.uid;
node->node.gid = parent->node.gid;
node->node.hidden = parent->node.hidden;
/* current time */
now = time(NULL);
node->node.atime = now;
node->node.ctime = now;
node->node.mtime = now;
/* add to dir */
node->node.parent = parent;
node->node.next = *pos;
*pos = (IsoNode*)node;
if (boot) {
*boot = node;
}
return ++parent->nchildren;
}
static
int create_image(IsoImage *image, const char *image_path,
enum eltorito_boot_media_type type,
struct el_torito_boot_image **bootimg)
{
int ret;
struct el_torito_boot_image *boot;
int boot_media_type = 0;
int load_sectors = 0; /* number of sector to load */
unsigned char partition_type = 0;
IsoNode *imgfile;
IsoStream *stream;
ret = iso_tree_path_to_node(image, image_path, &imgfile);
if (ret < 0) {
return ret;
}
if (ret == 0) {
return ISO_NODE_DOESNT_EXIST;
}
if (imgfile->type != LIBISO_FILE) {
return ISO_BOOT_IMAGE_NOT_VALID;
}
stream = ((IsoFile*)imgfile)->stream;
/* we need to read the image at least two times */
if (!iso_stream_is_repeatable(stream)) {
return ISO_BOOT_IMAGE_NOT_VALID;
}
switch (type) {
case ELTORITO_FLOPPY_EMUL:
switch (iso_stream_get_size(stream)) {
case 1200 * 1024:
boot_media_type = 1; /* 1.2 meg diskette */
break;
case 1440 * 1024:
boot_media_type = 2; /* 1.44 meg diskette */
break;
case 2880 * 1024:
boot_media_type = 3; /* 2.88 meg diskette */
break;
default:
iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
"Invalid image size %d Kb. Must be one of 1.2, 1.44"
"or 2.88 Mb", iso_stream_get_size(stream) / 1024);
return ISO_BOOT_IMAGE_NOT_VALID;
break;
}
/* it seems that for floppy emulation we need to load
* a single sector (512b) */
load_sectors = 1;
break;
case ELTORITO_HARD_DISC_EMUL:
{
size_t i;
struct hard_disc_mbr mbr;
int used_partition;
/* read the MBR on disc and get the type of the partition */
ret = iso_stream_open(stream);
if (ret < 0) {
iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, ret,
"Can't open image file.");
return ret;
}
ret = iso_stream_read(stream, &mbr, sizeof(mbr));
iso_stream_close(stream);
if (ret != sizeof(mbr)) {
iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
"Can't read MBR from image file.");
return ret < 0 ? ret : ISO_FILE_READ_ERROR;
}
/* check valid MBR signature */
if ( mbr.sign1 != 0x55 || mbr.sign2 != 0xAA ) {
iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
"Invalid MBR. Wrong signature.");
return ISO_BOOT_IMAGE_NOT_VALID;
}
/* ensure single partition */
used_partition = -1;
for (i = 0; i < 4; ++i) {
if (mbr.partition[i].type != 0) {
/* it's an used partition */
if (used_partition != -1) {
iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
"Invalid MBR. At least 2 partitions: %d and "
"%d, are being used\n", used_partition, i);
return ISO_BOOT_IMAGE_NOT_VALID;
} else
used_partition = i;
}
}
partition_type = mbr.partition[used_partition].type;
}
boot_media_type = 4;
/* only load the MBR */
load_sectors = 1;
break;
case ELTORITO_NO_EMUL:
boot_media_type = 0;
break;
}
boot = calloc(1, sizeof(struct el_torito_boot_image));
if (boot == NULL) {
return ISO_OUT_OF_MEM;
}
boot->image = (IsoFile*)imgfile;
iso_node_ref(imgfile); /* get our ref */
boot->bootable = 1;
boot->type = boot_media_type;
boot->load_size = load_sectors;
boot->partition_type = partition_type;
if (bootimg) {
*bootimg = boot;
}
return ISO_SUCCESS;
}
int iso_image_set_boot_image(IsoImage *image, const char *image_path,
enum eltorito_boot_media_type type,
const char *catalog_path,
ElToritoBootImage **boot)
{
int ret;
struct el_torito_boot_catalog *catalog;
ElToritoBootImage *boot_image= NULL;
IsoBoot *cat_node= NULL;
if (image == NULL || image_path == NULL || catalog_path == NULL) {
return ISO_NULL_POINTER;
}
if (image->bootcat != NULL) {
return ISO_IMAGE_ALREADY_BOOTABLE;
}
/* create the node for the catalog */
{
IsoDir *parent;
char *catdir = NULL, *catname = NULL;
catdir = strdup(catalog_path);
if (catdir == NULL) {
return ISO_OUT_OF_MEM;
}
/* get both the dir and the name */
catname = strrchr(catdir, '/');
if (catname == NULL) {
free(catdir);
return ISO_WRONG_ARG_VALUE;
}
if (catname == catdir) {
/* we are apending catalog to root node */
parent = image->root;
} else {
IsoNode *p;
catname[0] = '\0';
ret = iso_tree_path_to_node(image, catdir, &p);
if (ret <= 0) {
free(catdir);
return ret < 0 ? ret : ISO_NODE_DOESNT_EXIST;
}
if (p->type != LIBISO_DIR) {
free(catdir);
return ISO_WRONG_ARG_VALUE;
}
parent = (IsoDir*)p;
}
catname++;
ret = iso_tree_add_boot_node(parent, catname, &cat_node);
free(catdir);
if (ret < 0) {
return ret;
}
}
/* create the boot image */
ret = create_image(image, image_path, type, &boot_image);
if (ret < 0) {
goto boot_image_cleanup;
}
/* creates the catalog with the given image */
catalog = malloc(sizeof(struct el_torito_boot_catalog));
if (catalog == NULL) {
ret = ISO_OUT_OF_MEM;
goto boot_image_cleanup;
}
catalog->image = boot_image;
catalog->node = cat_node;
iso_node_ref((IsoNode*)cat_node);
image->bootcat = catalog;
if (boot) {
*boot = boot_image;
}
return ISO_SUCCESS;
boot_image_cleanup:;
if (cat_node) {
iso_node_take((IsoNode*)cat_node);
iso_node_unref((IsoNode*)cat_node);
}
if (boot_image) {
iso_node_unref((IsoNode*)boot_image->image);
free(boot_image);
}
return ret;
}
/**
* Get El-Torito boot image of an ISO image, if any.
*
* This can be useful, for example, to check if a volume read from a previous
* session or an existing image is bootable. It can also be useful to get
* the image and catalog tree nodes. An application would want those, for
* example, to prevent the user removing it.
*
* Both nodes are owned by libisofs and should not be freed. You can get your
* own ref with iso_node_ref(). You can can also check if the node is already
* on the tree by getting its parent (note that when reading El-Torito info
* from a previous image, the nodes might not be on the tree even if you haven't
* removed them). Remember that you'll need to get a new ref
* (with iso_node_ref()) before inserting them again to the tree, and probably
* you will also need to set the name or permissions.
*
* @param image
* The image from which to get the boot image.
* @param boot
* If not NULL, it will be filled with a pointer to the boot image, if
* any. That object is owned by the IsoImage and should not be freed by
* the user, nor dereferenced once the last reference to the IsoImage was
* disposed via iso_image_unref().
* @param imgnode
* When not NULL, it will be filled with the image tree node. No extra ref
* is added, you can use iso_node_ref() to get one if you need it.
* @param catnode
* When not NULL, it will be filled with the catnode tree node. No extra
* ref is added, you can use iso_node_ref() to get one if you need it.
* @return
* 1 on success, 0 is the image is not bootable (i.e., it has no El-Torito
* image), < 0 error.
*/
int iso_image_get_boot_image(IsoImage *image, ElToritoBootImage **boot,
IsoFile **imgnode, IsoBoot **catnode)
{
if (image == NULL) {
return ISO_NULL_POINTER;
}
if (image->bootcat == NULL) {
return 0;
}
/* ok, image is bootable */
if (boot) {
*boot = image->bootcat->image;
}
if (imgnode) {
*imgnode = image->bootcat->image->image;
}
if (catnode) {
*catnode = image->bootcat->node;
}
return ISO_SUCCESS;
}
/**
* Removes the El-Torito bootable image.
*
* The IsoBoot node that acts as placeholder for the catalog is also removed
* for the image tree, if there.
* If the image is not bootable (don't have el-torito boot image) this function
* just returns.
*/
void iso_image_remove_boot_image(IsoImage *image)
{
if (image == NULL || image->bootcat == NULL)
return;
/*
* remove catalog node from its parent
* (the reference will be disposed next)
*/
iso_node_take((IsoNode*)image->bootcat->node);
/* free boot catalog and image, including references to nodes */
el_torito_boot_catalog_free(image->bootcat);
image->bootcat = NULL;
}
void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat)
{
struct el_torito_boot_image *image;
if (cat == NULL) {
return;
}
image = cat->image;
iso_node_unref((IsoNode*)image->image);
free(image);
iso_node_unref((IsoNode*)cat->node);
free(cat);
}
/**
* Stream that generates the contents of a El-Torito catalog.
*/
struct catalog_stream
{
Ecma119Image *target;
uint8_t buffer[BLOCK_SIZE];
int offset; /* -1 if stream is not openned */
};
static void
write_validation_entry(uint8_t *buf)
{
size_t i;
int checksum;
struct el_torito_validation_entry *ve =
(struct el_torito_validation_entry*)buf;
ve->header_id[0] = 1;
ve->platform_id[0] = 0; /* 0: 80x86, 1: PowerPC, 2: Mac */
ve->key_byte1[0] = 0x55;
ve->key_byte2[0] = 0xAA;
/* calculate the checksum, to ensure sum of all words is 0 */
checksum = 0;
for (i = 0; i < sizeof(struct el_torito_validation_entry); i += 2) {
checksum -= (int16_t) ((buf[i+1] << 8) | buf[i]);
}
iso_lsb(ve->checksum, checksum, 2);
}
/**
* Write one section entry.
* Currently this is used only for default image (the only supported just now)
*/
static void
write_section_entry(uint8_t *buf, Ecma119Image *t)
{
struct el_torito_boot_image *img;
struct el_torito_section_entry *se =
(struct el_torito_section_entry*)buf;
img = t->catalog->image;
se->boot_indicator[0] = img->bootable ? 0x88 : 0x00;
se->boot_media_type[0] = img->type;
iso_lsb(se->load_seg, img->load_seg, 2);
se->system_type[0] = img->partition_type;
iso_lsb(se->sec_count, img->load_size, 2);
iso_lsb(se->block, t->bootimg->block, 4);
}
static
int catalog_open(IsoStream *stream)
{
struct catalog_stream *data;
if (stream == NULL) {
return ISO_NULL_POINTER;
}
data = stream->data;
if (data->offset != -1) {
return ISO_FILE_ALREADY_OPENED;
}
memset(data->buffer, 0, BLOCK_SIZE);
/* fill the buffer with the catalog contents */
write_validation_entry(data->buffer);
/* write default entry */
write_section_entry(data->buffer + 32, data->target);
data->offset = 0;
return ISO_SUCCESS;
}
static
int catalog_close(IsoStream *stream)
{
struct catalog_stream *data;
if (stream == NULL) {
return ISO_NULL_POINTER;
}
data = stream->data;
if (data->offset == -1) {
return ISO_FILE_NOT_OPENED;
}
data->offset = -1;
return ISO_SUCCESS;
}
static
off_t catalog_get_size(IsoStream *stream)
{
return BLOCK_SIZE;
}
static
int catalog_read(IsoStream *stream, void *buf, size_t count)
{
size_t len;
struct catalog_stream *data;
if (stream == NULL || buf == NULL) {
return ISO_NULL_POINTER;
}
if (count == 0) {
return ISO_WRONG_ARG_VALUE;
}
data = stream->data;
if (data->offset == -1) {
return ISO_FILE_NOT_OPENED;
}
len = MIN(count, BLOCK_SIZE - data->offset);
memcpy(buf, data->buffer + data->offset, len);
return len;
}
static
int catalog_is_repeatable(IsoStream *stream)
{
return 1;
}
/**
* fs_id will be the id reserved for El-Torito
* dev_id will be 0 for catalog, 1 for boot image (if needed)
* we leave ino_id for future use when we support multiple boot images
*/
static
void catalog_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id,
ino_t *ino_id)
{
*fs_id = ISO_ELTORITO_FS_ID;
*dev_id = 0;
*ino_id = 0;
}
static
void catalog_free(IsoStream *stream)
{
free(stream->data);
}
IsoStreamIface catalog_stream_class = {
0,
"boot",
catalog_open,
catalog_close,
catalog_get_size,
catalog_read,
catalog_is_repeatable,
catalog_get_id,
catalog_free
};
/**
* Create an IsoStream for writing El-Torito catalog for a given target.
*/
static
int catalog_stream_new(Ecma119Image *target, IsoStream **stream)
{
IsoStream *str;
struct catalog_stream *data;
if (target == NULL || stream == NULL || target->catalog == NULL) {
return ISO_NULL_POINTER;
}
str = malloc(sizeof(IsoStream));
if (str == NULL) {
return ISO_OUT_OF_MEM;
}
data = malloc(sizeof(struct catalog_stream));
if (str == NULL) {
free(str);
return ISO_OUT_OF_MEM;
}
/* fill data */
data->target = target;
data->offset = -1;
str->refcount = 1;
str->data = data;
str->class = &catalog_stream_class;
*stream = str;
return ISO_SUCCESS;
}
int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src)
{
int ret;
IsoFileSrc *file;
IsoStream *stream;
if (target == NULL || src == NULL || target->catalog == NULL) {
return ISO_OUT_OF_MEM;
}
if (target->cat != NULL) {
/* catalog file src already created */
*src = target->cat;
return ISO_SUCCESS;
}
file = malloc(sizeof(IsoFileSrc));
if (file == NULL) {
return ISO_OUT_OF_MEM;
}
ret = catalog_stream_new(target, &stream);
if (ret < 0) {
free(file);
return ret;
}
/* fill fields */
file->prev_img = 0; /* TODO allow copy of old img catalog???? */
file->block = 0; /* to be filled later */
file->sort_weight = 1000; /* slightly high */
file->stream = stream;
ret = iso_file_src_add(target, file, src);
if (ret <= 0) {
iso_stream_unref(stream);
free(file);
} else {
target->cat = *src;
}
return ret;
}
/******************* EL-TORITO WRITER *******************************/
static
int eltorito_writer_compute_data_blocks(IsoImageWriter *writer)
{
/* nothing to do, the files are written by the file writer */
return ISO_SUCCESS;
}
/**
* Write the Boot Record Volume Descriptor (ECMA-119, 8.2)
*/
static
int eltorito_writer_write_vol_desc(IsoImageWriter *writer)
{
Ecma119Image *t;
struct el_torito_boot_catalog *cat;
struct ecma119_boot_rec_vol_desc vol;
if (writer == NULL) {
return ISO_NULL_POINTER;
}
t = writer->target;
cat = t->catalog;
iso_msg_debug(t->image->id, "Write El-Torito boot record");
memset(&vol, 0, sizeof(struct ecma119_boot_rec_vol_desc));
vol.vol_desc_type[0] = 0;
memcpy(vol.std_identifier, "CD001", 5);
vol.vol_desc_version[0] = 1;
memcpy(vol.boot_sys_id, "EL TORITO SPECIFICATION", 23);
iso_lsb(vol.boot_catalog, t->cat->block, 4);
return iso_write(t, &vol, sizeof(struct ecma119_boot_rec_vol_desc));
}
/**
* Patch an isolinux boot image.
*
* @return
* 1 on success, 0 error (but continue), < 0 error
*/
static
int patch_boot_image(uint8_t *buf, Ecma119Image *t, size_t imgsize)
{
struct boot_info_table *info;
uint32_t checksum;
size_t offset;
if (imgsize < 64) {
return iso_msg_submit(t->image->id, ISO_ISOLINUX_CANT_PATCH, 0,
"Isolinux image too small. We won't patch it.");
}
/* compute checksum, as the the sum of all 32 bit words in boot image
* from offset 64 */
checksum = 0;
offset = (size_t) 64;
while (offset <= imgsize - 4) {
checksum += iso_read_lsb(buf + offset, 4);
offset += 4;
}
if (offset != imgsize) {
/* file length not multiple of 4 */
return iso_msg_submit(t->image->id, ISO_ISOLINUX_CANT_PATCH, 0,
"Unexpected isolinux image length. Patch might not work.");
}
/* patch boot info table */
info = (struct boot_info_table*)(buf + 8);
/*memset(info, 0, sizeof(struct boot_info_table));*/
iso_lsb(info->bi_pvd, t->ms_block + 16, 4);
iso_lsb(info->bi_file, t->bootimg->block, 4);
iso_lsb(info->bi_length, imgsize, 4);
iso_lsb(info->bi_csum, checksum, 4);
return ISO_SUCCESS;
}
static
int eltorito_writer_write_data(IsoImageWriter *writer)
{
/*
* We have nothing to write, but if we need to patch an isolinux image,
* this is a good place to do so.
*/
Ecma119Image *t;
int ret;
if (writer == NULL) {
return ISO_NULL_POINTER;
}
t = writer->target;
if (t->catalog->image->isolinux) {
/* we need to patch the image */
size_t size;
uint8_t *buf;
IsoStream *new = NULL;
IsoStream *original = t->bootimg->stream;
size = (size_t) iso_stream_get_size(original);
buf = malloc(size);
if (buf == NULL) {
return ISO_OUT_OF_MEM;
}
ret = iso_stream_open(original);
if (ret < 0) {
return ret;
}
ret = iso_stream_read(original, buf, size);
iso_stream_close(original);
if (ret != size) {
return (ret < 0) ? ret : ISO_FILE_READ_ERROR;
}
/* ok, patch the read buffer */
ret = patch_boot_image(buf, t, size);
if (ret < 0) {
return ret;
}
/* replace the original stream with a memory stream that reads from
* the patched buffer */
ret = iso_memory_stream_new(buf, size, &new);
if (ret < 0) {
return ret;
}
t->bootimg->stream = new;
iso_stream_unref(original);
}
return ISO_SUCCESS;
}
static
int eltorito_writer_free_data(IsoImageWriter *writer)
{
/* nothing to do */
return ISO_SUCCESS;
}
int eltorito_writer_create(Ecma119Image *target)
{
int ret;
IsoImageWriter *writer;
IsoFile *bootimg;
IsoFileSrc *src;
writer = malloc(sizeof(IsoImageWriter));
if (writer == NULL) {
return ISO_OUT_OF_MEM;
}
writer->compute_data_blocks = eltorito_writer_compute_data_blocks;
writer->write_vol_desc = eltorito_writer_write_vol_desc;
writer->write_data = eltorito_writer_write_data;
writer->free_data = eltorito_writer_free_data;
writer->data = NULL;
writer->target = target;
/* add this writer to image */
target->writers[target->nwriters++] = writer;
/*
* get catalog and image file sources.
* Note that the catalog may be already added, when creating the low
* level ECMA-119 tree.
*/
if (target->cat == NULL) {
ret = el_torito_catalog_file_src_create(target, &src);
if (ret < 0) {
return ret;
}
}
bootimg = target->catalog->image->image;
ret = iso_file_src_create(target, bootimg, &src);
if (ret < 0) {
return ret;
}
target->bootimg = src;
/* if we have selected to patch the image, it needs to be copied always */
if (target->catalog->image->isolinux) {
src->prev_img = 0;
}
/* we need the bootable volume descriptor */
target->curblock++;
return ISO_SUCCESS;
}

View File

@ -0,0 +1,103 @@
/*
* Copyright (c) 2007 Vreixo Formoso
*
* This file is part of the libisofs project; 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. See COPYING file for details.
*/
/**
* Declare El-Torito related structures.
* References:
* "El Torito" Bootable CD-ROM Format Specification Version 1.0 (1995)
*/
#ifndef LIBISO_ELTORITO_H
#define LIBISO_ELTORITO_H
#include "ecma119.h"
#include "node.h"
/**
* A node that acts as a placeholder for an El-Torito catalog.
*/
struct Iso_Boot
{
IsoNode node;
};
struct el_torito_boot_catalog {
IsoBoot *node; /* node of the catalog */
struct el_torito_boot_image *image; /* default boot image */
};
struct el_torito_boot_image {
IsoFile *image;
unsigned int bootable:1; /**< If the entry is bootable. */
unsigned int isolinux:1; /**< If the image will be patched */
unsigned char type; /**< The type of image */
unsigned char partition_type; /**< type of partition for HD-emul images */
short load_seg; /**< Load segment for the initial boot image. */
short load_size; /**< Number of sectors to load. */
};
/** El-Torito, 2.1 */
struct el_torito_validation_entry {
uint8_t header_id BP(1, 1);
uint8_t platform_id BP(2, 2);
uint8_t reserved BP(3, 4);
uint8_t id_string BP(5, 28);
uint8_t checksum BP(29, 30);
uint8_t key_byte1 BP(31, 31);
uint8_t key_byte2 BP(32, 32);
};
/** El-Torito, 2.2 */
struct el_torito_default_entry {
uint8_t boot_indicator BP(1, 1);
uint8_t boot_media_type BP(2, 2);
uint8_t load_seg BP(3, 4);
uint8_t system_type BP(5, 5);
uint8_t unused1 BP(6, 6);
uint8_t sec_count BP(7, 8);
uint8_t block BP(9, 12);
uint8_t unused2 BP(13, 32);
};
/** El-Torito, 2.3 */
struct el_torito_section_header {
uint8_t header_indicator BP(1, 1);
uint8_t platform_id BP(2, 2);
uint8_t number BP(3, 4);
uint8_t character BP(5, 32);
};
/** El-Torito, 2.4 */
struct el_torito_section_entry {
uint8_t boot_indicator BP(1, 1);
uint8_t boot_media_type BP(2, 2);
uint8_t load_seg BP(3, 4);
uint8_t system_type BP(5, 5);
uint8_t unused1 BP(6, 6);
uint8_t sec_count BP(7, 8);
uint8_t block BP(9, 12);
uint8_t selec_criteria BP(13, 13);
uint8_t vendor_sc BP(14, 32);
};
void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat);
/**
* Create a IsoFileSrc for writing the el-torito catalog for the given
* target, and add it to target. If the target already has a src for the
* catalog, it just returns.
*/
int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src);
/**
* Create a writer for el-torito information.
*/
int eltorito_writer_create(Ecma119Image *target);
#endif /* LIBISO_ELTORITO_H */

View File

@ -0,0 +1,387 @@
/*
* Copyright (c) 2007 Vreixo Formoso
*
* This file is part of the libisofs project; 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. See COPYING file for details.
*/
#include "filesrc.h"
#include "node.h"
#include "util.h"
#include "writer.h"
#include "messages.h"
#include "image.h"
#include <stdlib.h>
#include <string.h>
#include <limits.h>
int iso_file_src_cmp(const void *n1, const void *n2)
{
const IsoFileSrc *f1, *f2;
unsigned int fs_id1, fs_id2;
dev_t dev_id1, dev_id2;
ino_t ino_id1, ino_id2;
f1 = (const IsoFileSrc *)n1;
f2 = (const IsoFileSrc *)n2;
iso_stream_get_id(f1->stream, &fs_id1, &dev_id1, &ino_id1);
iso_stream_get_id(f2->stream, &fs_id2, &dev_id2, &ino_id2);
if (fs_id1 < fs_id2) {
return -1;
} else if (fs_id1 > fs_id2) {
return 1;
} else {
/* files belong to the same fs */
if (dev_id1 > dev_id2) {
return -1;
} else if (dev_id1 < dev_id2) {
return 1;
} else {
/* files belong to same device in same fs */
return (ino_id1 < ino_id2) ? -1 : (ino_id1 > ino_id2) ? 1 : 0;
}
}
}
int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
{
int ret;
IsoFileSrc *fsrc;
unsigned int fs_id;
dev_t dev_id;
ino_t ino_id;
if (img == NULL || file == NULL || src == NULL) {
return ISO_NULL_POINTER;
}
iso_stream_get_id(file->stream, &fs_id, &dev_id, &ino_id);
fsrc = malloc(sizeof(IsoFileSrc));
if (fsrc == NULL) {
return ISO_OUT_OF_MEM;
}
/* fill key and other atts */
fsrc->prev_img = file->msblock ? 1 : 0;
fsrc->block = file->msblock;
fsrc->sort_weight = file->sort_weight;
fsrc->stream = file->stream;
/* insert the filesrc in the tree */
ret = iso_rbtree_insert(img->files, fsrc, (void**)src);
if (ret <= 0) {
free(fsrc);
return ret;
}
iso_stream_ref(fsrc->stream);
return ISO_SUCCESS;
}
/**
* Add a given IsoFileSrc to the given image target.
*
* The IsoFileSrc will be cached in a tree to prevent the same file for
* being written several times to image. If you call again this function
* with a node that refers to the same source file, the previously
* created one will be returned.
*
* @param img
* The image where this file is to be written
* @param new
* The IsoFileSrc to add
* @param src
* Will be filled with a pointer to the IsoFileSrc really present in
* the tree. It could be different than new if the same file already
* exists in the tree.
* @return
* 1 on success, 0 if file already exists on tree, < 0 error
*/
int iso_file_src_add(Ecma119Image *img, IsoFileSrc *new, IsoFileSrc **src)
{
int ret;
if (img == NULL || new == NULL || src == NULL) {
return ISO_NULL_POINTER;
}
/* insert the filesrc in the tree */
ret = iso_rbtree_insert(img->files, new, (void**)src);
return ret;
}
void iso_file_src_free(void *node)
{
iso_stream_unref(((IsoFileSrc*)node)->stream);
free(node);
}
off_t iso_file_src_get_size(IsoFileSrc *file)
{
return iso_stream_get_size(file->stream);
}
static int cmp_by_weight(const void *f1, const void *f2)
{
IsoFileSrc *f = *((IsoFileSrc**)f1);
IsoFileSrc *g = *((IsoFileSrc**)f2);
/* higher weighted first */
return g->sort_weight - f->sort_weight;
}
static
int is_ms_file(void *arg)
{
IsoFileSrc *f = (IsoFileSrc *)arg;
return f->prev_img ? 0 : 1;
}
static
int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
{
size_t i, size;
Ecma119Image *t;
IsoFileSrc **filelist;
int (*inc_item)(void *);
if (writer == NULL) {
return ISO_ASSERT_FAILURE;
}
t = writer->target;
/* on appendable images, ms files shouldn't be included */
if (t->appendable) {
inc_item = is_ms_file;
} else {
inc_item = NULL;
}
/* store the filesrcs in a array */
filelist = (IsoFileSrc**)iso_rbtree_to_array(t->files, inc_item, &size);
if (filelist == NULL) {
return ISO_OUT_OF_MEM;
}
/* sort files by weight, if needed */
if (t->sort_files) {
qsort(filelist, size, sizeof(void*), cmp_by_weight);
}
/* fill block value */
for (i = 0; i < size; ++i) {
IsoFileSrc *file = filelist[i];
file->block = t->curblock;
t->curblock += DIV_UP(iso_file_src_get_size(file), BLOCK_SIZE);
}
/* the list is only needed by this writer, store locally */
writer->data = filelist;
return ISO_SUCCESS;
}
static
int filesrc_writer_write_vol_desc(IsoImageWriter *writer)
{
/* nothing needed */
return ISO_SUCCESS;
}
/* open a file, i.e., its Stream */
static inline
int filesrc_open(IsoFileSrc *file)
{
return iso_stream_open(file->stream);
}
static inline
int filesrc_close(IsoFileSrc *file)
{
return iso_stream_close(file->stream);
}
/**
* @return
* 1 ok, 0 EOF, < 0 error
*/
static
int filesrc_read(IsoFileSrc *file, char *buf, size_t count)
{
size_t bytes = 0;
/* loop to ensure the full buffer is filled */
do {
ssize_t result;
result = iso_stream_read(file->stream, buf + bytes, count - bytes);
if (result < 0) {
/* fill buffer with 0s and return */
memset(buf + bytes, 0, count - bytes);
return result;
}
if (result == 0)
break;
bytes += result;
} while (bytes < count);
if (bytes < count) {
/* eof */
memset(buf + bytes, 0, count - bytes);
return 0;
} else {
return 1;
}
}
static
int filesrc_writer_write_data(IsoImageWriter *writer)
{
int res;
size_t i, b;
Ecma119Image *t;
IsoFileSrc *file;
IsoFileSrc **filelist;
char name[PATH_MAX];
char buffer[BLOCK_SIZE];
if (writer == NULL) {
return ISO_ASSERT_FAILURE;
}
t = writer->target;
filelist = writer->data;
iso_msg_debug(t->image->id, "Writing Files...");
i = 0;
while ((file = filelist[i++]) != NULL) {
/*
* TODO WARNING
* when we allow files greater than 4GB, current DIV_UP implementation
* can overflow!!
*/
uint32_t nblocks = DIV_UP(iso_file_src_get_size(file), BLOCK_SIZE);
res = filesrc_open(file);
iso_stream_get_file_name(file->stream, name);
if (res < 0) {
/*
* UPS, very ugly error, the best we can do is just to write
* 0's to image
*/
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
"File \"%s\" can't be opened. Filling with 0s.", name);
if (res < 0) {
return res; /* aborted due to error severity */
}
memset(buffer, 0, BLOCK_SIZE);
for (b = 0; b < nblocks; ++b) {
res = iso_write(t, buffer, BLOCK_SIZE);
if (res < 0) {
/* ko, writer error, we need to go out! */
return res;
}
}
continue;
} else if (res > 1) {
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
"Size of file \"%s\" has changed. It will be %s", name,
(res == 2 ? "truncated" : "padded with 0's"));
if (res < 0) {
filesrc_close(file);
return res; /* aborted due to error severity */
}
}
#ifdef LIBISOFS_VERBOSE_DEBUG
else {
iso_msg_debug(t->image->id, "Writing file %s", name);
}
#endif
/* write file contents to image */
for (b = 0; b < nblocks; ++b) {
int wres;
res = filesrc_read(file, buffer, BLOCK_SIZE);
if (res < 0) {
/* read error */
break;
}
wres = iso_write(t, buffer, BLOCK_SIZE);
if (wres < 0) {
/* ko, writer error, we need to go out! */
filesrc_close(file);
return wres;
}
}
filesrc_close(file);
if (b < nblocks) {
/* premature end of file, due to error or eof */
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
if (res < 0) {
/* error */
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
"Read error in file %s.", name);
} else {
/* eof */
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
"Premature end of file %s.", name);
}
if (res < 0) {
return res; /* aborted due error severity */
}
/* fill with 0s */
iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
"Filling with 0");
memset(buffer, 0, BLOCK_SIZE);
while (b++ < nblocks) {
res = iso_write(t, buffer, BLOCK_SIZE);
if (res < 0) {
/* ko, writer error, we need to go out! */
return res;
}
}
}
}
return ISO_SUCCESS;
}
static
int filesrc_writer_free_data(IsoImageWriter *writer)
{
/* free the list of files (contents are free together with the tree) */
free(writer->data);
return ISO_SUCCESS;
}
int iso_file_src_writer_create(Ecma119Image *target)
{
IsoImageWriter *writer;
writer = malloc(sizeof(IsoImageWriter));
if (writer == NULL) {
return ISO_ASSERT_FAILURE;
}
writer->compute_data_blocks = filesrc_writer_compute_data_blocks;
writer->write_vol_desc = filesrc_writer_write_vol_desc;
writer->write_data = filesrc_writer_write_data;
writer->free_data = filesrc_writer_free_data;
writer->data = NULL;
writer->target = target;
/* add this writer to image */
target->writers[target->nwriters++] = writer;
return ISO_SUCCESS;
}

Some files were not shown because too many files have changed in this diff Show More