Blame doc/text/libarchive_internals.3.txt

Packit Service 1d0348
LIBARCHIVE_INTERNALS(3)  BSD Library Functions Manual  LIBARCHIVE_INTERNALS(3)
Packit Service 1d0348
Packit Service 1d0348
NAME
Packit Service 1d0348
     libarchive_internals — description of libarchive internal interfaces
Packit Service 1d0348
Packit Service 1d0348
OVERVIEW
Packit Service 1d0348
     The libarchive library provides a flexible interface for reading and
Packit Service 1d0348
     writing streaming archive files such as tar and cpio.  Internally, it
Packit Service 1d0348
     follows a modular layered design that should make it easy to add new ar‐
Packit Service 1d0348
     chive and compression formats.
Packit Service 1d0348
Packit Service 1d0348
GENERAL ARCHITECTURE
Packit Service 1d0348
     Externally, libarchive exposes most operations through an opaque, object-
Packit Service 1d0348
     style interface.  The archive_entry(3) objects store information about a
Packit Service 1d0348
     single filesystem object.	The rest of the library provides facilities to
Packit Service 1d0348
     write archive_entry(3) objects to archive files, read them from archive
Packit Service 1d0348
     files, and write them to disk.  (There are plans to add a facility to
Packit Service 1d0348
     read archive_entry(3) objects from disk as well.)
Packit Service 1d0348
Packit Service 1d0348
     The read and write APIs each have four layers: a public API layer, a for‐
Packit Service 1d0348
     mat layer that understands the archive file format, a compression layer,
Packit Service 1d0348
     and an I/O layer.	The I/O layer is completely exposed to clients who can
Packit Service 1d0348
     replace it entirely with their own functions.
Packit Service 1d0348
Packit Service 1d0348
     In order to provide as much consistency as possible for clients, some
Packit Service 1d0348
     public functions are virtualized.	Eventually, it should be possible for
Packit Service 1d0348
     clients to open an archive or disk writer, and then use a single set of
Packit Service 1d0348
     code to select and write entries, regardless of the target.
Packit Service 1d0348
Packit Service 1d0348
READ ARCHITECTURE
Packit Service 1d0348
     From the outside, clients use the archive_read(3) API to manipulate an
Packit Service 1d0348
     archive object to read entries and bodies from an archive stream.	Inter‐
Packit Service 1d0348
     nally, the archive object is cast to an archive_read object, which holds
Packit Service 1d0348
     all read-specific data.  The API has four layers: The lowest layer is the
Packit Service 1d0348
     I/O layer.  This layer can be overridden by clients, but most clients use
Packit Service 1d0348
     the packaged I/O callbacks provided, for example, by
Packit Service 1d0348
     archive_read_open_memory(3), and archive_read_open_fd(3).	The compres‐
Packit Service 1d0348
     sion layer calls the I/O layer to read bytes and decompresses them for
Packit Service 1d0348
     the format layer.	The format layer unpacks a stream of uncompressed
Packit Service 1d0348
     bytes and creates archive_entry objects from the incoming data.  The API
Packit Service 1d0348
     layer tracks overall state (for example, it prevents clients from reading
Packit Service 1d0348
     data before reading a header) and invokes the format and compression
Packit Service 1d0348
     layer operations through registered function pointers.  In particular,
Packit Service 1d0348
     the API layer drives the format-detection process: When opening the ar‐
Packit Service 1d0348
     chive, it reads an initial block of data and offers it to each registered
Packit Service 1d0348
     compression handler.  The one with the highest bid is initialized with
Packit Service 1d0348
     the first block.  Similarly, the format handlers are polled to see which
Packit Service 1d0348
     handler is the best for each archive.  (Prior to 2.4.0, the format bid‐
Packit Service 1d0348
     ders were invoked for each entry, but this design hindered error recov‐
Packit Service 1d0348
     ery.)
Packit Service 1d0348
Packit Service 1d0348
   I/O Layer and Client Callbacks
Packit Service 1d0348
     The read API goes to some lengths to be nice to clients.  As a result,
Packit Service 1d0348
     there are few restrictions on the behavior of the client callbacks.
Packit Service 1d0348
Packit Service 1d0348
     The client read callback is expected to provide a block of data on each
Packit Service 1d0348
     call.  A zero-length return does indicate end of file, but otherwise
