lbrate(1)

NAME
lbrate - extract/decompress CP/M LBR archives

SYNOPSIS
lbrate [-chlntv] [archive.lbr] [match1 [match2 @cc .

DESCRIPTION
lbrate lists, extracts, or tests CP/M LBR archives. It does this in an `unzip'-like manner, mostly hiding the details of individually compressed and renamed files, and transparently deals with the required decompression and renaming.

(It can also work on CP/M-ish compressed files (`squeezed', etc.) outside of such archives, treating them as if they were really single-member LBRs.)

The default action is to extract all files in the specified archive; see OPTIONS below for how to do other things instead.

OPTIONS

-c  use/show creation date (and time) rather than last-modified. (But note that many LBRs lack date/time stamps entirely.)

-h  give terse usage help.

-l  list files in archive. If verbose listings are enabled, it shows the filename (and the modified filename actually given in the LBR, if the file is compressed), compression method, compressed size (the uncompressed size can't be easily determined), and CRC; but by default, it just shows the filename and compressed size.

-n  don't decompress files, just extract the files precisely as they are stored in the LBR. This also means the possibly-modified LBR filenames are used (see FILENAME ISSUES below), even when used with `-l'.

-t  test files in archive - check file CRCs at the LBR level, also checking file checksums for any compressed files. (If used together with `-n', only LBR CRCs are checked.)

-v  give verbose output (when used with `-l'). Using `-lv' is the easiest way to see the filenames specified in the LBR, which are (due to compression/renaming) usually not the original filenames.

archive.lbr
    the archive to operate on. You can also specify a CP/M-ish individually-compressed file (these have names like `foo.tqt', `bar.dzc', and `baz.cym'); these are treated as if they were single-entry LBRs.

match1 etc.
    optionally specify which archive members to list/extract/test. Those which match any of these filenames/wildcards are processed. Wildcard operators supported are shell-like `*' and `?', but don't forget to quote arguments which use these (e.g. `lbrate foo.lbr '*.bar''). Note that, unless you're using `-n', these matches are always on the original filename (the one lbrate normally shows you), and not the (often modified) filename stored in the LBR.

FILENAME ISSUES
All this talk of modified filenames is probably rather confusing, so here's a brief summary of what the deal is with LBR files for those unfamiliar with the situation.

The LBR format in itself is a pure, uncompressed archival format; a bit like tar files. But while tar files are normally compressed after the component files get bundled together, LBR files normally bundle together compressed files.

Now, CP/M is limited to 8.3 file naming, so compressed files weren't indicated by adding an extension, but (loosely speaking) by changing the 2nd character of the extension. So foo.txt becomes foo.tqt, for example. What happens to the original name? Easy, it gets stored in the compressed file, and is restored when it's decompressed.

So, there we have the justification for lbrate's behaviour - LBRs are often full of weirdly-named files, so it's generally best to peek into the start of any compressed files, find the real filename, and use that. Since the compressed file formats all have `magic numbers' and can be very reliably detected, this approach is pretty much ideal.

EXTRACTING MULTIPLE ARCHIVES
lbrate follows the `unzip'-like practice of working on only one archive per run, with further `filenames' given on the command-line actually specifying files to extract (or whatever). The easiest way to work on multiple files with lbrate is simply to run it multiple times using for; for example:

for i in *.{lbr,LBR}; do lbrate -t $i; done

The above would test all LBR archives in the current directory. Another example, this time to extract all the squeezed/crunched files:

for i in *.?[qzQZ]*; do lbrate $i; done

TIMESTAMPS
While the LBR format did support file dates/times, there are a lot of LBRs which lack them. lbrate's approach to this is simply to use them whenever available. The last-modified date/time is used/shown by default; specify `-c' to get creation date/time instead.

DIAGNOSTICS
Given the two-level nature of the extraction process (the raw extraction of the file from the LBR, then any required decompression), there are (unless `-n' is used) two different ways that a corrupted archive can cause reading from the LBR to fail. lbrate tries to communicate this in the way which seems most reasonable given the way it's being run, as described here.

When testing an archive, lbrate gives priority to LBR CRC errors. It only mentions an error decompressing when there wasn't a CRC error at the LBR level.

When extracting an archive, lbrate considers decompression errors more important; and note that currently, a decompression error means no file data is written. (Though in this case it does say `seems valid at LBR level?' if the LBR CRC was ok.) If there's `only' an LBR CRC mismatch, then file data is written, but with a warning.

BUGS
The CRC used by LBR is only 16-bit, so `-t' is a less-than-perfect test. The additional checksum test for compressed files may improve matters slightly.

SEE ALSO
nomarch(1), tar(1), gzip(1), bzip2(1)

The CP/M programs `lt' and `lbrext' do something similar.

AUTHOR
Russell Marks (rus@svgalib.org).

The LZH decompression is based on code by Haruhiko Okumura, Haruyasu Yoshizaki, and Kenji Rikitake.