home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1992 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1992.iso
/
usenet
/
altsrcs
/
3
/
3609
< prev
next >
Wrap
Text File
|
1991-07-10
|
49KB
|
1,619 lines
Newsgroups: alt.sources
Subject: zoo 2.1 source part 02/15
Message-ID: <12768@bsu-cs.bsu.edu>
From: dhesi@bsu-cs.bsu.edu (Rahul Dhesi)
Date: 10 Jul 91 08:48:26 GMT
Checksum: 837499929 (verify with "brik -cv")
Submitted-by: dhesi@bsu-cs.bsu.edu
Archive-name: zoo210/part02
---- Cut Here and feed the following to sh ----
#!/bin/sh
# This is part 02 of zoo210
# ============= comment.c ==============
if test -f 'comment.c' -a X"$1" != X"-c"; then
echo 'x - skipping comment.c (File already exists)'
else
echo 'x - extracting comment.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'comment.c' &&
#ifndef LINT
static char sccsid[]="@(#) comment.c 2.14 88/01/24 12:42:13";
#endif /* LINT */
X
/*
Copyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
(C) Copyright 1988 Rahul Dhesi -- All rights reserved
*/
X
#include "options.h"
#include "portable.h"
/* comment() */
/* Updates comments */
X
/* buffer size for any one comment line */
#define COMMENT_LINE_SIZE 76
X
#define MAX_COMMENT_SIZE 32767
#include "zooio.h"
#include "various.h"
X
#ifndef NOSIGNAL
#include <signal.h>
#endif
X
#include "zoo.h"
#include "zoofns.h"
#include "errors.i"
X
void show_comment PARMS ((struct direntry *, ZOOFILE, int, char *));
void get_comment PARMS ((struct direntry *, ZOOFILE, char *));
int needed PARMS ((char *, struct direntry *, struct zoo_header *));
X
void comment(zoo_path, option)
char *zoo_path, *option;
{
#ifndef NOSIGNAL
T_SIGNAL (*oldsignal)();
#endif
ZOOFILE zoo_file; /* stream for open archive */
long next_ptr; /* pointers to within archive */
long this_dir_offset; /* pointers to within archive */
struct direntry direntry; /* directory entry */
struct zoo_header zoo_header;
int matched = 0; /* any files matched? */
unsigned int zoo_date, zoo_time; /* for restoring archive timestamp */
char whichname[PATHSIZE]; /* which name to use */
#ifdef ZOOCOMMENT
int acmt = 0; /* if changing archive comment */
#endif
X
/* on entry option points to first letter */
option++; /* skip 'c' */
#ifdef ZOOCOMMENT
while (*option != '\0') {
X if (*option == 'A') {
X acmt++; /* changing archive comment */
X option++;
X } else
X prterror ('f', inv_option, *option);
}
#else
if (*option != '\0')
X prterror ('f', inv_option, *option);
#endif /* ZOOCOMMENT */
X
if ((zoo_file = zooopen (zoo_path, Z_RDWR)) == NOFILE)
X prterror ('f', could_not_open, zoo_path);
X
/* save archive timestamp */
#ifdef GETUTIME
getutime (zoo_path, &zoo_date, &zoo_time);
#else
gettime (zoo_file, &zoo_date, &zoo_time);
#endif
X
/* read header and rewrite with updated version numbers, but ask user to pack
archive first if archive comment is to be added and header type is 0 */
#ifdef ZOOCOMMENT
if (acmt)
X rwheader (&zoo_header, zoo_file, 0);
else
X rwheader (&zoo_header, zoo_file, 1);
#else
rwheader (&zoo_header, zoo_file, 1);
#endif
X
#ifdef ZOOCOMMENT
/* if archive comment being added, handle it and return */
if (acmt) {
X void do_acmt PARMS ((struct zoo_header *, ZOOFILE, char *));
X do_acmt (&zoo_header, zoo_file, zoo_path);
#ifdef NIXTIME
X zooclose (zoo_file);
X setutime (zoo_path, zoo_date, zoo_time); /* restore timestamp */
#else
X settime (zoo_file, zoo_date, zoo_time); /* restore timestamp */
X zooclose (zoo_file);
#endif
X return;
}
#endif /* ZOOCOMMENT */
X
/* Loop through and add comments for matching files */
while (1) {
X this_dir_offset = zootell (zoo_file); /* save pos'n of this dir entry */
X readdir (&direntry, zoo_file, 1); /* read directory entry */
X next_ptr = direntry.next; /* ptr to next dir entry */
X
X /* exit on end of directory chain or end of file */
X if (next_ptr == 0L || feof(stdin))
X break;
X
X strcpy (whichname, fullpath (&direntry)); /* full pathname */
X add_version (whichname, &direntry); /* add version suffix */
X /* add comments for matching non-deleted files */
X if (!direntry.deleted && needed (whichname, &direntry, &zoo_header)) {
X matched++;
X show_comment (&direntry, zoo_file, 1, whichname);
X get_comment (&direntry, zoo_file, whichname);
X zooseek (zoo_file, this_dir_offset, 0);
#ifndef NOSIGNAL
X oldsignal = signal (SIGINT, SIG_IGN);
#endif
X fwr_dir (&direntry, zoo_file);
#ifndef NOSIGNAL
X signal (SIGINT, oldsignal);
#endif
X }
X zooseek (zoo_file, next_ptr, 0); /* ..seek to next dir entry */
} /* end while */
X
#ifdef NIXTIME
zooclose (zoo_file);
setutime (zoo_path, zoo_date, zoo_time); /* restore timestamp */
#else
settime (zoo_file, zoo_date, zoo_time); /* restore timestamp */
zooclose (zoo_file);
#endif
X
if (!matched)
X printf ("Zoo: %s", no_match);
} /* comment */
X
/* show_comment() */
/* shows comment on screen. If show=1, says "Current comment is..." */
X
void show_comment (direntry, zoo_file, show, name)
struct direntry *direntry;
ZOOFILE zoo_file;
int show;
char *name; /* name of file for which comment is being added */
{
X if (direntry->cmt_size != 0) {
X unsigned int i;
X char ch;
X int newline = 1;
X zooseek (zoo_file, direntry->comment, 0);
X if (show)
X printf ("Current comment for %s is:\n", name);
X for (i = 0; i < direntry->cmt_size; i++) {/* show it */
X ch = zgetc (zoo_file) & 0x7f; /* 7 bits only */
X if (newline)
X printf (" |"); /* indent and mark comment lines thus */
X zputchar (ch);
X if (ch == '\n')
X newline = 1;
X else
X newline = 0;
X }
X if (!newline) /* always terminate with newline */
X zputchar ('\n');
X }
} /* show_comment() */
X
X
/* get_comment() */
/* Shows user old comment and updates it */
X
/* INPUT:
X direntry points to current directory entry.
X zoo_file is archive file.
X this_path is full pathname of file being updated/added.
X
X OUTPUT:
X Comment is added to file and supplied directory entry is updated
X with comment size and seek position but directory entry is
X not written to file. Exceptions: If RETURN is hit as first line,
X previous comment is left unchanged. If /END is hit, previous
X comment is superseded, even if new comment is null.
*/
X
char cmt_prompt[]="[Enter %scomment for %s then type /END]\n";
X
void get_comment (direntry, zoo_file, this_path) /* update comment */
register struct direntry *direntry;
ZOOFILE zoo_file;
char *this_path;
{
X unsigned int line_count = 0; /* count of new comment lines */
X
X zooseek (zoo_file, 0L, 2); /* ready to append new comment */
#if 0
X fprintf (stderr, "[Enter comment for %s then type /END]\n", this_path);
#else
X fprintf (stderr, cmt_prompt, "", this_path);
#endif
X while (1) {
X char cmt_line[COMMENT_LINE_SIZE];
X int cmt_size;
X if (fgets (cmt_line, sizeof(cmt_line), stdin) == NULL)
X break;
X line_count++;
X if (line_count == 1) { /* first line typed */
X if (!strcmp (cmt_line, "\n")) /* exit if first line blank */
X break;
X direntry->comment = zootell (zoo_file);
X direntry->cmt_size = 0;
X }
X if (!str_icmp (cmt_line, "/end\n"))
X break;
X cmt_size = strlen (cmt_line);
X if (MAX_COMMENT_SIZE - direntry->cmt_size > cmt_size) {
X direntry->cmt_size += (unsigned int) cmt_size;
X if (zoowrite (zoo_file, cmt_line, cmt_size) < cmt_size)
X prterror ('f', disk_full);
X }
X } /* end while */
} /* get_comment() */
X
#ifdef ZOOCOMMENT
/*
do_acmt() updates archive comment by showing it to user and
requesting a new one. Typed input terminates as with file comment,
i.e., empty initial line leaves comment unchanged, case-insensitive
"/end" terminates input comment.
*/
void do_acmt (zoo_header, zoo_file, zoo_path)
struct zoo_header *zoo_header;
ZOOFILE zoo_file;
char *zoo_path;
{
X unsigned int line_count = 0; /* count of new comment lines */
X void show_acmt PARMS ((struct zoo_header *, ZOOFILE, int));
X
X show_acmt (zoo_header, zoo_file, 1); /* show current archive comment */
X zooseek (zoo_file, 0L, 2); /* ready to append new comment */
#if 0
X fprintf (stderr, "[Enter archive comment for %s then type /END]\n",
X zoo_path);
#else
X fprintf (stderr, cmt_prompt, "archive ", zoo_path);
#endif
X
X while (1) {
X char cmt_line[COMMENT_LINE_SIZE];
X int cmt_size;
X if (fgets (cmt_line, sizeof(cmt_line), stdin) == NULL)
X break;
X line_count++;
X if (line_count == 1) { /* first line typed */
X if (!strcmp (cmt_line, "\n")) /* exit if first line blank */
X break;
X zoo_header->acmt_pos = zootell (zoo_file);
X zoo_header->acmt_len = 0;
X }
X if (!str_icmp (cmt_line, "/end\n"))
X break;
X cmt_size = strlen (cmt_line);
X if (MAX_COMMENT_SIZE - zoo_header->acmt_len > cmt_size) {
X zoo_header->acmt_len += (unsigned int) cmt_size;
X if (zoowrite (zoo_file, cmt_line, cmt_size) < cmt_size)
X prterror ('f', disk_full);
X }
X } /* end while */
X zooseek (zoo_file, 0L, 0); /* seek back to beginning */
X fwr_zooh (zoo_header, zoo_file); /* write update zoo_header */
} /* do_acmt() */
#endif /* ZOOCOMMENT */
X
/* Prints archive comment. If show==1, says "Current archive comment is:" */
void show_acmt (zoo_header, zoo_file, show)
struct zoo_header *zoo_header;
ZOOFILE zoo_file;
int show;
{
X if (zoo_header->zoo_start != FIXED_OFFSET && zoo_header->acmt_len > 0) {
X unsigned int i;
X char ch;
X int newline = 1;
X zooseek (zoo_file, zoo_header->acmt_pos, 0);
X if (show)
X printf ("Current archive comment is:\n");
X for (i = 0; i < zoo_header->acmt_len; i++) {/* show it */
X ch = zgetc (zoo_file) & 0x7f; /* 7 bits only */
X if (newline)
X printf (">> "); /* indent and mark comment lines thus */
X zputchar (ch);
X if (ch == '\n')
X newline = 1;
X else
X newline = 0;
X }
X if (!newline) /* always terminate with newline */
X zputchar ('\n');
X }
} /* show_acmt() */
SHAR_EOF
chmod 0644 comment.c ||
echo 'restore of comment.c failed'
Wc_c="`wc -c < 'comment.c'`"
test 9595 -eq "$Wc_c" ||
echo 'comment.c: original size 9595, current size' "$Wc_c"
fi
# ============= crcdefs.c ==============
if test -f 'crcdefs.c' -a X"$1" != X"-c"; then
echo 'x - skipping crcdefs.c (File already exists)'
else
echo 'x - extracting crcdefs.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'crcdefs.c' &&
#ifndef LINT
static char sccsid[]="@(#) crcdefs.c 2.1 87/12/25 12:21:58";
#endif /* LINT */
X
#include "options.h"
X
/*
Global definitions for CRC calculation. I claim no copyright over
the contents of this file.
X
X -- Rahul Dhesi 1987/08/27
*/
X
unsigned int crccode;
unsigned int crctab[] = {
X 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
X 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
X 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0F00, 0xcFc1, 0xce81, 0x0e40,
X 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
X 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
X 0x1e00, 0xdec1, 0xdF81, 0x1F40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
X 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
X 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
X 0xF001, 0x30c0, 0x3180, 0xF141, 0x3300, 0xF3c1, 0xF281, 0x3240,
X 0x3600, 0xF6c1, 0xF781, 0x3740, 0xF501, 0x35c0, 0x3480, 0xF441,
X 0x3c00, 0xFcc1, 0xFd81, 0x3d40, 0xFF01, 0x3Fc0, 0x3e80, 0xFe41,
X 0xFa01, 0x3ac0, 0x3b80, 0xFb41, 0x3900, 0xF9c1, 0xF881, 0x3840,
X 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
X 0xee01, 0x2ec0, 0x2F80, 0xeF41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
X 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
X 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
X 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
X 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
X 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaF01, 0x6Fc0, 0x6e80, 0xae41,
X 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
X 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
X 0xbe01, 0x7ec0, 0x7F80, 0xbF41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
X 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
X 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
X 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
X 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
X 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5F00, 0x9Fc1, 0x9e81, 0x5e40,
X 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
X 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
X 0x4e00, 0x8ec1, 0x8F81, 0x4F40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
X 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
X 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
};
SHAR_EOF
chmod 0644 crcdefs.c ||
echo 'restore of crcdefs.c failed'
Wc_c="`wc -c < 'crcdefs.c'`"
test 2446 -eq "$Wc_c" ||
echo 'crcdefs.c: original size 2446, current size' "$Wc_c"
fi
# ============= debug.h ==============
if test -f 'debug.h' -a X"$1" != X"-c"; then
echo 'x - skipping debug.h (File already exists)'
else
echo 'x - extracting debug.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'debug.h' &&
/* @(#) debug.h 2.1 87/12/25 12:22:02 */
X
/*
The contents of this file are hereby released to the public domain.
X
X -- Rahul Dhesi 1986/11/14
X
defines conditional function calls
X
Usage: The statement
X
X debug((printf("y = %d\n", y)))
X
may be placed anywhere where two or more statements could be used. It will
print the value of y at that point.
X
Conditional compilation:
X
X if DEBUG is defined
X define the macro debug(X) to execute statement X
X else
X define the macro debug(X) to be null
X endif
*/
X
#ifdef DEBUG
#define debug(x) x;
#else
#define debug(x)
#endif
X
SHAR_EOF
chmod 0644 debug.h ||
echo 'restore of debug.h failed'
Wc_c="`wc -c < 'debug.h'`"
test 615 -eq "$Wc_c" ||
echo 'debug.h: original size 615, current size' "$Wc_c"
fi
# ============= decode.c ==============
if test -f 'decode.c' -a X"$1" != X"-c"; then
echo 'x - skipping decode.c (File already exists)'
else
echo 'x - extracting decode.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'decode.c' &&
/*$Source: /usr/home/dhesi/zoo/RCS/decode.c,v $*/
/*$Id: decode.c,v 1.6 91/07/09 01:39:49 dhesi Exp $*/
/***********************************************************
X decode.c
X
Adapted from "ar" archiver written by Haruhiko Okumura.
***********************************************************/
X
#include "options.h"
#include "zoo.h"
#include "ar.h"
#include "lzh.h"
X
extern int decoded; /* from huf.c */
X
static int j; /* remaining bytes to copy */
X
void decode_start()
{
X huf_decode_start();
X j = 0;
X decoded = 0;
}
X
/*
decodes; returns no. of chars decoded
*/
X
int decode(count, buffer)
uint count;
uchar buffer[];
X /* The calling function must keep the number of
X bytes to be processed. This function decodes
X either 'count' bytes or 'DICSIZ' bytes, whichever
X is smaller, into the array 'buffer[]' of size
X 'DICSIZ' or more.
X Call decode_start() once for each new file
X before calling this function. */
{
X static uint i;
X uint r, c;
X
X r = 0;
X while (--j >= 0) {
X buffer[r] = buffer[i];
X i = (i + 1) & (DICSIZ - 1);
X if (++r == count)
X return r;
X }
X for ( ; ; ) {
X c = decode_c();
X if (decoded)
X return r;
X if (c <= UCHAR_MAX) {
X buffer[r] = c;
X if (++r == count)
X return r;
X } else {
X j = c - (UCHAR_MAX + 1 - THRESHOLD);
X i = (r - decode_p() - 1) & (DICSIZ - 1);
X while (--j >= 0) {
X buffer[r] = buffer[i];
X i = (i + 1) & (DICSIZ - 1);
X if (++r == count)
X return r;
X }
X }
X }
}
SHAR_EOF
chmod 0644 decode.c ||
echo 'restore of decode.c failed'
Wc_c="`wc -c < 'decode.c'`"
test 1444 -eq "$Wc_c" ||
echo 'decode.c: original size 1444, current size' "$Wc_c"
fi
# ============= descrip.mms ==============
if test -f 'descrip.mms' -a X"$1" != X"-c"; then
echo 'x - skipping descrip.mms (File already exists)'
else
echo 'x - extracting descrip.mms (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'descrip.mms' &&
# derived from: @(#) descrip.mms 2.2 88/01/09 12:10:49
# $Source: /usr/home/dhesi/zoo/RCS/descrip.mms,v $
# $Id: descrip.mms,v 1.9 91/07/07 14:58:21 dhesi Exp $
#Make Zoo for VAX/VMS
#
#The contents of this makefile are hereby released to the public domain.
# -- Rahul Dhesi 1991/07/06
X
CC = cc
CFLAGS =
EXTRA = /define=(BIG_MEM,NDEBUG,VMS)
ldswitch =
X
#List of all object files created for Zoo
ZOOOBJS = addbfcrc.obj, addfname.obj, basename.obj, comment.obj, -
X crcdefs.obj, decode.obj, encode.obj, getfile.obj, huf.obj, -
X io.obj, lzc.obj, lzd.obj, lzh.obj, machine.obj, makelist.obj, -
X maketbl.obj, maketree.obj, misc.obj, misc2.obj, needed.obj, -
X nextfile.obj, options.obj, parse.obj, portable.obj, prterror.obj, -
X version.obj, vmstime.obj, zoo.obj, zooadd.obj, zooadd2.obj, -
X zoodel.obj, zooext.obj, zoolist.obj, zoopack.obj
X
FIZOBJS = fiz.obj, addbfcrc.obj, portable.obj, crcdefs.obj
X
BILFOBJS = bilf.obj
X
.c.obj :
X $(CC) $(CFLAGS) $(EXTRA) $*.c
X
zoo.exe : $(ZOOOBJS)
X link/executable=zoo.exe $(ldswitch) $(ZOOOBJS), options/opt
X
# bigger but perhaps more (less?) portable across machines --
# no shared libraries
zoobig.exe : $(ZOOOBJS)
X link/executable=zoobig.exe $(ldswitch) $(ZOOOBJS)
X
fiz : $(FIZOBJS)
X link/executable=fiz.exe $(ldswitch) $(FIZOBJS), options/opt
X
bilf : $(BILFOBJS)
X link/executable=bilf.exe $(ldswitch) $(BILFOBJS), options/opt
X
#######################################################################
# DEPENDENCIES -- not guaranteed to be up-to-date
#######################################################################
X
addbfcrc.obj : options.h
addfname.obj : options.h various.h zoo.h zoofns.h zooio.h
addfname.obj : zoomem.h
basename.obj : assert.h debug.h options.h parse.h various.h
basename.obj : zoo.h zoofns.h zooio.h
comment.obj : errors.i options.h portable.h various.h
comment.obj : zoo.h zoofns.h zooio.h
crcdefs.obj : options.h
decode.obj : ar.h lzh.h options.h zoo.h
encode.obj : ar.h errors.i lzh.h
encode.obj : options.h zoo.h
fiz.obj : options.h portable.h various.h zoo.h zoofns.h
fiz.obj : zooio.h
getfile.obj : options.h various.h zoo.h zoofns.h zooio.h
getfile.obj : zoomem.h
huf.obj : ar.h errors.i lzh.h options.h zoo.h
io.obj : ar.h errors.i lzh.h options.h portable.h zoo.h
io.obj : zooio.h
lzc.obj : assert.h debug.h lzconst.h options.h various.h
lzc.obj : zoo.h zoofns.h zooio.h zoomem.h
lzd.obj : assert.h debug.h lzconst.h options.h various.h
lzd.obj : zoo.h zoofns.h zooio.h zoomem.h
lzh.obj : ar.h errors.i options.h zoo.h
machine.obj : options.h various.h zoo.h zoofns.h zooio.h
makelist.obj : assert.h debug.h errors.i options.h
makelist.obj : portable.h various.h zoo.h zoofns.h zooio.h
maketbl.obj : ar.h lzh.h options.h zoo.h
maketree.obj : ar.h lzh.h options.h zoo.h
misc.obj : errors.i options.h portable.h various.h zoo.h zoofns.h zooio.h
misc2.obj : errors.i options.h portable.h various.h zoo.h
misc2.obj : zoofns.h zooio.h zoomem.h
msdos.obj : errors.i options.h zoo.h zoofns.h zooio.h
needed.obj : debug.h options.h portable.h various.h zoo.h
needed.obj : zoofns.h zooio.h
nextfile.obj : options.h various.h zoo.h
options.obj : errors.i options.h various.h zoo.h zoofns.h
options.obj : zooio.h
parse.obj : assert.h options.h parse.h various.h zoo.h
parse.obj : zoofns.h zooio.h
portable.obj : assert.h debug.h machine.h options.h
portable.obj : portable.h various.h zoo.h zoofns.h zooio.h
prterror.obj : options.h various.h
prterror.obj : zoofns.h zooio.h
zoo.obj : errors.i options.h various.h zoo.h zoofns.h
zoo.obj : zooio.h zoomem.h
zooadd.obj : debug.h errors.i options.h parse.h portable.h
zooadd.obj : various.h zoo.h zoofns.h zooio.h zoomem.h
zooadd2.obj : assert.h debug.h errors.i options.h parse.h
zooadd2.obj : various.h zoo.h zoofns.h zooio.h
zoodel.obj : errors.i options.h portable.h various.h zoo.h zoofns.h zooio.h
zooext.obj : errors.i machine.h options.h parse.h portable.h various.h zoo.h
zooext.obj : zoofns.h zooio.h
zoofilt.obj : options.h
zoolist.obj : errors.i options.h portable.h various.h zoo.h
zoolist.obj : zoofns.h zooio.h zoomem.h
zoopack.obj : errors.i options.h portable.h various.h
zoopack.obj : zoo.h zoofns.h zooio.h
SHAR_EOF
chmod 0644 descrip.mms ||
echo 'restore of descrip.mms failed'
Wc_c="`wc -c < 'descrip.mms'`"
test 4173 -eq "$Wc_c" ||
echo 'descrip.mms: original size 4173, current size' "$Wc_c"
fi
# ============= encode.c ==============
if test -f 'encode.c' -a X"$1" != X"-c"; then
echo 'x - skipping encode.c (File already exists)'
else
echo 'x - extracting encode.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'encode.c' &&
/*$Source: /usr/home/dhesi/zoo/RCS/encode.c,v $*/
/*$Id: encode.c,v 1.41 91/07/09 01:39:47 dhesi Exp $*/
X
/*
Adapted from "ar" archiver written by Haruhiko Okumura.
*/
X
#include "options.h"
#include "zoo.h"
#include "ar.h"
#include "lzh.h"
X
extern void prterror();
extern char *out_buf_adr;
X
#include <assert.h>
X
#ifdef ANSI_HDRS
# include <stdlib.h>
# include <string.h>
#endif
X
#include "errors.i"
X
FILE *lzh_infile;
FILE *lzh_outfile;
X
/*
sliding dictionary with percolating update
*/
X
#define PERCOLATE 1
#define NIL 0
#define MAX_HASH_VAL (3 * DICSIZ + (DICSIZ / 512 + 1) * UCHAR_MAX)
X
typedef short node;
X
static uchar *text, *childcount;
static node pos, matchpos, avail,
X *position, *parent, *prev, *next = NULL;
static int remainder, matchlen;
X
#if MAXMATCH <= (UCHAR_MAX + 1)
X static uchar *level;
# define T_LEVEL uchar *
#else
X static ushort *level;
# define T_LEVEL ushort *
#endif
X
static void allocate_memory()
{
X if (next != NULL) return;
X /* text = (uchar *) malloc(DICSIZ * 2 + MAXMATCH); */
X text = (uchar *) out_buf_adr; /* reuse I/O buffer used elsewhere */
X level = (T_LEVEL) malloc((DICSIZ + UCHAR_MAX + 1) * sizeof(*level));
X childcount = (uchar *)malloc((DICSIZ + UCHAR_MAX + 1) * sizeof(*childcount));
#ifdef PERCOLATE
X position = (node *) malloc((DICSIZ + UCHAR_MAX + 1) * sizeof(*position));
#else
X position = (node *) malloc(DICSIZ * sizeof(*position));
#endif
X parent = (node *) malloc(DICSIZ * 2 * sizeof(*parent));
X prev = (node *) malloc(DICSIZ * 2 * sizeof(*prev));
X next = (node *) malloc((MAX_HASH_VAL + 1) * sizeof(*next));
X if (next == NULL) prterror('f', no_memory);
}
X
static void init_slide()
{
X node i;
X
X for (i = DICSIZ; i <= DICSIZ + UCHAR_MAX; i++) {
X level[i] = 1;
#ifdef PERCOLATE
X position[i] = NIL; /* sentinel */
#endif
X }
X for (i = DICSIZ; i < DICSIZ * 2; i++) parent[i] = NIL;
X avail = 1;
X for (i = 1; i < DICSIZ - 1; i++) next[i] = i + 1;
X next[DICSIZ - 1] = NIL;
X for (i = DICSIZ * 2; i <= MAX_HASH_VAL; i++) next[i] = NIL;
}
X
#define HASH(p, c) ((p) + ((c) << (DICBIT - 9)) + DICSIZ * 2)
X
static node child(q, c)
node q;
uchar c;
X /* q's child for character c (NIL if not found) */
{
X node r;
X
X r = next[HASH(q, c)];
X parent[NIL] = q; /* sentinel */
X while (parent[r] != q) r = next[r];
X return r;
}
X
static void makechild(q, c, r)
node q;
uchar c;
node r;
X /* Let r be q's child for character c. */
{
X node h, t;
X
X h = HASH(q, c);
X t = next[h]; next[h] = r; next[r] = t;
X prev[t] = r; prev[r] = h;
X parent[r] = q; childcount[q]++;
}
X
void split(old)
node old;
{
X node new, t;
X
X new = avail; avail = next[new]; childcount[new] = 0;
X t = prev[old]; prev[new] = t; next[t] = new;
X t = next[old]; next[new] = t; prev[t] = new;
X parent[new] = parent[old];
X level[new] = matchlen;
X position[new] = pos;
X makechild(new, text[matchpos + matchlen], old);
X makechild(new, text[pos + matchlen], pos);
}
X
static void insert_node()
{
X node q, r, j, t;
X uchar c, *t1, *t2;
X
X if (matchlen >= 4) {
X matchlen--;
X r = (matchpos + 1) | DICSIZ;
X while ((q = parent[r]) == NIL) r = next[r];
X while (level[q] >= matchlen) {
X r = q; q = parent[q];
X }
#ifdef PERCOLATE
X t = q;
X while (position[t] < 0) {
X position[t] = pos; t = parent[t];
X }
X if (t < DICSIZ) position[t] = pos | PERC_FLAG;
#else
X t = q;
X while (t < DICSIZ) {
X position[t] = pos; t = parent[t];
X }
#endif
X } else {
X q = text[pos] + DICSIZ; c = text[pos + 1];
X if ((r = child(q, c)) == NIL) {
X makechild(q, c, pos); matchlen = 1;
X return;
X }
X matchlen = 2;
X }
X for ( ; ; ) {
X if (r >= DICSIZ) {
X j = MAXMATCH; matchpos = r;
X } else {
X j = level[r];
X matchpos = position[r] & ~PERC_FLAG;
X }
X if (matchpos >= pos) matchpos -= DICSIZ;
X t1 = &text[pos + matchlen]; t2 = &text[matchpos + matchlen];
X while (matchlen < j) {
X if (*t1 != *t2) { split(r); return; }
X matchlen++; t1++; t2++;
X }
X if (matchlen >= MAXMATCH) break;
X position[r] = pos;
X q = r;
X if ((r = child(q, *t1)) == NIL) {
X makechild(q, *t1, pos); return;
X }
X matchlen++;
X }
X t = prev[r]; prev[pos] = t; next[t] = pos;
X t = next[r]; next[pos] = t; prev[t] = pos;
X parent[pos] = q; parent[r] = NIL;
X next[r] = pos; /* special use of next[] */
}
X
static void delete_node()
{
#ifdef PERCOLATE
X node q, r, s, t, u;
#else
X node r, s, t, u;
#endif
X
X if (parent[pos] == NIL) return;
X r = prev[pos]; s = next[pos];
X next[r] = s; prev[s] = r;
X r = parent[pos]; parent[pos] = NIL;
X if (r >= DICSIZ || --childcount[r] > 1) return;
#ifdef PERCOLATE
X t = position[r] & ~PERC_FLAG;
#else
X t = position[r];
#endif
X if (t >= pos) t -= DICSIZ;
#ifdef PERCOLATE
X s = t; q = parent[r];
X while ((u = position[q]) & PERC_FLAG) {
X u &= ~PERC_FLAG; if (u >= pos) u -= DICSIZ;
X if (u > s) s = u;
X position[q] = (s | DICSIZ); q = parent[q];
X }
X if (q < DICSIZ) {
X if (u >= pos) u -= DICSIZ;
X if (u > s) s = u;
X position[q] = s | DICSIZ | PERC_FLAG;
X }
#endif
X s = child(r, text[t + level[r]]);
X t = prev[s]; u = next[s];
X next[t] = u; prev[u] = t;
X t = prev[r]; next[t] = s; prev[s] = t;
X t = next[r]; prev[t] = s; next[s] = t;
X parent[s] = parent[r]; parent[r] = NIL;
X next[r] = avail; avail = r;
}
X
static void get_next_match()
{
X int n;
X
X remainder--;
X if (++pos == DICSIZ * 2) {
#ifdef CHECK_BREAK
X check_break();
#endif
X (void) MOVE_LEFT((char *) &text[0], (char *) &text[DICSIZ], DICSIZ + MAXMATCH);
X n = fread_crc(&text[DICSIZ + MAXMATCH], DICSIZ, lzh_infile);
X remainder += n; pos = DICSIZ;
#ifdef SHOW_DOTS
X (void) putc('.', stderr);
X (void) fflush(stderr);
#endif
X }
X delete_node(); insert_node();
}
X
/* read from infile, compress, write to outfile */
void encode(infile, outfile)
FILE *infile;
FILE *outfile;
{
X int lastmatchlen;
X node lastmatchpos;
X
X /* make input/output files visible to other functions */
X lzh_infile = infile;
X lzh_outfile = outfile;
X
X allocate_memory(); init_slide(); huf_encode_start();
X remainder = fread_crc(&text[DICSIZ], DICSIZ + MAXMATCH, lzh_infile);
#ifdef SHOW_DOTS
X (void) putc('.', stderr);
X (void) fflush(stderr);
#endif
X matchlen = 0;
X pos = DICSIZ; insert_node();
X if (matchlen > remainder) matchlen = remainder;
X while (remainder > 0 && ! unpackable) {
X lastmatchlen = matchlen; lastmatchpos = matchpos;
X get_next_match();
X if (matchlen > remainder) matchlen = remainder;
X if (matchlen > lastmatchlen || lastmatchlen < THRESHOLD) {
#if 0
X d1log("%c", text[pos-1]);
#endif
X output(text[pos - 1], 0);
X } else {
#if 0
X (void) putc('.', stderr); (void) fflush(stderr);
#endif
X
#if 0
X {
X int i;
X d1log("\nlastmatchlen=%d, pos=%d, lastmatchpos=%d",
X lastmatchlen, pos, lastmatchpos);
X d1log("\n[%d: ", (int) lastmatchlen);
X for (i = 0; i < lastmatchlen; i++)
X d1log("%c", text[lastmatchpos + i]);
X d1log("]\n");
X }
#endif
X
X output((uint) (lastmatchlen + (UCHAR_MAX + 1 - THRESHOLD)),
X (uint) ((pos - lastmatchpos - 2) & (DICSIZ - 1)));
X while (--lastmatchlen > 0) get_next_match();
X if (matchlen > remainder) matchlen = remainder;
X }
X }
X huf_encode_end();
}
X
#ifdef NEED_MEMMOVE
/* like memmove, but for moving stuff LEFT (downwards in memory) only!! */
void move_left(dest, src, len)
char *dest;
char *src;
int len;
{
X while (len-- > 0)
X *dest++ = *src++;
}
#endif /* NEED_MEMMOVE */
SHAR_EOF
chmod 0644 encode.c ||
echo 'restore of encode.c failed'
Wc_c="`wc -c < 'encode.c'`"
test 7292 -eq "$Wc_c" ||
echo 'encode.c: original size 7292, current size' "$Wc_c"
fi
# ============= errors.i ==============
if test -f 'errors.i' -a X"$1" != X"-c"; then
echo 'x - skipping errors.i (File already exists)'
else
echo 'x - extracting errors.i (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'errors.i' &&
/* @(#) errors.i 2.4 88/01/31 12:32:46 */
X
/*
The contents of this file are hereby released to the public domain.
X
X -- Rahul Dhesi 1986/11/14
*/
X
/* defines all the errors as externs. Declarations must be
equivalent to those in prterror.c */
X
/* These declarations must be equivalent to those in prterror.c */
extern char no_match[];
extern char failed_consistency[];
extern char invalid_header[];
extern char internal_error[];
extern char disk_full[];
extern char bad_directory[];
extern char no_memory[];
extern char too_many_files[];
extern char packfirst[];
extern char garbled[];
extern char start_ofs[];
X
#ifndef OOZ
extern char wrong_version[];
extern char cant_process[];
extern char option_ignored[];
extern char inv_option[];
extern char bad_crc[];
#endif
X
extern char could_not_open[];
X
SHAR_EOF
chmod 0644 errors.i ||
echo 'restore of errors.i failed'
Wc_c="`wc -c < 'errors.i'`"
test 825 -eq "$Wc_c" ||
echo 'errors.i: original size 825, current size' "$Wc_c"
fi
# ============= file.fix ==============
if test -f 'file.fix' -a X"$1" != X"-c"; then
echo 'x - skipping file.fix (File already exists)'
else
echo 'x - extracting file.fix (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'file.fix' &&
X Making the "file" command recognize zoo archives
X
Zoo archives have the following magic number: Beginning at offset 20
decimal, there are four bytes with the values 0xdc, 0xa7, 0xc4, and
0xfd. (But if you call the first byte of a zoo archive byte 1, then
the magic bytes will be bytes 21 through 24.)
X
To make the "file" command identify zoo archives, changes can be made
as follows.
X
4.3BSD: See the context diff near the end of this document, suitable
for application with the "patch" utility, that works with the 4.3BSD
"file" command on a VAX-11/785. I don't know if this will also work
under 4.2BSD or with any other implementation of the "file" command
or on any other CPU.
X
System V Release 2 (as exemplified by Microport System V/AT): At the
end of the file "/etc/magic", add the following line:
X
20 long 0xfdc4a7dc zoo archive
X
This should work on a little-endian machine, in which the long value
0xfdc4a7dc is stored with the least-significant byte first. For a big-
endian machine, you will probably need to replace it with 0xdca7c4fd.
This assumes that long occupies 4 bytes. If not, use a data type name
that is exactly 4 bytes.
X
=====
Changes needed to make the 4.3BSD "file" command recognize zoo
archives. Known to work on a VAX-11/785.
X
*** file.c.old Thu Mar 6 19:34:29 1986
--- file.c Sat Feb 21 19:28:52 1987
***************
*** 172,181 ****
--- 172,187 ----
X case 070707:
X printf("cpio data\n");
X return;
X }
X
+ if (buf[20] == (char) 0xdc && buf[21] == (char) 0xa7 &&
+ buf[22] == (char) 0xc4 && buf[23] == (char) 0xfd) {
+ printf ("zoo archive\n");
+ return;
+ }
+
X if (buf[0] == '#' && buf[1] == '!' && shellscript(buf+2, &mbuf))
X return;
X if (buf[0] == '\037' && buf[1] == '\235') {
X if (buf[2]&0x80)
X printf("block ");
SHAR_EOF
chmod 0644 file.fix ||
echo 'restore of file.fix failed'
Wc_c="`wc -c < 'file.fix'`"
test 1814 -eq "$Wc_c" ||
echo 'file.fix: original size 1814, current size' "$Wc_c"
fi
# ============= fiz.1 ==============
if test -f 'fiz.1' -a X"$1" != X"-c"; then
echo 'x - skipping fiz.1 (File already exists)'
else
echo 'x - extracting fiz.1 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'fiz.1' &&
.\" @(#) fiz.1 1.2 88/01/31 23:22:04
.\"
.\" For formatting with nroff:
.\" nroff -man fiz.1
.\"
.TH FIZ 1 "Jan 31, 1988"
.SH NAME
fiz \- analyze damaged zoo archive for data revovery
.SH SYNOPSIS
.I fiz
.RB archive[ .zoo ]
.SH DESCRIPTION
.I Fiz
is used to analyze damaged
.I zoo
archives and locate directory entries and file data in them.
The current version of
.I fiz
is 2.0 and it is meant to be used in conjunction with
.I zoo
version 2.0.
.I Fiz
makes no assumptions about archive structure. Instead, it simply
searches the entire subject archive for tag values
that mark the locations of directory entries and file data.
In a
.I zoo
archive, a
.I directory entry
contains information about a stored file such as its name, whether
compressed or not, and its timestamp. The
.I file data
are the actual data for the archived file, and may be
either the original data, or the result of compressing the file.
.PP
For each directory entry found,
.I fiz
prints where in the archive it is located, the directory path and
filename(s) found in it, whether the directory entry appears
to be corrupted (indicated by [*CRC Error*]), and the value of
the pointer to the file data that is found in the directory entry.
For each block of file data found in the archive,
.I fiz
prints where in the archive the block begins. In the case of
an undamaged archive, the pointer to file data found in
a directory entry will correspond to where
.I fiz
actually locates the data. Here is some sample output from
.I fiz:
.PP
.nf
****************
X 2526: DIR [changes] ==> 95
X 2587: DATA
****************
X 3909: DIR [copyrite] ==> 1478
X 3970: DATA
X 4769: DATA
****************
.fi
.sp 1
In such output,
.B DIR
indicates where
.I fiz
found a directory entry in the archive, and
.B DATA
indicates where
.I fiz
found file data in the archive. Filenames located by
.I fiz
are enclosed in square brackets, and the notation
"==> 95" indicates that the directory entry found by
.I fiz
at position 2526 has a file data pointer to
position 95. In actuality,
.I fiz
found file data at positions 2587, 3970, and
4769. Since
.I fiz
found only two directory entries, and each directory entry corresponds
to one file, one of the file data positions is an artifact.
.PP
Once the locations of directory entries and file data are found, the
.B @
modifier to
.I "zoo's"
archive list and extract commands can be used and
the archive contents selectively listed or extracted,
skipping the damaged portion. This is further described
in the documentation for
.I zoo(1).
.PP
In the above case, commands to try giving to
.I zoo
might be
.B x@2526,2587
(extract beginning at position 2526, and get file data
from position 2587),
.B x@3090,3970
(extract at 3090, get data from 3970)
and
.B x@3909,4769
(extract at 3909, get data from 4769). Once a correctly-matched
directory entry/file data pair is found,
.I zoo
will in most cases synchronize with and correctly extract all files
subsequently found in the archive. Trial and error should allow
all undamaged files to be extracted.
Also note that self-extracting archives created using
.I sez
(the Self-Extracting
.I Zoo
utility for MS-DOS), which are normally executed on an MS-DOS
system for extraction, can
be extracted on non-MSDOS systems in a similar way.
.PP
.SH "SEE ALSO"
zoo(1)
.SH BUGS
Random byte patterns can occasionally be incorrectly recognized
as tag values. This occurs very rarely, however, and trial
and error will usually permit all undamaged data to be
extracted.
.SH DIAGNOSTICS
.I Fiz
always exits with a status code of 0.
.SH "FUTURE DIRECTIONS"
Automation of data recovery from a damaged archive is potentially
achievable. However, since damaged archives occur only rarely,
.I fiz
as it currently stands is unlikely to change much in the
near future.
.SH AUTHOR
Rahul Dhesi
SHAR_EOF
chmod 0644 fiz.1 ||
echo 'restore of fiz.1 failed'
Wc_c="`wc -c < 'fiz.1'`"
test 3849 -eq "$Wc_c" ||
echo 'fiz.1: original size 3849, current size' "$Wc_c"
fi
# ============= fiz.c ==============
if test -f 'fiz.c' -a X"$1" != X"-c"; then
echo 'x - skipping fiz.c (File already exists)'
else
echo 'x - extracting fiz.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'fiz.c' &&
#ifndef LINT
static char sccsid[]="@(#) fiz.c 2.6 88/01/31 23:23:50";
#endif /* LINT */
X
/*
The contents of this file are hereby released to the public domain.
X
X -- Rahul Dhesi 1987/02/06
*/
X
/*
Searches for all directory entries in an archive and prints their
offsets. Zoo 1.41 and later may then be asked to extract a specific
file by supplying the offset of the file.
*/
X
#include "options.h"
#include "zooio.h"
#include "various.h"
#include "zoofns.h"
#include "portable.h" /* I/O definitions */
#include "zoo.h"
X
void prtctrl ();
void prtch ();
X
main(argc,argv)
register int argc;
register char **argv;
{
X char *zooname; /* name of archive to be read */
X ZOOFILE zoo_file; /* the archive being examined opened for read */
X int state; /* to keep track of how much of tag seen */
X int inch; /* char just read from archive */
X
X static char usage1[] = "Fiz 2.0 (1987/02/01) public domain Zoo archive repair utility by Rahul Dhesi\n";
X static char usage2[] = "Usage: fiz archive[.zoo] (\"fiz -h\" for help)\n";
X
#ifdef SETBUF
/* set stdout to unbuffered */
setbuf (stdout, (char *) NULL);
#endif
X
X if (argc < 2) {
X printf("%s%s", usage1, usage2);
X exit (1);
X }
X
X if (strcmp(argv[1],"-h") == 0)
X goto givehelp;
X
X zooname = argv[1];
X
X /* Add default extension if none supplied */
X {
X char *p, *q;
X p = zooname + strlen(zooname); /* point to last char */
X while (p != zooname && *p != EXT_CH)
X --p;
X /* either found EXT_CH or reached beginning of zooname */
X if (*p != EXT_CH) {
X q = malloc(strlen(zooname) + strlen(EXT_DFLT) + 2);
X if (q == NULL) {
X printf("Fiz: Ran out of memory.\n");
X exit(1);
X }
X strcpy(q, zooname);
X strcat(q, EXT_DFLT);
X zooname = q;
X }
X }
X
X zoo_file = zooopen (zooname, Z_READ);
X if (zoo_file == NOFILE) {
X printf("Fiz: FATAL: Could not open %s.\n", zooname);
X exit(1);
X }
X
#ifdef DOUBLE_SECRET
X { void oh_well(void); oh_well(); }
#endif
X
#define NOSTATE 1
#define HDR_1 0xdc
#define HDR_2 0xa7
#define HDR_3 0xc4
#define HDR_4 0xfd
X
#define DAT_1 '@'
#define DAT_2 ')'
#define DAT_3 '#'
#define DAT_4 '('
X
/* finite state machine implemented here by hand */
X
X state = NOSTATE;
X while ((inch = zgetc(zoo_file)) != EOF) {
X inch = inch & 0xff;
X if (state == NOSTATE) {
X if (inch == HDR_1)
X state = HDR_1;
X else if (inch == DAT_1)
X state = DAT_1;
X } else if (state == HDR_1 && inch == HDR_2)
X state = HDR_2;
X else if (state == HDR_2 && inch == HDR_3)
X state = HDR_3;
X else if (state == HDR_3 && inch == HDR_4)
X state = HDR_4;
X else if (state == DAT_1 && inch == DAT_2)
X state = DAT_2;
X else if (state == DAT_2 && inch == DAT_3)
X state = DAT_3;
X else if (state == DAT_3 && inch == DAT_4)
X state = DAT_4;
X else
X state = NOSTATE;
X
X if (state == HDR_4) { /* found archive tag */
X long save_pos;
X struct direntry direntry;
X save_pos = zootell(zoo_file);
X zooseek(zoo_file, save_pos-4L, 0); /* back to tag pos */
X frd_dir(&direntry, zoo_file); /* read dir entry */
X printf("****************\n");
X
X printf ("%8lu: DIR ", save_pos-4L);
X
X if (direntry.dirlen > 0) {
X printf ("[");
X prtctrl (direntry.dirname);
X printf ("]");
X }
X
X printf(" [");
X prtctrl (direntry.fname);
X printf ("]");
X
X if (direntry.namlen > 0) {
X printf (" [");
X prtctrl (direntry.lfname);
X printf ("]");
X }
X printf (" ==> %4lu", direntry.offset);
X if (direntry.dir_crc != 0)
X printf (" [*bad CRC*]");
X printf ("\n");
X fseek (zoo_file, save_pos, 0); /* try again from there */
X } else if (state == DAT_4) { /* file data */
X printf ("%8lu: DATA\n", zootell(zoo_file) + 1);
X }
X }
exit (0); /* don't fall through */
X
givehelp:
X
/*
vi macros:
to add printf:
:s/^.*$/printf("&\\n");/
To remove printf:
:s/^printf("\(.*\)\\n");/\1/
*/
printf("Fiz is used to help you recover data from a damaged archive. Fiz searches\n");
printf("the specified archive for directory entries and stored files, and prints the\n");
printf("position of each one found. Each directory entry contains a number that\n");
printf("represents the location in the archive where the file is stored; fiz also\n");
printf("prints this position. All numbers printed are decimal numbers.\n\n");
X
printf("Use Zoo version 2.00 or higher to list or extract files in the damaged\n");
printf("archive starting at a position identified by fiz. For example, you can\n");
printf("start extracting files from archive \"badarc.zoo\" at position 1098 with the\n");
printf("command:\n\n");
X
printf(" zoo x@1098 badarc\n\n");
X
printf("Zoo will ignore the first 1098 bytes of the damaged archive and you should be\n");
printf("able to recover the undamaged files from the rest of the archive. You can\n");
printf("also manually specify where to look for the file data with a command like\n\n");
X
printf(" zoo x@1098,1153\n\n");
X
printf("which tells zoo to use the directory entry at position 1098, but to get the\n");
printf("actual file data from position 1153 (and not from where the directory entry\n");
printf("says the data ought to be). See the manuals for fiz and zoo for more details.\n");
X
exit (0);
}
X
/*
prtctrl() prints a string with all unprintable characters converted
to printable form. To avoid the program running astray trying to
print damaged data, no more than MAXPRT characters are printed.
Characters with the 8th bit set are printed preceded with ~. Control
characters are printed preceded with ^. Both ~ and ^ may preced
the character if a control character has the 8th bit set.
*/
#define MAXPRT 50
X
void prtctrl (str)
char *str;
{
X unsigned int ch;
X int count;
X count = 0;
X
X while (count < MAXPRT && *str != '\0') {
X ch = (unsigned) *str;
X prtch(ch);
X str++;
X count++;
X }
}
X
/*
Does the actual character printing for prtctrl()
*/
void prtch(ch)
unsigned int ch;
{
X /* assumes ASCII character set */
X if (ch < ' ') { /* ^@ through ^_ */
X printf("^%c", ch + 0x40);
X } else if (ch == 0x7f) { /* DEL */
X printf("^?");
X } else if (ch > 0x7f) { /* 8th bit set */
X printf("~"); /* .. so precede with ~ */
X prtch(ch & 0x7f); /* slick recursive call */
X } else
X printf("%c", ch); /* plain char */
}
SHAR_EOF
chmod 0644 fiz.c ||
echo 'restore of fiz.c failed'
Wc_c="`wc -c < 'fiz.c'`"
test 6784 -eq "$Wc_c" ||
echo 'fiz.c: original size 6784, current size' "$Wc_c"
fi
# ============= fiz.man ==============
if test -f 'fiz.man' -a X"$1" != X"-c"; then
echo 'x - skipping fiz.man (File already exists)'
else
echo 'x - extracting fiz.man (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'fiz.man' &&
X
X
X
FIZ(1) **IX Programmer's Manual FIZ(1)
X
X
X
NAME
X fiz - analyze damaged zoo archive for data revovery
X
SYNOPSIS
X fiz archive[.zoo]
X
DESCRIPTION
X Fiz is used to analyze damaged zoo archives and locate
X directory entries and file data in them. The current ver-
X sion of fiz is 2.0 and it is meant to be used in conjunction
X with zoo version 2.0. Fiz makes no assumptions about
X archive structure. Instead, it simply searches the entire
X subject archive for tag values that mark the locations of
X directory entries and file data. In a zoo archive, a direc-
X tory entry contains information about a stored file such as
X its name, whether compressed or not, and its timestamp. The
X file data are the actual data for the archived file, and may
X be either the original data, or the result of compressing
X the file.
X
X For each directory entry found, fiz prints where in the
X archive it is located, the directory path and filename(s)
X found in it, whether the directory entry appears to be cor-
X rupted (indicated by [*CRC Error*]), and the value of the
X pointer to the file data that is found in the directory
X entry. For each block of file data found in the archive,
X fiz prints where in the archive the block begins. In the
X case of an undamaged archive, the pointer to file data found
X in a directory entry will correspond to where fiz actually
X locates the data. Here is some sample output from fiz:
X
X ****************
X 2526: DIR [changes] ==> 95
X 2587: DATA
X ****************
X 3909: DIR [copyrite] ==> 1478
X 3970: DATA
X 4769: DATA
X ****************
X
X In such output, DIR indicates where fiz found a directory
X entry in the archive, and DATA indicates where fiz found
X file data in the archive. Filenames located by fiz are
X enclosed in square brackets, and the notation "==> 95"
X indicates that the directory entry found by fiz at position
X 2526 has a file data pointer to position 95. In actuality,
X fiz found file data at positions 2587, 3970, and 4769.
X Since fiz found only two directory entries, and each direc-
X tory entry corresponds to one file, one of the file data
X positions is an artifact.
X
X
X
X
X
Printed 2/7/88 Jan 31, 1988 1
X
X
X
X
X
X
FIZ(1) **IX Programmer's Manual FIZ(1)
X
X
X
X Once the locations of directory entries and file data are
X found, the @ modifier to zoo's archive list and extract com-
X mands can be used and the archive contents selectively
X listed or extracted, skipping the damaged portion. This is
X further described in the documentation for zoo(1).
X
X In the above case, commands to try giving to zoo might be
X x@2526,2587 (extract beginning at position 2526, and get
X file data from position 2587), x@3090,3970 (extract at 3090,
X get data from 3970) and x@3909,4769 (extract at 3909, get
X data from 4769). Once a correctly-matched directory
X entry/file data pair is found, zoo will in most cases syn-
X chronize with and correctly extract all files subsequently
X found in the archive. Trial and error should allow all
X undamaged files to be extracted. Also note that self-
X extracting archives created using sez (the Self-Extracting
X Zoo utility for MS-DOS), which are normally executed on an
X MS-DOS system for extraction, can be extracted on non-MSDOS
X systems in a similar way.
X
SEE ALSO
X zoo(1)
X
BUGS
X Random byte patterns can occasionally be incorrectly recog-
X nized as tag values. This occurs very rarely, however, and
X trial and error will usually permit all undamaged data to be
X extracted.
X
DIAGNOSTICS
X Fiz always exits with a status code of 0.
X
FUTURE DIRECTIONS
X Automation of data recovery from a damaged archive is poten-
X tially achievable. However, since damaged archives occur
X only rarely, fiz as it currently stands is unlikely to
X change much in the near future.
X
AUTHOR
X Rahul Dhesi
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
Printed 2/7/88 Jan 31, 1988 2
X
X
X
SHAR_EOF
chmod 0644 fiz.man ||
echo 'restore of fiz.man failed'
Wc_c="`wc -c < 'fiz.man'`"
test 4227 -eq "$Wc_c" ||
echo 'fiz.man: original size 4227, current size' "$Wc_c"
fi
true || echo 'restore of generic.c failed'
echo End of part 2, continue with part 3
exit 0