Packit Service 1d0348
     blocks may be as small as one byte or as large as the entire file.  In
Packit Service 1d0348
     particular, blocks may be of different sizes.
Packit Service 1d0348
Packit Service 1d0348
     The client skip callback returns the number of bytes actually skipped,
Packit Service 1d0348
     which may be much smaller than the skip requested.  The only requirement
Packit Service 1d0348
     is that the skip not be larger.  In particular, clients are allowed to
Packit Service 1d0348
     return zero for any skip that they don't want to handle.  The skip call‐
Packit Service 1d0348
     back must never be invoked with a negative value.
Packit Service 1d0348
Packit Service 1d0348
     Keep in mind that not all clients are reading from disk: clients reading
Packit Service 1d0348
     from networks may provide different-sized blocks on every request and
Packit Service 1d0348
     cannot skip at all; advanced clients may use mmap(2) to read the entire
Packit Service 1d0348
     file into memory at once and return the entire file to libarchive as a
Packit Service 1d0348
     single block; other clients may begin asynchronous I/O operations for the
Packit Service 1d0348
     next block on each request.
Packit Service 1d0348
Packit Service 1d0348
   Decompresssion Layer
Packit Service 1d0348
     The decompression layer not only handles decompression, it also buffers
Packit Service 1d0348
     data so that the format handlers see a much nicer I/O model.  The decom‐
Packit Service 1d0348
     pression API is a two stage peek/consume model.  A read_ahead request
Packit Service 1d0348
     specifies a minimum read amount; the decompression layer must provide a
Packit Service 1d0348
     pointer to at least that much data.  If more data is immediately avail‐
Packit Service 1d0348
     able, it should return more: the format layer handles bulk data reads by
Packit Service 1d0348
     asking for a minimum of one byte and then copying as much data as is
Packit Service 1d0348
     available.
Packit Service 1d0348
Packit Service 1d0348
     A subsequent call to the consume() function advances the read pointer.
Packit Service 1d0348
     Note that data returned from a read_ahead() call is guaranteed to remain
Packit Service 1d0348
     in place until the next call to read_ahead().  Intervening calls to
Packit Service 1d0348
     consume() should not cause the data to move.
Packit Service 1d0348
Packit Service 1d0348
     Skip requests must always be handled exactly.  Decompression handlers
Packit Service 1d0348
     that cannot seek forward should not register a skip handler; the API
Packit Service 1d0348
     layer fills in a generic skip handler that reads and discards data.
Packit Service 1d0348
Packit Service 1d0348
     A decompression handler has a specific lifecycle:
Packit Service 1d0348
     Registration/Configuration
Packit Service 1d0348
	     When the client invokes the public support function, the decom‐
Packit Service 1d0348
	     pression handler invokes the internal
Packit Service 1d0348
	     __archive_read_register_compression() function to provide bid and
Packit Service 1d0348
	     initialization functions.	This function returns NULL on error or
Packit Service 1d0348
	     else a pointer to a struct decompressor_t.  This structure con‐
Packit Service 1d0348
	     tains a void * config slot that can be used for storing any cus‐
Packit Service 1d0348
	     tomization information.
Packit Service 1d0348
     Bid     The bid function is invoked with a pointer and size of a block of
Packit Service 1d0348
	     data.  The decompressor can access its config data through the
Packit Service 1d0348
	     decompressor element of the archive_read object.  The bid func‐
Packit Service 1d0348
	     tion is otherwise stateless.  In particular, it must not perform
Packit Service 1d0348
	     any I/O operations.
Packit Service 1d0348
Packit Service 1d0348
	     The value returned by the bid function indicates its suitability
Packit Service 1d0348
	     for handling this data stream.  A bid of zero will ensure that
Packit Service 1d0348
	     this decompressor is never invoked.  Return zero if magic number
Packit Service 1d0348
	     checks fail.  Otherwise, your initial implementation should
Packit Service 1d0348
	     return the number of bits actually checked.  For example, if you
Packit Service 1d0348
	     verify two full bytes and three bits of another byte, bid 19.
Packit Service 1d0348
	     Note that the initial block may be very short; be careful to only
Packit Service 1d0348
	     inspect the data you are given.  (The current decompressors
Packit Service 1d0348
	     require two bytes for correct bidding.)
Packit Service 1d0348
     Initialize
Packit Service 1d0348
	     The winning bidder will have its init function called.  This
