.. RST source for unalf(1) man page. Convert with:
..   rst2man.py unalf.rst > unalf.1

.. include:: ver.rst

.. |date| date::

=====
unalf
=====

--------------------------------
extract Atari 8-bit ALF archives
--------------------------------

:Manual section: 1
:Manual group: Urchlay's Atari 8-bit Tools
:Date: |date|
:Version: |version|

SYNOPSIS
========

unalf [**--help**] [**-aehtklLopqstv**] [**-d** *dir*] [**-n** *number*] [**-x** *wildcard*] *alf-file* [*wildcard* ...]

DESCRIPTION
===========

**unalf** lists, extracts, or tests the contents of an *ALF* archive.

*ALF* is a compressed archive format similar to **arc**\(1), though
not compatible with it. It was used on the Atari 8-bit platform
beginning in the late 1980s. The Atari executables are **LZ.COM**
for the compressor and **DZ.COM** for the decompressor. **unalf** is a
port of **DZ.COM** for modern operating systems, with added features.

Extracted files are written to the current directory by
default. Existing files are backed up by default (by adding a **~**
suffix to the filename).

If one or more *wildcard* arguments are provided, files will only be
listed or extracted if they match one of the wildcards. See **WILDCARDS**
below for details.

Only one *alf-file* argument is allowed. It's impossible to process
multiple ALF files per run of **unalf**. If you need bulk extraction,
use e.g. a **for** loop in a shell script.

**unalf** can't read an ALF file on standard input; *alf-file* must be
a real file.

OPTIONS
=======

Options can be combined (e.g. **-ov** means **-o** **-v**), though
the options that take an argument (**-d**, **-n**, **-x**) must appear
last in the combination.

-a
  Convert text file line endings and tabs from ATASCII to ASCII. Text
  files are detected by looking at the first 2 bytes of the extracted
  file. If both are printable ASCII (including ATASCII EOL, aka **$9B**), the
  file is considered text.

  Note that *only* line-endings and tabs are converted. Other ATASCII
  characters are left alone. If you need anything more in-depth, use
  **a8cat**\(1).

.. convert EOLs and tabs in text files.

**-aa**
  Convert line endings and tabs in *all* extracted files. This will
  corrupt any executables or non-text data files, so use with caution.

.. convert EOLs and tabs in ALL files.

-d output-dir
  Write extracted files to this directory, which will be created if it
  does not exist. The default is the current directory.

.. set output directory (created if needed).

-e
  Extract files. This is actually a no-op, as extraction is the
  default action.

.. extract files (redundant; this is the default action).

-f
  Fix (remove) junk at EOF. This option truncates the *alf-file*.
  It is the only **unalf** option that writes to the input file. No
  backup is made.

.. fix (remove) junk at EOF.

-F
  Force **unalf** to continue after detecting an invalid compressed file
  size in an *ALF* header. This isn't the default because it can cause
  **unalf** to get stuck in an infinite loop.

.. force uncompressing in case of invalid compressed size.

-h, --help
   Show built-in help message.

.. show this help message.

-k
  Keep trailing periods. In most (all?) ALF files, filenames that have no
  extension are stored with a trailing period, e.g. '**FOO**' would
  be stored as '**FOO.**'. On the Atari, the extracted file would be
  named '**FOO**', so **unalf** does the same by default. With **-k**,
  the file will be named '**FOO.**'.

.. keep trailing periods (dots) in filenames.

-l
  List filenames in archive, one per line, but do not extract. Use
  **-v** for more information (file size, etc). Obeys *wildcards* and
  the **-x**, **-L**, **-k** options.

.. list files in archive (filenames only).

-L
  Lowercase filenames. Example: **FOO.TXT** will extract to **foo.txt**.

.. use lowercase filenames.

-n number
  Only extract the *number*\th file. *wildcards* are ignored when using
  this option. Numbering begins at 1 for the first file in the archive;
  **-n0** is an error.

.. extract only file #<number> (counting from 1).

-o
  Overwrite files, if they already exist. The default is to rename
  existing files, adding a **~** suffix. Note that renaming **file**
  to **file~** *will* overwrite **file~** if it already exists.

.. overwrite files (do not create file~ backups).

-p
  Extract to standard output. All the files that get extracted will be
  printed to stdout with no delimiters, so this is most useful when
  only extracting one file. **-q** is automatically enabled by this option.

  *Warning:* No checking is done to see whether stdout is a terminal.
  Printing binary files to a terminal is a good way to make a mess.
  Even text files with the EOLs translated can still contain ATASCII
  formatting/graphics codes that can confuse your terminal. You have
  been warned.

