libisofs/doc/Tutorial
2008-02-02 01:49:26 +01:00

340 lines
12 KiB
Plaintext
Executable File

===============================================================================
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 multisession
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_ERR_SEV() macro [TODO: we need a function to
translate error severity to string]
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.