Packit Service 1d0348
	     function should initialize the remaining slots of the struct
Packit Service 1d0348
	     decompressor_t object pointed to by the decompressor element of
Packit Service 1d0348
	     the archive_read object.  In particular, it should allocate any
Packit Service 1d0348
	     working data it needs in the data slot of that structure.	The
Packit Service 1d0348
	     init function is called with the block of data that was used for
Packit Service 1d0348
	     tasting.  At this point, the decompressor is responsible for all
Packit Service 1d0348
	     I/O requests to the client callbacks.  The decompressor is free
Packit Service 1d0348
	     to read more data as and when necessary.
Packit Service 1d0348
     Satisfy I/O requests
Packit Service 1d0348
	     The format handler will invoke the read_ahead, consume, and skip
Packit Service 1d0348
	     functions as needed.
Packit Service 1d0348
     Finish  The finish method is called only once when the archive is closed.
Packit Service 1d0348
	     It should release anything stored in the data and config slots of
Packit Service 1d0348
	     the decompressor object.  It should not invoke the client close
Packit Service 1d0348
	     callback.
Packit Service 1d0348
Packit Service 1d0348
   Format Layer
Packit Service 1d0348
     The read formats have a similar lifecycle to the decompression handlers:
Packit Service 1d0348
     Registration
Packit Service 1d0348
	     Allocate your private data and initialize your pointers.
Packit Service 1d0348
     Bid     Formats bid by invoking the read_ahead() decompression method but
Packit Service 1d0348
	     not calling the consume() method.	This allows each bidder to
Packit Service 1d0348
	     look ahead in the input stream.  Bidders should not look further
Packit Service 1d0348
	     ahead than necessary, as long look aheads put pressure on the
Packit Service 1d0348
	     decompression layer to buffer lots of data.  Most formats only
Packit Service 1d0348
	     require a few hundred bytes of look ahead; look aheads of a few
Packit Service 1d0348
	     kilobytes are reasonable.	(The ISO9660 reader sometimes looks
Packit Service 1d0348
	     ahead by 48k, which should be considered an upper limit.)
Packit Service 1d0348
     Read header
Packit Service 1d0348
	     The header read is usually the most complex part of any format.
Packit Service 1d0348
	     There are a few strategies worth mentioning: For formats such as
Packit Service 1d0348
	     tar or cpio, reading and parsing the header is straightforward
Packit Service 1d0348
	     since headers alternate with data.  For formats that store all
Packit Service 1d0348
	     header data at the beginning of the file, the first header read
Packit Service 1d0348
	     request may have to read all headers into memory and store that
Packit Service 1d0348
	     data, sorted by the location of the file data.  Subsequent header
Packit Service 1d0348
	     read requests will skip forward to the beginning of the file data
Packit Service 1d0348
	     and return the corresponding header.
Packit Service 1d0348
     Read Data
Packit Service 1d0348
	     The read data interface supports sparse files; this requires that
Packit Service 1d0348
	     each call return a block of data specifying the file offset and
Packit Service 1d0348
	     size.  This may require you to carefully track the location so
Packit Service 1d0348
	     that you can return accurate file offsets for each read.  Remem‐
Packit Service 1d0348
	     ber that the decompressor will return as much data as it has.
Packit Service 1d0348
	     Generally, you will want to request one byte, examine the return
Packit Service 1d0348
	     value to see how much data is available, and possibly trim that
Packit Service 1d0348
	     to the amount you can use.  You should invoke consume for each
Packit Service 1d0348
	     block just before you return it.
Packit Service 1d0348
     Skip All Data
Packit Service 1d0348
	     The skip data call should skip over all file data and trailing
Packit Service 1d0348
	     padding.  This is called automatically by the API layer just
Packit Service 1d0348
	     before each header read.  It is also called in response to the
Packit Service 1d0348
	     client calling the public data_skip() function.
Packit Service 1d0348
     Cleanup
Packit Service 1d0348
	     On cleanup, the format should release all of its allocated mem‐
Packit Service 1d0348
	     ory.
Packit Service 1d0348
Packit Service 1d0348
   API Layer
Packit Service 1d0348
     XXX to do XXX
Packit Service 1d0348
Packit Service 1d0348
WRITE ARCHITECTURE
Packit Service 1d0348
     The write API has a similar set of four layers: an API layer, a format