.. extract to stdout (enables -q).

-q
  Quiet extraction or testing: do not print "Uncrunching *file*"
  or "Testing *file*" messages. Errors and warnings will still be
  printed. This is the default when **-p** is used. This option
  doesn't do anything when used with **-l** or **-v**.

.. quiet: don't print filenames during extraction/testing.

-s
  Split *ALF* file into multiple *ALF* files, one per archive member.
  The new *ALF* files are named after the filenames in the input
  *ALF* file, with ".ALF" appended. There is no corresponding option
  to join them back together, but you can use **cat**\(1) for that.

.. split ALF file into multiple ALFs.

-t
  Test archive. Same as extraction, except the files are not written
  anywhere.

.. test archive.

-T
  Ignore timestamps in *alf-file*, when extracting. Normally the extracted files
  have their **mtime** set to the time saved in the archive. With **-T**, the
  extracted files will have **mtime** set to the current time.

-v
  Verbose listing of archive contents, with compressed and original
  sizes, compression ratio, date/time stamps, and checksum. The
  output format is similar to that of **arc -v**, minus the *Stowage*
  column, since *ALF* doesn't support multiple compression types. The
  date and time are displayed, but in most .alf files these are the
  default values of "8 Jan 82  12:24:38a".

  Unlike **-l**, the **-v** listing shows the filenames exactly as
  stored in the archive (ignores **-L**, enables **-k**), and always
  shows all the files (ignores *wildcards*, **-n**, and **-x**).

.. verbose listing of archive contents.

-V, --version
  Show **unalf** version number and exit.

.. show version number.

-x wildcard
  Exclude (do not list or extract) files matching *wildcard*. See
  **WILDCARDS** below. This option can be given multiple times
  to exclude multiple patterns.

.. exclude <wildcard>. may be given multiple times.

--
  End of options. The next argument is treated as the *alf-file* and
  any further options are *wildcard*\s.

.. end of options (next arg is alf-file).

.. ENDOPTS

WILDCARDS
=========

Wildcard (aka glob) matching works like it does on the Atari: *\*.\**
matches any filename (whether or not it has an extension), and *\**
or *\*.* only match filenames with no extension.

A *\** matches any number of characters (including zero). A *?*
matches a single character. All other characters match themselves, so
a wildcard with no *\** or *?* must match exactly.

Like the Atari, anything in the name or extension following a *\** is
ignored: **FOO\*BAR.TXT** is equivalent to **FOO\*.TXT**, and
**FOO.T\*T** is equivalent to **FOO.T\***. **FOO\*TXT** is
equivalent to **FOO\***, and *will not* match the file **FOO.TXT**.

Unlike the Atari, matching is case-insensitive.

To avoid your shell trying to expand the wildcards, always quote them!
Example::

  unalf filename.alf '*.txt'

EXIT STATUS
===========

0
  Success.

1
  Fatal error (I/O or bad command-line arguments, stack under/overrun).

2
  Processing completed OK, but at least one file in the archive
  has a bad checksum.

DIAGNOSTICS
===========

Besides the standard error messages such as "no such file or directory":

Fatal errors
------------

**unalf** will exit with status 1 immediately after these errors:

**this is an ARC file, not ALF**
  Self-explanatory. Use the **arc**\(1) utility for this file.

**not an ALF file**
  Self-explanatory. Either the file is too small (less than 29 bytes)
  or its first two bytes don't match the *ALF* signature **0x1a** **0x0f**\.

**stack underrun/overrun**
  Generally means the archive is corrupt. Valid ALF files should never
  cause these errors.

**compressed data is truncated, EOF before end marker**
  Self-explanatory. The ALF file ends before the compressed data does.

**header #<n> (compressed|original) size is impossibly large (>16MB)**
  **unalf** can't handle files of more than 16MB in size. This isn't a
  bug, it's just the way it was designed (in 1988, remember). Neither
  **LZ.COM** nor **alf** will create files like this, so you *probably*
  have a corrupt ALF archive.

**compressed size for header #<n> is bigger than the rest of the file (truncated?)**
  Normally this means a truncated *ALF* file, or one with a corrupted header.
  You can use the **-F** option to turn this error into a non-fatal warning.

**compressed size for header #<n> is over twice the uncompressed size (corrupt?)**
  This generally means you have a corrupted *ALF* file.
  You can use the **-F** option to turn this error into a non-fatal warning.