Packit Service 1d0348
     layer, a compression layer, and an I/O layer.  The registration here is
Packit Service 1d0348
     much simpler because only one format and one compression can be regis‐
Packit Service 1d0348
     tered at a time.
Packit Service 1d0348
Packit Service 1d0348
   I/O Layer and Client Callbacks
Packit Service 1d0348
     XXX To be written XXX
Packit Service 1d0348
Packit Service 1d0348
   Compression Layer
Packit Service 1d0348
     XXX To be written XXX
Packit Service 1d0348
Packit Service 1d0348
   Format Layer
Packit Service 1d0348
     XXX To be written XXX
Packit Service 1d0348
Packit Service 1d0348
   API Layer
Packit Service 1d0348
     XXX To be written XXX
Packit Service 1d0348
Packit Service 1d0348
WRITE_DISK ARCHITECTURE
Packit Service 1d0348
     The write_disk API is intended to look just like the write API to
Packit Service 1d0348
     clients.  Since it does not handle multiple formats or compression, it is
Packit Service 1d0348
     not layered internally.
Packit Service 1d0348
Packit Service 1d0348
GENERAL SERVICES
Packit Service 1d0348
     The archive_read, archive_write, and archive_write_disk objects all con‐
Packit Service 1d0348
     tain an initial archive object which provides common support for a set of
Packit Service 1d0348
     standard services.  (Recall that ANSI/ISO C90 guarantees that you can
Packit Service 1d0348
     cast freely between a pointer to a structure and a pointer to the first
Packit Service 1d0348
     element of that structure.)  The archive object has a magic value that
Packit Service 1d0348
     indicates which API this object is associated with, slots for storing
Packit Service 1d0348
     error information, and function pointers for virtualized API functions.
Packit Service 1d0348
Packit Service 1d0348
MISCELLANEOUS NOTES
Packit Service 1d0348
     Connecting existing archiving libraries into libarchive is generally
Packit Service 1d0348
     quite difficult.  In particular, many existing libraries strongly assume
Packit Service 1d0348
     that you are reading from a file; they seek forwards and backwards as
Packit Service 1d0348
     necessary to locate various pieces of information.  In contrast,
Packit Service 1d0348
     libarchive never seeks backwards in its input, which sometimes requires
Packit Service 1d0348
     very different approaches.
Packit Service 1d0348
Packit Service 1d0348
     For example, libarchive's ISO9660 support operates very differently from
Packit Service 1d0348
     most ISO9660 readers.  The libarchive support utilizes a work-queue
Packit Service 1d0348
     design that keeps a list of known entries sorted by their location in the
Packit Service 1d0348
     input.  Whenever libarchive's ISO9660 implementation is asked for the
Packit Service 1d0348
     next header, checks this list to find the next item on the disk.  Direc‐
Packit Service 1d0348
     tories are parsed when they are encountered and new items are added to
Packit Service 1d0348
     the list.	This design relies heavily on the ISO9660 image being opti‐
Packit Service 1d0348
     mized so that directories always occur earlier on the disk than the files
Packit Service 1d0348
     they describe.
Packit Service 1d0348
Packit Service 1d0348
     Depending on the specific format, such approaches may not be possible.
Packit Service 1d0348
     The ZIP format specification, for example, allows archivers to store key
Packit Service 1d0348
     information only at the end of the file.  In theory, it is possible to
Packit Service 1d0348
     create ZIP archives that cannot be read without seeking.  Fortunately,
Packit Service 1d0348
     such archives are very rare, and libarchive can read most ZIP archives,
Packit Service 1d0348
     though it cannot always extract as much information as a dedicated ZIP
Packit Service 1d0348
     program.
Packit Service 1d0348
Packit Service 1d0348
SEE ALSO
Packit Service 1d0348
     archive_entry(3), archive_read(3), archive_write(3),
Packit Service 1d0348
     archive_write_disk(3) libarchive(3),
Packit Service 1d0348
Packit Service 1d0348
HISTORY
Packit Service 1d0348
     The libarchive library first appeared in FreeBSD 5.3.
Packit Service 1d0348
Packit Service 1d0348
AUTHORS
Packit Service 1d0348
     The libarchive library was written by Tim Kientzle <kientzle@acm.org>.
Packit Service 1d0348
Packit Service 1d0348
BSD			       January 26, 2011 			   BSD