Warnings
--------

**unalf** will continue after these messages occur.

**junk at EOF (ignoring)**
  Mostly harmless: does *not* imply data corruption.

  Usually this is caused by the .alf file being stored on a CP/M disk
  at some time, or by a dumb file transfer protocol. Either way, the
  file gets padded to the block size of the filesystem or protocol.
  Usually, the padding characters are **0x1a**, aka ASCII control-Z.

  This message means you can't append to the ALF file with **alf -a**
  or **LZ.COM**. You can, however, use **unalf -f** to remove the junk.

**checksum error on** *<file>*
  The archive is corrupt. If *<file>* is a text file, it may be
  partially readable. If it's an executable or other binary file, it's
  probably unrecoverable. **unalf** will try to extract the rest of
  the archive, but will exit with status 2 when it's done.

  If you have an ALF file that does this, try it with the Atari
  **DZ.COM** and see if it has the same problem. If it doesn't,
  you've found a bug in **unalf**, please send me the .alf file via
  email (see **AUTHOR**, below). Actually, I'd be interested to see
  the .alf file even if it doesn't work on the Atari either.

*<file>* **should be** *<size>* **bytes, but extracted to** *<size>*
  The archive is corrupt. If this happens on the last (or only) file, it
  probably means the ALF file was truncated. You'll almost certainly
  get a checksum error for *<file>*, too.

**filename has underscore, OK on Sparta/MyDOS, not Atari DOS 2.x**
  Not an actual problem, unless you try to extract this ALF file on
  an Atari running Atari DOS 2.0/2.5, or any other DOS that doesn't
  allow underscores in filenames.

**bad Atari filename** *<filename>* *<reason>*
  The filename stored in the ALF header doesn't follow the rules for
  Atari DOS filenames. *<reason>* will be something like "doesn't start
  with A-Z" or "invalid character". The filename will be printed with
  any unprintable characters as hex values (e.g. **$01**).

**duplicate Atari filename** *<filename>*
  The ALF archive contains duplicate filenames. Use **-n** to extract the
  second (and any further) occurrences of the name.

**header #<n> (compressed|original) size is...**
  Followed by "suspiciously large" or "too large to fit on a floppy
  disk". May indicate a corrupt archive, or someone really might have
  created an ALF file with files this big.

**ALF files don't normally contain other ALF files, are you trying to extract/list multiple ALF files at once?**
  You gave a *wildcard* argument that ends with *.alf*. This is OK if
  your *ALF* file actually contains another *ALF* file, but that would
  be a pathological case. Most likely, you're trying to extract multiple
  *ALF* files with one command, which doesn't work. Use one **unalf**
  command per file.

**date/time for <file> is zero, using current date/time**
  The date stored in the *ALF* header for this file is all zeroes, which
  is an invalid date. **unalf -v** shows this as *<none>*. The
  date on the extracted file can't be set, so it'll have the current
  date and time instead.

NOTES
=====

This **unalf** is 100% compatible with the original Atari **DZ.COM**
aka **UNALF.COM**, with the following differences:

- There is no interactive mode. The file to extract must be given as
  a command-line argument, and the output directory must be given
  with the **-d** option.

- This **unalf** is capable of listing or testing the contents of an archive
  without extracting it, plus other handy features such as extracting
  to standard output and text file EOL conversion.

- Turning the screen off for speed makes no sense on modern operating
  systems, so there's no option for that.

- The timestamps saved in the archive are actually used to set the
  date/time of the extracted files (though this can be disabled with **-T**).

A note about the Atari filenames: **DZ.COM** is sometimes found on
old disk images as **UNALF.COM**, and **LZ.COM** is sometimes called
**ALF.COM** or **ALFER.COM**. I've used the original names partly
out of respect for the original author, and partly to avoid confusion
between my **alf**\/**unalf** and his Atari ones.

COPYRIGHT
=========

The original AlfCrunch (**DZ.COM** and **LZ.COM**) for the Atari
8-bit was released into the Public Domain. Portions of the **DZ.COM**
code are included in **unalf**, converted from 6502 instructions to
C macros.

**unalf** is released under the WTPFL: Do WTF you want with this.

AUTHOR
======

The original AlfCrunch for the Atari 8-bit was written by Alfred, who
can be reached via the AtariAge.com forums with the username "Alfred".

This **unalf** was written by B. Watson <urchlay@slackware.uk>.

SEE ALSO
========

**alf**\(1), **alfsum**\(1)

.. include:: manftr.rst
