home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!rs
- From: rs@uunet.UU.NET (Rich Salz)
- Newsgroups: comp.sources.unix
- Subject: v11i015: File archive program, Part06/07
- Message-ID: <995@uunet.UU.NET>
- Date: 18 Aug 87 22:48:54 GMT
- Organization: UUNET Communications Services, Arlington, VA
- Lines: 1843
- Approved: rs@uunet.UU.NET
-
- Submitted-by: iuvax!bsu-cs!dhesi@seismo.CSS.GOV (Rahul Dhesi)
- Posting-number: Volume 11, Issue 15
- Archive-name: zoo/Part06
-
- #! /bin/sh
- #
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create:
- # zooadd.c
- # zooadd2.c
- # zoodel.c
- # zooext.c
- # zoofns.h
- export PATH; PATH=/bin:/usr/bin:$PATH
- if test -f 'zooadd.c'
- then
- echo shar: "will not over-write existing file 'zooadd.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'zooadd.c'
- X#ifndef LINT
- X/* @(#) zooadd.c 1.22 87/05/30 00:04:52 */
- Xstatic char sccsid[]="@(#) zooadd.c 1.22 87/05/30 00:04:52";
- X#endif /* LINT */
- X
- X/*
- XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
- X*/
- X#include "options.h"
- X/* Adds files specified in parameter-list to archive zoo_path. */
- X
- X#define LONGEST 20 /* assumed length of longest filename */
- X#include "zoomem.h" /* to define MAXADD */
- X#include "zoo.h"
- X#include <stdio.h>
- X#include "various.h"
- X#include "parse.h"
- X#include "debug.h"
- X
- X#include "portable.h"
- X/* for low-level I/O */
- X#ifdef NOFCNTL
- X#include <file.h>
- X#else
- X#include <fcntl.h>
- X#endif
- X
- X#ifdef FLAT
- X#include <types.h>
- X#include <stat.h>
- X#else
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#endif
- X
- X#ifdef IGNORECASE
- X#define COMPARE strcmpi
- X#else
- X#define COMPARE strcmp
- X#endif
- X
- X#include "zoofns.h"
- X#include "errors.i"
- Xextern int break_hit;
- Xextern int quiet;
- X
- X#ifdef LINT_ARGS
- Xvoid opts_add (char *, int *, int *, int *, int *, int *, int *,
- X int *, int *, int *, int *, int *);
- Xint ver_too_high (struct zoo_header *);
- Xget_comment (struct direntry *, FILE *, char *);
- Xvoid copyfields (struct direntry *, struct tiny_header *);
- Xvoid storefname (struct direntry *, char *, int);
- Xchar *choosefname (struct direntry *);
- X#else
- Xvoid opts_add();
- Xint ver_too_high ();
- Xget_comment ();
- Xvoid copyfields ();
- Xvoid storefname ();
- Xchar *choosefname ();
- X#endif
- X
- Xextern struct zoo_header zoo_header;
- X
- Xextern char file_leader[];
- Xextern unsigned int crccode;
- X
- Xvoid zooadd(zoo_path, argc, argv, option)
- Xchar *zoo_path; /* pathname of zoo archive to add to */
- Xint argc; /* how many filespecs supplied */
- Xchar **argv; /* array of pointers to filespecs */
- Xchar *option; /* option string */
- X{
- Xchar *whichname; /* which name to show user */
- Xchar *flist[MAXADD]; /* list of ptrs to input fnames */
- Xint fptr; /* will point to within flist */
- Xint zoo_han; /* handle for open archive */
- Xint this_han; /* handle of file to add */
- Xchar zoo_fname[LFNAMESIZE]; /* basename of archive itself */
- Xchar zoo_bak[LFNAMESIZE]; /* name of archive's backup */
- Xchar this_fname[LFNAMESIZE]; /* just filename of file to add */
- Xchar latest_name[LFNAMESIZE]; /* latest name in archive */
- Xlong last_old = 0L; /* last direntry in old chain */
- XFILE *zoo_file; /* stream for open archive */
- Xchar *this_path; /* pathname of file to add */
- X
- X#ifdef NOENUM
- X#define NEW_ZOO 1
- X#define OLD_ZOO 2
- Xint zoo_status;
- X#else
- Xenum {NEW_ZOO, OLD_ZOO} zoo_status; /* newly created or not */
- X#endif
- X
- Xlong this_dir_offset; /* pointers to within archive */
- Xlong save_position; /* pointer to within archive */
- Xlong prev_pos; /* posn of prev file of same name */
- Xstruct direntry direntry; /* directory entry */
- Xstruct direntry dir2entry; /* spare */
- Xstruct tiny_header tiny_header; /* for Z format archives */
- Xint status; /* error status */
- Xint success; /* successful addition of file? */
- Xint addcount = 0; /* number added */
- Xint update=0; /* add only files already in archive */
- Xint suppress=0; /* suppress compression */
- Xint new=0; /* add only files not in archive */
- Xint zootime = 0; /* just set archive time */
- Xint add_comment = 0; /* add comment */
- Xint pack = 0; /* pack after adding */
- Xint need_dir = 1; /* store directories too */
- Xint delcount = 0; /* count of deleted entries */
- Xint exit_status = 0; /* exit status to set */
- X
- Xunsigned int latest_date = 0; /* to set time on archive itself */
- Xunsigned int latest_time = 0; /* .. same */
- Xint move = 0; /* delete after adding to archive */
- Xint longest; /* length of longest pathname added */
- Xint firstfile = 1; /* first file being added? */
- Xint z_fmt = 0; /* look for Z format files? */
- Xint inargs = 0; /* read filenames from stdin? */
- X
- X/* on entry option points to first letter */
- X
- Xopts_add (option, &zootime, &quiet, &suppress, &move, &new, &pack,
- X &update, &add_comment, &z_fmt, &need_dir, &inargs);
- X
- X/* POSSIBLE RACE CONDITION BETWEEN TESTING EXISTENCE AND CREATING FILE */
- Xif (exists (zoo_path)) {
- X zoo_file = fopen (zoo_path, "r+b"); /* binary open, no create */
- X zoo_status = OLD_ZOO;
- X} else {
- X if (!zootime)
- X zoo_file = fopen (zoo_path, "w+b"); /* binary create/truncate */
- X else
- X zoo_file = NULL; /* don't create if just setting time */
- X zoo_status = NEW_ZOO;
- X}
- X
- Xif (zoo_file == NULL)
- X prterror ('f', could_not_open, zoo_path);
- Xzoo_han = fileno(zoo_file); /* get file handle */
- X
- Xbasename(zoo_path, zoo_fname); /* get basename of archive */
- Xrootname (zoo_path, zoo_bak); /* name without extension */
- Xstrcat (zoo_bak, BACKUP_EXT); /* name of backup of this archive */
- X
- X/*
- XFrom now on, both zoo_file and zoo_han can be used (one for stream I/O and
- Xthe other for low-level I/O). But before doing any low-level I/O, or
- Xbefore switching between reading and writing on the stream, a seek
- Xmust be done on the stream to flush buffered data and synchronize file
- Xpointers.
- X*/
- X
- X/* Now we prepare the archive for adding one or more files. If the archive
- Xhas just been created, we write the archive header */
- X
- Xaddfname ("",0L,0,0); /* initialize table of files already in archive */
- Xif (zoo_status == NEW_ZOO) { /* newly-created archive */
- X fwr_zooh (&zoo_header, zoo_file);
- X /* fwrite ((char *) &zoo_header, sizeof(zoo_header), 1, zoo_file); */
- X fseek (zoo_file, zoo_header.zoo_start, 0); /* seek to where data begins */
- X} else {
- X /* read header and rewrite with updated version numbers */
- X rwheader (&zoo_header, zoo_file);
- X /* initialize latest_name to null string */
- X /* NOTE: latest_name is not currently used for anything, but
- X may be used in the future for inserting files into the
- X archive in alphabetic order. */
- X *latest_name = '\0';
- X
- X /* Skip existing files but add them to a list. The variable last_old
- X gets the tail of the old chain of directory entries */
- X skip_files (zoo_file, &latest_date, &latest_time, &delcount,
- X latest_name, &last_old);
- X}
- X/* The file pointer is now positioned correctly to add a file to archive,
- Xunless the null directory entry is too short. This will be fixed below. */
- X
- X/* If we are just setting time, do it and run. */
- Xif (zootime) {
- X#ifdef NIXTIME
- X fclose (zoo_file);
- X setutime (zoo_path, latest_date, latest_time);
- X#else
- X settime (zoo_han, latest_date, latest_time);
- X fclose (zoo_file);
- X#endif
- X prterror ('m', "Archive time adjusted.\n");
- X exit (0);
- X}
- X
- X/* make list of files, excluding archive and its backup */
- Xlongest = LONGEST;
- Xif (!inargs) {
- X makelist(argc, argv, flist, MAXADD-2, zoo_fname, zoo_bak, ".", &longest);
- X /* ^^ ^^ ^^ exclude */
- X}
- X
- Xfptr = 0; /* ready to get filename (if makelist() was called) or to
- X begin adding filenames (if reading them from stdin) */
- X
- Xwhile (1) {
- X unsigned int this_date, this_time;
- X int INLIST; /* boolean */
- X int RECENT; /* boolean */
- X int danger; /* if update requested and disk copy is out of date */
- X if (inargs) {
- X again: /* loop back if filename was same as archive name or its backup */
- X this_path = getstdin(); /* pathname from stdin, in static area */
- X modpath (this_path);
- X /* if moving files, add to list for later deletion; if list overflows,
- X terminate addition loop and give warning message */
- X if (move) {
- X if (fptr >= MAXADD-2) {
- X prterror ('w', too_many_files, MAXADD-2);
- X this_path = NULL;
- X } else if (this_path != NULL) {
- X if (!COMPARE(zoo_fname,nameptr(this_path)) ||
- X !COMPARE(zoo_bak,nameptr(this_path)))
- X goto again;
- X else
- X flist[fptr++] = strdup (this_path);
- X }
- X }
- X } else {
- X this_path = flist[fptr++];
- X }
- X /* exit the addition loop when no more pathnames are left */
- X if (this_path == NULL) {
- X /* in case stdin was being read, make sure flist is NULL-terminated */
- X flist[fptr] = NULL;
- X break;
- X }
- X
- X basename (this_path, this_fname); /* get just filename for later */
- X
- X this_han = OPEN(this_path, F_READ);
- X if (this_han == -1) {
- X prterror ('e', could_not_open, this_path);
- X exit_status++;
- X continue;
- X }
- X
- X#ifndef PORTABLE
- X /* Test to see if this is a Z format file. We assume the file is Z format
- X if (a) tag is correct and (b) type is 1 and (c) embedded filename
- X is not longer than FNAMESIZE.
- X */
- X if (z_fmt) {
- X read (this_han, (char *) &tiny_header, sizeof(tiny_header));
- X if (tiny_header.tinytag == TINYTAG && tiny_header.type == 1 &&
- X strlen (tiny_header.fname) <= FNAMESIZE)
- X /* ok */ ;
- X else {
- X close (this_han);
- X prterror ('e', "File %s does not have Z format.\n", this_fname);
- X exit_status++;
- X continue;
- X }
- X }
- X#endif
- X
- X /* get file time; also fix name */
- X#ifndef PORTABLE
- X if (z_fmt) {
- X direntry.date = tiny_header.date;
- X direntry.time = tiny_header.time;
- X strcpy (direntry.fname, tiny_header.fname);
- X direntry.dirlen = direntry.namlen = 0;
- X } else {
- X#endif
- X
- X /* Get timstamp of file being added */
- X#ifdef GETUTIME
- X getutime (this_path, &direntry.date, &direntry.time);
- X#else
- X gettime (this_han, &direntry.date, &direntry.time);
- X#endif
- X
- X#ifdef FOLD
- X strlwr(this_fname);
- X#endif
- X dosname (this_fname, direntry.fname); /* MSDOS filename */
- X
- X /*
- X Store long filename into direntry.lfname iff it is different from MSDOS
- X filename. Also store directory name if need_dir is true. Moved out of
- X zooadd() so zooadd() doesn't get too big for optimization.
- X */
- X storefname (&direntry, this_path, need_dir);
- X
- X#ifndef PORTABLE
- X }
- X#endif
- X
- X#ifdef DEBUG
- Xprintf ("zooadd: direntry.lfname = [%s] direntry.dirname = [%s]\n",
- X direntry.lfname, direntry.dirname);
- X#endif
- X
- X /* if update option, then we add file if it is already in the archive
- X AND the archived file is older */
- X
- X /* The following logic was derived from a Karnaugh map so it may
- X be hard to understand. Essentially, if U=update requested,
- X N=new files requested, I=file is already in archive, and
- X R=file being archived is more recent than file already in
- X archive, then the boolean equation is:
- X
- X add = U' (N' + I') + U (IR + I'N)
- X */
- X
- X /* Get the filename to use for this addition. */
- X whichname = choosefname(&direntry);
- X
- X /* get position in archive of any old file of same name, ignoring
- X any directory prefix if need_dir is not true */
- X prev_pos = inlist (fullpath (&direntry), &this_date, &this_time, !need_dir);
- X
- X INLIST = prev_pos > 0; /* already in archive if positive value */
- X if (INLIST) {
- X int result;
- X result = cmpnum (direntry.date, direntry.time, this_date, this_time);
- X RECENT = result > 0;
- X danger = result < 0;
- X } else
- X danger = 0; /* And RECENT is undefined and should not be used */
- X
- X if (
- X !update && (!new || !INLIST) ||
- X update && (INLIST && RECENT || !INLIST && new)
- X )
- X ; /* then continue and add file */
- X else {
- X if (update && danger)
- X prterror ('w', "Archived copy of %s is newer.\n", whichname);
- X close (this_han);
- X continue; /* cycle back, skip this file */
- X }
- X
- X#ifdef CHEKDIR
- X /* Don't add if this is a directory */
- X if (isadir (this_han)) {
- X close (this_han);
- X continue;
- X }
- X#endif
- X
- X#ifdef CHEKUDIR
- X /* Don't add if this is a directory */
- X if (isuadir (this_path)) {
- X close (this_han);
- X continue;
- X }
- X#endif
- X
- X /* Create directory entry for new file (but don't add just yet) */
- X /* NOTE: we already got file date and time above for update option */
- X /* add tag, type, timezone, struc, system_id, and var_dir_len */
- X newdir (&direntry);
- X
- X /*
- X Write a null direntry entry. Thus, if an error occurs or the program
- X is interrupted, the end of the archive will still be meaningful.
- X Special check needed for first one written.
- X */
- X
- X direntry.next = direntry.offset = 0L; /* trailing null entry */
- X this_dir_offset = ftell (zoo_file);
- X if (!firstfile) {
- X writedir (&direntry, zoo_file);
- X } else {
- X /*
- X Before adding the first file to the archive, we must make sure that
- X the previous directory chain (if any) is properly terminated with a
- X null entry of the right size. If this is a new archive, we simply
- X write a new null entry of the right size. If this is an existing
- X archive, we must check the size of the previous trailing null entry.
- X If it is too small, we will back up to the most recent real directory
- X entry and change its .next field to point to end of file.
- X */
- X
- X if (zoo_status == NEW_ZOO) {
- X writedir (&direntry, zoo_file); /* write null dir entry */
- X } else {
- X#define DIRLEN(x) ((x.type<2) ? SIZ_DIR : (SIZ_DIRL+x.var_dir_len))
- X struct direntry tmpentry;
- X long tmppos;
- X int oldlen, newlen;
- X tmppos = ftell(zoo_file);
- X frd_dir (&tmpentry, zoo_file);
- X oldlen = DIRLEN(tmpentry); /* get length of direntry */
- X newlen = DIRLEN(direntry); /* ditto */
- X
- X if (newlen > oldlen) { /* trouble */
- X fseek (zoo_file, last_old, 0); /* back to previous entry */
- X frd_dir (&tmpentry, zoo_file);
- X fseek (zoo_file, 0L, 2); /* get EOF position */
- X tmpentry.next = ftell(zoo_file); /* point to EOF */
- X fseek (zoo_file, last_old, 0); /* back to previous entry */
- X writedir (&tmpentry, zoo_file); /* update it */
- X fseek (zoo_file, 0L, 2); /* to EOF ... */
- X this_dir_offset = ftell (zoo_file);
- X writedir (&direntry, zoo_file); /* ...write null dir entry */
- X } else
- X fseek (zoo_file, tmppos, 0); /* long enough -- let it be */
- X } /* if (zoo_status == NEW_ZOO) ... */
- X } /* if (!firstfile) ... */
- X
- X /* Now `this_dir_offset' is where the next directory entry will go */
- X
- X /* first file added goes at EOF to avoid overwriting comments */
- X if (firstfile) {
- X fseek (zoo_file, 0L, 2); /* EOF */
- X direntry.offset = ftell (zoo_file) + SIZ_FLDR;
- X } else {
- X direntry.offset = this_dir_offset + SIZ_DIRL +
- X direntry.var_dir_len + SIZ_FLDR;
- X }
- X
- X direntry.major_ver = MAJOR_EXT_VER; /* minimum version number needed */
- X direntry.minor_ver = MINOR_EXT_VER; /* .. to extract */
- X direntry.deleted = 0; /* not deleted, naturally */
- X direntry.comment = 0L; /* no comment (yet) */
- X direntry.cmt_size = 0; /* .. so no size either */
- X
- X save_position = direntry.offset; /* save position in case of error */
- X
- X fseek (zoo_file, direntry.offset - SIZ_FLDR, 0);
- X fwrite (file_leader, SIZ_FLDR, 1, zoo_file);
- X fseek (zoo_file, ftell (zoo_file), 0); /* for low-level I/O */
- X
- X#ifdef PORTABLE
- X prterror ('m', "%-*s -- ", longest, this_path);
- X#else
- X if (z_fmt)
- X prterror ('m', "%-12s <== %-*s -- ",
- X direntry.fname, longest, this_path);
- X else
- X prterror ('m', "%-*s -- ", longest, this_path);
- X
- X#ifdef COMMENT
- X prterror ('m', z_fmt ? "%-12s <== %-12s -- " : "%-12s -- ",
- X direntry.fname, this_fname);
- X prterror ('m', z_fmt ? "%-12s <== %-12s -- " : "%-12s -- ",
- X direntry.fname, this_fname);
- X#endif /* COMMENT */
- X#endif /* PORTABLE */
- X
- X crccode = 0;
- X if (z_fmt) {
- X direntry.packing_method = tiny_header.packing_method;
- X lseek (this_han, (long) (sizeof(tiny_header) + tiny_header.cmt_size), 0);
- X status = getfile (this_han, zoo_han, tiny_header.size_now, 1);
- X } else if (suppress) { /* suppress compression */
- X direntry.packing_method = 0; /* no compression */
- X status = getfile (this_han, zoo_han, -1L, 1);
- X /* status = copyfile (this_han, zoo_han); */
- X } else {
- X direntry.packing_method = 1; /* compressed */
- X status = lzc(this_han, zoo_han); /* add with compression */
- X }
- X if (status != 0) { /* if I */
- X ++exit_status; /* remember error */
- X if (status == 1)
- X prterror ('F', no_memory);
- X else if (status == 2)
- X prterror ('F', disk_full);
- X else if (status == 3)
- X prterror ('F', "Read error.\n");
- X else
- X prterror ('F', internal_error);
- X success = 0;
- X } else {
- X direntry.next = ftell(zoo_file);
- X direntry.size_now = direntry.next - direntry.offset;
- X
- X /* find and store original size of file just compressed */
- X direntry.org_size = tell (this_han); /* should be EOF already */
- X
- X /* If the compressed one is bigger, just copy */
- X
- X if (direntry.size_now >= direntry.org_size && /* if II */
- X direntry.packing_method > 0) {
- X lseek (zoo_han, save_position, 0); /* ..restore file pointer */
- X trunc (zoo_han); /* ..truncate file */
- X direntry.packing_method = 0; /* ..and just copy */
- X lseek (this_han, 0L, 0); /* (but rewind first!) */
- X crccode = 0; /* re-start crc from 0 */
- X status = getfile (this_han, zoo_han, -1L, 1);
- X /* status = copyfile (this_han, zoo_han); */
- X if (status != 0) { /* if III */
- X success = 0;
- X printf (disk_full);
- X exit_status++;
- X } else {
- X success = 1;
- X direntry.next = ftell(zoo_file);
- X direntry.size_now = direntry.next - direntry.offset;
- X } /* end if III */
- X } else {
- X success = 1;
- X } /* end if II */
- X
- X } /* end if I */
- X
- X if (success) { /* file successfully added */
- X addcount++; /* how many added */
- X direntry.file_crc = crccode;
- X
- X /* remember most recent date and time */
- X if (cmpnum (direntry.date,direntry.time,latest_date,latest_time) > 0) {
- X latest_date = direntry.date;
- X latest_time = direntry.time;
- X }
- X
- X /* mark any previous version of this file in archive as deleted */
- X dir2entry.comment = 0L; /* for later use assigning to direntry */
- X dir2entry.cmt_size = 0;
- X
- X if (!z_fmt)
- X prterror ('M', " (%2d%%) ", cfactor (direntry.org_size, direntry.size_now));
- X
- X if (prev_pos > 0) {
- X long save_pos = ftell(zoo_file); /*DEBUG*/
- X ++delcount; /* remember to pack */
- X prterror ('M', "replaced\n");
- X fseek (zoo_file, prev_pos, 0);
- X readdir (&dir2entry, zoo_file, 1);
- X dir2entry.deleted = 1; /* mark as deleted */
- X fseek (zoo_file, prev_pos, 0);
- X writedir (&dir2entry, zoo_file);
- X fseek (zoo_file, save_pos, 0); /*DEBUG*/
- X } else prterror ('M', "added\n");
- X
- X /* Preserve any old comment if we replaced the file */
- X direntry.comment = dir2entry.comment;
- X direntry.cmt_size = dir2entry.cmt_size;
- X
- X#ifndef PORTABLE
- X /* Copy comment if any from Z format file */
- X if (z_fmt && tiny_header.cmt_size != 0) {
- X lseek (this_han, (long) sizeof(tiny_header), 0); /* get to comment */
- X#ifdef COMMENT
- X fseek (zoo_file, 0L, 2); /* append comment to end */
- X#endif
- X direntry.comment = ftell (zoo_file);
- X direntry.cmt_size = tiny_header.cmt_size;
- X /* 4th param is 0 for no CRC */
- X getfile (this_han, zoo_han, (long) tiny_header.cmt_size, 0);
- X direntry.next = ftell(zoo_file);
- X }
- X#endif
- X
- X /* if user requested comments, any previous comment in a Z format
- X file may now be manually overwritten */
- X if (add_comment && !feof (stdin)) {
- X show_comment (&direntry, zoo_file, 1, whichname);
- X get_comment (&direntry, zoo_file, this_path);
- X direntry.next = ftell(zoo_file); /* update .next ptr */
- X } /* end if */
- X
- X#ifndef PORTABLE
- X /* if adding Z format archive, copy relevant fields from its header */
- X if (z_fmt) { /* moved out to shorten code & allow optimizer to work */
- X copyfields (&direntry, &tiny_header);
- X }
- X#endif
- X
- X debug((printf ("zooadd: our new .next = [%lx].\n", direntry.next)))
- X
- X {
- X long savepos = ftell(zoo_file); /* save position */
- X fseek (zoo_file, this_dir_offset, 0);
- X writedir (&direntry, zoo_file);
- X fseek (zoo_file, savepos, 0); /* restore position */
- X }
- X
- X } else { /* file was not properly added */
- X lseek (zoo_han, save_position, 0); /* ..restore file pointer */
- X trunc (zoo_han); /* ..truncate file */
- X } /* end if */
- X close (this_han);
- Xif (!success)
- X break;
- Xfirstfile = 0;
- X} /* end for */
- X
- Xsave_position = ftell (zoo_file);
- X
- X/* Write a null direntry entry */
- Xfseek (zoo_file, save_position, 0);
- Xwritenull (zoo_han, MAXDIRSIZE);
- Xtrunc (zoo_han); /* truncate */
- X
- X#ifdef NIXTIME
- Xfclose (zoo_file);
- Xsetutime (zoo_path, latest_date, latest_time);
- X#else
- Xsettime (zoo_han, latest_date, latest_time);
- Xfclose (zoo_file);
- X#endif
- X
- Xif (!addcount) { /* no files added */
- X prterror ('m', "No files added.\n");
- X if (zoo_status == NEW_ZOO)
- X unlink (zoo_path);
- X} else {
- X if (delcount && pack) { /* pack if user asked and found deleted entries */
- X prterror ('M', "-----\nPacking...");
- X zoopack (zoo_path, "PP");
- X prterror ('M', "done\n");
- X }
- X
- X /* If files to move & we added some and no error so far, delete originals */
- X if (move && !exit_status)
- X if (kill_files (flist, longest) != 0)
- X exit_status++;
- X}
- X
- Xif (exit_status)
- X exit (1);
- X} /* end zoo_add */
- SHAR_EOF
- fi
- if test -f 'zooadd2.c'
- then
- echo shar: "will not over-write existing file 'zooadd2.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'zooadd2.c'
- X#ifndef LINT
- X/* @(#) zooadd2.c 1.11 87/05/29 12:55:51 */
- Xstatic char sccsid[]="@(#) zooadd2.c 1.11 87/05/29 12:55:51";
- X#endif /* LINT */
- X
- X/*
- XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
- X*/
- X#include "options.h"
- X#include "zoo.h"
- X#include <stdio.h>
- X#include "various.h"
- X#include "zoofns.h"
- X#include "errors.i"
- X#include "assert.h"
- X#include "debug.h"
- X#include "parse.h"
- X
- X/*
- XMiscellaneous routines to support zooadd().
- X*/
- X
- X/****************
- XThis function is called with zoo_file positioned to the first
- Xdirectory entry in an archive. It skips past all existing files,
- Xcounts the number of deleted files, saves the latest data and time
- Xencountered, and adds all filenames encountered to a global list. The
- Xlong filename is added if available, else the MSDOS filename is
- Xadded.
- X*/
- X
- Xvoid skip_files (zoo_file, latest_date, latest_time, delcount,
- X latest_name, latest_pos)
- XFILE *zoo_file;
- Xunsigned int *latest_date, *latest_time;
- Xint *delcount;
- Xchar latest_name[];
- Xlong *latest_pos;
- X{
- X char *whichname; /* will point to name to use */
- X long save_offset, next_ptr;
- X struct direntry direntry;
- X struct direntry *drp = &direntry;
- X
- X *latest_pos = 0L;
- X do {
- X /* read a directory entry */
- X save_offset = ftell (zoo_file); /* save pos'n of this dir entry */
- X readdir (&direntry, zoo_file, 1); /* read directory entry */
- X if (drp->next == 0L) { /* END OF CHAIN */
- X fseek (zoo_file, save_offset, 0); /* back up */
- X break; /* EXIT on end of chain */
- X } else
- X *latest_pos = save_offset;
- X /* remember most recent date and time, for files not marked deleted */
- X if (!drp->deleted)
- X if (drp->date > *latest_date ||
- X (drp->date == *latest_date && drp->time > *latest_time)) {
- X *latest_date = drp->date;
- X *latest_time = drp->time;
- X }
- X next_ptr = drp->next; /* ptr to next dir entry */
- X if (drp->deleted)
- X ++(*delcount); /* count deleted entries */
- X /* add name of file and position of direntry into global list */
- X /* but only if the entry is not deleted */
- X if (!drp->deleted) {
- X#ifdef FOLD
- X /* IS THIS REALLY NEEDED? IF SO, WHAT ABOUT drp->lfname? */
- X strlwr(drp->fname);
- X#endif
- X /* add full pathname to global list */
- X strcpy (latest_name, fullpath (drp));
- X addfname (latest_name, save_offset, drp->date, drp->time);
- X }
- X fseek (zoo_file, next_ptr, 0); /* ..seek to next dir entry */
- X } while (next_ptr != 0L); /* loop terminates on null ptr */
- X}
- X
- X/*******************/
- X/* kill_files() deletes all files in the supplied list of pointers to
- Xfilenames */
- X
- Xint kill_files (flist, pathlength)
- Xchar *flist[]; /* list of ptrs to input fnames */
- Xint pathlength; /* length of longest pathname */
- X{
- X int status = 0;
- X int fptr;
- X prterror ('M', "-----\nErasing added files...\n");
- X for (fptr = 0; flist[fptr] != NULL; fptr++) {
- X prterror ('m', "%-*s -- ", pathlength, flist[fptr]);
- X if (unlink (flist[fptr]) == 0) {
- X prterror ('M', "erased\n");
- X } else {
- X prterror ('w', "Could not erase %s.\n", flist[fptr]);
- X status = 1;
- X }
- X }
- X return (status);
- X}
- X
- X#ifndef PORTABLE
- X/*******************/
- Xvoid copyfields (drp, thp)
- Xstruct direntry *drp;
- Xstruct tiny_header *thp;
- X{
- X drp->org_size = thp->org_size;
- X drp->file_crc = thp->file_crc;
- X drp->size_now = thp->size_now;
- X drp->major_ver = thp->major_ver;
- X drp->minor_ver = thp->minor_ver;
- X}
- X#endif
- X
- X/*******************/
- X/* processes option switches for zooadd() */
- Xvoid opts_add (option, zootime, quiet, suppress, move, new, pack,
- X update, add_comment, z_fmt, need_dir, inargs)
- Xchar *option;
- Xint *zootime, *quiet, *suppress, *move, *new, *pack,
- X *update, *add_comment, *z_fmt, *need_dir, *inargs;
- X
- X{
- X if (*option == 'T') {
- X (*zootime)++;
- X option++;
- X while (*option) {
- X switch (*option) {
- X case 'q': (*quiet)++; break;
- X default:
- X prterror ('f', inv_option, *option);
- X }
- X option++;
- X }
- X }
- X
- X while (*option) {
- X switch (*option) {
- X case 'a': break;
- X case 'f': (*suppress)++; break; /* suppress compression */
- X case 'M': (*move)++; break; /* delete files after adding them */
- X case 'n': (*new)++; break; /* add only files not in archive */
- X case 'P': (*pack)++; break; /* pack after adding */
- X case 'u': (*update)++; break; /* add only files already in archive */
- X case 'q': (*quiet)++; break; /* be quiet */
- X case 'c': (*add_comment)++; break; /* add comment */
- X case ':': *need_dir = 0; break; /* don't store directories */
- X case 'I': (*inargs)++; break; /* get filenames from stdin */
- X#ifndef PORTABLE
- X case 'z': (*z_fmt)++; break; /* look for Z format files */
- X#endif
- X default:
- X prterror ('f', inv_option, *option);
- X }
- X option++;
- X } /* end while */
- X}
- X
- X
- X/*
- XStores long filename into direntry.lfname iff it is different from MSDOS
- Xfilename. Also stores directory name if need_dir is true. Moved out of
- Xzooadd() so zooadd() doesn't get too big for optimization.
- X*/
- Xvoid storefname (direntry, this_path, need_dir)
- Xstruct direntry *direntry;
- Xchar *this_path;
- Xint need_dir;
- X{
- X struct path_st path_st;
- X parse (&path_st, this_path);
- X direntry->lfname[0] = '\0';
- X direntry->namlen = 0;
- X if (strcmp(path_st.lfname,direntry->fname) != 0) {
- X strcpy (direntry->lfname, path_st.lfname); /* full filename */
- X direntry->namlen = strlen(direntry->lfname) + 1;
- X }
- X if (need_dir) {
- X strcpy (direntry->dirname, path_st.dir); /* directory name */
- X direntry->dirlen = strlen(direntry->dirname) + 1;
- X if (direntry->dirlen == 1) /* don't store trailing null alone */
- X direntry->dirlen = 0;
- X } else {
- X direntry->dirname[0] = '\0';
- X direntry->dirlen = 0;
- X }
- X}
- X
- X/*
- XFunction getsdtin() gets a pathname from standard input, cleans
- Xit if necessary by removing any following blanks/tabs and other
- Xjunk, and returns it in a static area that is overwritten by each
- Xcall.
- X*/
- Xchar *getstdin()
- X{
- X char *chptr; /* temp pointer */
- X static char tempname[PATHSIZE];
- X do {
- X if (fgets (tempname, PATHSIZE, stdin) == NULL)
- X return (NULL);
- X /* remove trailing blank, tab, newline */
- X for (chptr = tempname; *chptr != '\0'; chptr++) {
- X if (
- X /* PURIFY means remove trailing blanks/tabs and all subsequent chars */
- X#ifdef PURIFY
- X *chptr == '\t' || *chptr == ' ' ||
- X#endif
- X *chptr == '\n' /* always remove trailing \n */
- X )
- X {
- X
- X *chptr = '\0';
- X break;
- X }
- X }
- X } while (*tempname == '\0'); /* get a nonempty line */
- X#ifdef FOLD
- X strlwr (tempname);
- X#endif
- X return (tempname);
- X}
- X
- X/*
- XFunction newdir() adds some default information to a directory entry.
- XThis will be a new directory entry added to an archive.
- X*/
- Xvoid newdir (direntry)
- Xregister struct direntry *direntry;
- X{
- X direntry->zoo_tag = ZOO_TAG;
- X direntry->type = 2; /* type is now 2 */
- X direntry->tz = 127; /* timezone unknown */
- X direntry->struc = 0; /* unstructured file */
- X direntry->system_id = 0; /* identify UNIX filesystem */
- X direntry->var_dir_len =
- X (direntry->dirlen > 0 || direntry->namlen > 0 ? 2 : 0) +
- X direntry->dirlen + direntry->namlen;
- X}
- SHAR_EOF
- fi
- if test -f 'zoodel.c'
- then
- echo shar: "will not over-write existing file 'zoodel.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'zoodel.c'
- X#ifndef LINT
- Xstatic char sccsid[]="@(#) zoodel.c 1.8 87/05/29 12:56:02";
- X#endif /* LINT */
- X
- X/*
- XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
- X*/
- X#include "options.h"
- X/* Deletes or undeletes entries from an archive. choice=1 requests
- X deletion and choice=0 requests undeletion. */
- X#include "portable.h"
- X#include <stdio.h>
- X#include "various.h" /* may not be needed */
- X#include "zoo.h"
- X#include "zoofns.h"
- X#include "errors.i"
- X
- X#ifndef NOSIGNAL
- X#include <signal.h>
- X#endif
- X
- Xextern int quiet;
- X
- Xvoid zoodel (zoo_path, option, choice)
- Xchar *zoo_path;
- Xchar *option;
- Xint choice;
- X{
- X#ifndef NOSIGNAL
- X int (*oldsignal)(); /* to save previous SIGINT handler */
- X#endif
- X int delcount = 0; /* how many entries we [un]deleted */
- X char matchname[PATHSIZE]; /* will hold full pathname */
- X register FILE *zoo_file;
- X struct zoo_header zoo_header;
- X struct direntry direntry;
- X unsigned int latest_date = 0; /* so we can set time of archive later */
- X unsigned int latest_time = 0;
- X int pack = 0; /* pack after deletion? */
- X int file_deleted = 0; /* any files deleted? */
- X int one = 0; /* del/undel one file only */
- X int done; /* loop control */
- Xwhile (*(++option)) {
- X switch (*option) {
- X case 'P': pack++; break; /* pack after adding */
- X case 'q': quiet++; break; /* be quiet */
- X case '1': one++; break; /* del or undel only one file */
- X default:
- X prterror ('f', inv_option, *option);
- X }
- X} /* end while */
- X
- X /* Open archive for read/write/binary access. It must already exist */
- X if ((zoo_file = fopen (zoo_path, FRWSTR)) == NULL) {
- X prterror ('f', could_not_open, zoo_path);
- X }
- X
- X /* read archive header */
- X frd_zooh (&zoo_header, zoo_file);
- X /* fread ((char *) &zoo_header, sizeof(zoo_header), 1, zoo_file); */
- X if ((zoo_header.zoo_start + zoo_header.zoo_minus) != 0L)
- X prterror ('f', failed_consistency);
- X fseek (zoo_file, zoo_header.zoo_start, 0); /* seek to where data begins */
- X
- X done = 0; /* loop not done yet */
- X /* Go into loop deleting requested entries */
- X while (1) {
- X long this_dir_offset;
- X this_dir_offset = ftell (zoo_file); /* save pos'n of this dir entry */
- X frd_dir (&direntry, zoo_file);
- X /* fread ((char *) &direntry, sizeof (direntry), 1, zoo_file); */
- X if (direntry.zoo_tag != ZOO_TAG) {
- X prterror ('f', bad_directory);
- X }
- X if (direntry.next == 0L) { /* END OF CHAIN */
- X break; /* EXIT on end of chain */
- X }
- X
- X /* Now [un]delete this entry if it isn't already [un]deleted and
- X if filename matches. WARNING: convention of choice=1 for
- X deleted entry must be same as in direntry definition in zoo.h */
- X
- X /* Test for "done" so if "one" option requested, [un]del only 1 file */
- X /* But we go through the whole archive to adjust archive time */
- X
- X strcpy (matchname, fullpath (&direntry)); /* get full pathname */
- X
- X if (!done && direntry.deleted != choice &&
- X needed(matchname)) {
- X prterror ('m', "%-14s -- ", matchname);
- X delcount++;
- X direntry.deleted = choice;
- X if (choice)
- X file_deleted++; /* remember if any files actually deleted */
- X
- X fseek (zoo_file, this_dir_offset, 0);
- X
- X#ifndef NOSIGNAL
- X oldsignal = signal (SIGINT, SIG_IGN); /* disable ^C for write */
- X#endif
- X if (fwr_dir (&direntry, zoo_file) == -1)
- X /* if (fwrite ((char *) &direntry, sizeof(direntry), 1, zoo_file) < 1) */
- X prterror ('f', "Could not write to archive\n");
- X#ifndef NOSIGNAL
- X signal (SIGINT, oldsignal);
- X#endif
- X prterror ('M', choice ? "deleted\n" : "undeleted\n");
- X if (one)
- X done = 1; /* if 1 option, done after 1 file */
- X }
- X
- X /* remember most recent date and time if entry is not deleted */
- X if (!direntry.deleted)
- X if (direntry.date > latest_date ||
- X (direntry.date == latest_date && direntry.time > latest_time)) {
- X latest_date = direntry.date;
- X latest_time = direntry.time;
- X }
- X fseek (zoo_file, direntry.next, 0); /* ..seek to next dir entry */
- X } /* endwhile */
- X
- X if (!delcount)
- X printf ("Zoo: No files matched.\n");
- X else {
- X#ifdef NIXTIME
- X fclose (zoo_file);
- X setutime (zoo_path, latest_date, latest_time);
- X#else
- X fflush (zoo_file); /* superstition: might help time stamp */
- X settime (fileno(zoo_file), latest_date, latest_time);
- X#endif
- X }
- X
- X#ifndef NIXTIME
- Xfclose (zoo_file);
- X#endif
- X
- Xif (file_deleted && pack) { /* pack if files were deleted and user asked */
- X prterror ('M', "-----\nPacking...");
- X zoopack (zoo_path, "PP");
- X prterror ('M', "done\n");
- X}
- X
- X}
- SHAR_EOF
- fi
- if test -f 'zooext.c'
- then
- echo shar: "will not over-write existing file 'zooext.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'zooext.c'
- X#ifndef LINT
- Xstatic char sccsid[]="@(#) zooext.c 1.8 87/05/29 12:56:07";
- X#endif /* LINT */
- X
- X/*
- XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
- X*/
- X#include "options.h"
- X/* Extract file from archive. Extracts files specified in parameter-list
- X from archive zoo_path. If none specified, extracts all files from
- X archive. */
- X
- X#include "zoo.h"
- X#include "parse.h" /* defines struct for parse() */
- X
- X#include "portable.h" /* portable I/O definitions */
- X#include "machine.h" /* machine-specific declarations */
- X
- X#include <stdio.h>
- X#include "various.h"
- X
- X#ifndef NOSIGNAL
- X#include <signal.h>
- X#endif
- X
- X#include "zoofns.h"
- X
- X/* for low-level I/O */
- X#ifdef FLAT
- X#include <types.h>
- X#include <stat.h>
- X#else
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#endif
- X
- X#ifdef NOFCNTL
- X#include <file.h>
- X#else
- X#include <fcntl.h>
- X#endif
- X
- Xextern int quiet;
- X
- X#include "errors.i"
- X
- X/* Following two are used by ctrl_c() also, hence declared here */
- Xchar extfname[LFNAMESIZE]; /* filename of extracted file */
- Xstatic int this_han; /* handle of file to extract */
- X
- Xstatic int tofile; /* true if not pipe or null device */
- Xextern unsigned int crccode;
- Xextern char *out_buf_adr; /* address of output buffer */
- X
- Xvoid zooext(zoo_path, option)
- Xchar *zoo_path, *option;
- X{
- Xchar *whichname; /* which name to extract */
- Xchar matchname[PATHSIZE]; /* for pattern matching only */
- X#ifndef NOSIGNAL
- Xint (*oldsignal)(); /* to save previous SIGINT handler */
- X#endif
- Xint zoo_han; /* handle for open archive */
- Xlong next_ptr; /* pointer to within archive */
- Xstruct zoo_header zoo_header; /* header for archive */
- Xint status; /* error status */
- Xchar ans[3]; /* answer to "Overwrite?" */
- Xint error_message = 1; /* Whether to give error message */
- Xunsigned long disk_space; /* disk space left */
- Xint matched = 0; /* Any files matched? */
- Xint overwrite = 0; /* force overwrite of files? */
- Xint needdel = 0; /* extract deleted files too */
- Xint usepath = 0; /* use path for extraction */
- Xint todot = 0; /* extract relative to . */
- Xint zootime = 0; /* just set archive time */
- Xint badcrc_count = 0; /* how many files with bad CRC */
- Xint bad_header = 0; /* to avoid spurious messages later */
- Xlong fiz_ofs = 0; /* offset where to start */
- Xint pipe = 0; /* are we piping output? */
- Xint fast_ext = 0; /* fast extract as *.?Z? */
- Xint null_device = 0; /* are we sending to null device? */
- Xint alloc_size; /* disk allocation unit size */
- Xstruct direntry direntry; /* directory entry */
- X
- X#ifdef OOZ
- X static char extract_ver[] = "A higher version of OOZ is needed to extract ";
- X static char no_space[] = "Insufficient disk space to extract ";
- X#else
- X static char extract_ver[] = "Zoo %d.%d is needed to extract %s.\n";
- X static char no_space[] = "Insufficient disk space to extract %s.\n";
- X#endif
- X
- X#ifndef OOZ
- Xwhile (*option) {
- X switch (*option) {
- X#ifndef PORTABLE
- X case 'z': fast_ext++; break;
- X#endif
- X case 'x':
- X case 'e': break;
- X case 'N': null_device++; break;
- X case 'O': overwrite += 2; break;
- X case 'o': overwrite++; break;
- X case 'p': pipe++; break;
- X case 'd': needdel++; break;
- X case 'q': quiet++; break;
- X case '/': usepath++; break;
- X case '.': todot++; break;
- X case '@':
- X ++option;
- X fiz_ofs = calc_ofs(option);
- X goto no_more;
- X default:
- X prterror ('w', option_ignored, *option);
- X break;
- X }
- X option++;
- X}
- X
- Xno_more: /* come from exit in while loop above */
- X
- X
- Xif (overwrite == 1) /* must be at least 2 to begin with */
- X overwrite--;
- X
- Xif (null_device && pipe) {
- X prterror ('w', option_ignored, 'p');
- X pipe = 0;
- X}
- X
- Xif (overwrite && pipe)
- X prterror ('w', option_ignored, 'O');
- X
- Xif (null_device && fast_ext) {
- X prterror ('w', option_ignored, 'N');
- X null_device = 0;
- X}
- X
- Xtofile = !pipe && !null_device; /* sending to actual file */
- X#else
- Xtofile = 1;
- X#endif
- X
- X
- Xzoo_han = OPEN(zoo_path, F_READ);
- X
- Xif (zoo_han == -1)
- X#ifdef OOZ
- X prterror ('f', could_not_open, zoo_path, ".\n");
- X#else
- X prterror ('f', could_not_open, zoo_path);
- X#endif
- X
- Xif (fiz_ofs != 0L) { /* if offset specified, start there */
- X prterror('m', "Starting at %ld\n", fiz_ofs);
- X lseek (zoo_han, fiz_ofs, 0);
- X} else {
- X /* read header */
- X rd_zooh (&zoo_header, zoo_han);
- X /* read (zoo_han, (char *) &zoo_header, sizeof(zoo_header)); */
- X if ((zoo_header.zoo_start + zoo_header.zoo_minus) != 0L) {
- X prterror ('w', failed_consistency, (char *) NULL, (char *) NULL);
- X bad_header++;
- X }
- X lseek (zoo_han, zoo_header.zoo_start, 0); /* seek to where data begins */
- X}
- X
- X#ifndef PORTABLE
- Xdisk_space = space (0, &alloc_size); /* remember disk space left */
- X#else
- Xalloc_size = 0;
- Xdisk_space = MAXLONG; /* infinite disk space */
- X#endif
- X
- X#ifndef OOZ
- X/* Ooz does no piping */
- X/* if piping output we open the output device just once */
- X/* NOTE: the DOS device "NUL" was causing the system to hang up.
- X therefore we create our own. All functions called must recognize
- X -2 as a null output handle and ignore all output to that */
- Xif (null_device) { /* -2 means null device */
- X this_han = -2;
- X} else if (pipe)
- X this_han = (int) fileno(stdout); /* standard output */
- X#endif
- X
- Xwhile (1) {
- X rd_dir (&direntry, zoo_han);
- X /* read (zoo_han, (char *) &direntry, sizeof(direntry)); */
- X if (direntry.zoo_tag != ZOO_TAG) {
- X long currpos, zoolength;
- X
- X#ifdef OOZ
- X prterror ('f', invalid_header, (char *) NULL, (char *) NULL);
- X#else
- X prterror ('F', invalid_header);
- X
- X /* Note: if header was bad, there's no point trying to find
- X how many more bytes aren't processed -- our seek position is
- X likely very wrong */
- X
- X if (!bad_header)
- X if ((currpos = tell (zoo_han)) != -1L)
- X if (lseek (zoo_han, 0L, 2) != -1)
- X if ((zoolength = tell (zoo_han)) != -1L)
- X printf (cant_process, zoolength - currpos);
- X exit (1);
- X#endif
- X }
- X if (direntry.next == 0L) { /* END OF CHAIN */
- X break; /* EXIT on end of chain */
- X }
- X next_ptr = direntry.next; /* ptr to next dir entry */
- X
- X whichname = choosefname(&direntry); /* which filename */
- X fixfname(whichname); /* fix syntax */
- X strcpy (matchname, fullpath (&direntry)); /* get full pathname */
- X
- X if (todot && *direntry.dirname == *PATH_CH) {
- X char tmpstr[PATHSIZE];
- X strcpy(tmpstr, direntry.dirname);
- X strcpy(direntry.dirname,CUR_DIR);
- X strcat(direntry.dirname, tmpstr);
- X }
- X
- X /* matchname now holds the full pathname for pattern matching */
- X
- X if ( ( (needdel && direntry.deleted) ||
- X (needdel < 2 && !direntry.deleted)
- X ) && needed(matchname)) {
- X matched++; /* update count of files extracted */
- X
- X if (direntry.major_ver > MAJOR_EXT_VER ||
- X (direntry.major_ver == MAJOR_EXT_VER &&
- X direntry.minor_ver > MINOR_EXT_VER)) {
- X
- X#ifdef OOZ
- X prterror ('e', extract_ver, whichname, ".\n");
- X#else
- X prterror ('e', extract_ver, direntry.major_ver,
- X direntry.minor_ver, whichname);
- X#endif
- X goto loop_again;
- X }
- X
- X /*
- X If extracting to null device, or if user requested extraction
- X of entire path, include any directory name in filename.
- X If extraction to current directory requested, and if extfname
- X begins with path separator, fix it */
- X
- X strcpy (extfname, whichname);
- X if ((usepath || null_device) && direntry.dirlen > 0) {
- X combine(extfname, direntry.dirname, whichname);
- X if (usepath > 1 && !null_device)
- X makepath(direntry.dirname); /* make dir prefix */
- X }
- X
- X if (tofile) {
- X int present = 0;
- X
- X#ifndef OOZ
- X#ifndef PORTABLE
- X /*
- X if Z format (fast) extraction, extension is created as
- X follows: for no current extension, new extension is "zzz";
- X for current extension "a", new extension is "azz"; for
- X current extension "ab", new extension is "azb"; and for
- X current extension "abc", new extension is "azc".
- X */
- X
- X if (fast_ext) {
- X int length;
- X struct path_st path_st;
- X parse (&path_st, extfname); /* split filename */
- X strcpy (extfname, path_st.fname); /* just root filename */
- X length = strlen (path_st.ext);
- X strcat (extfname, ".");
- X if (length == 0)
- X strcat (extfname, "zzz"); /* no ext -> .zzz */
- X else if (length == 1) {
- X strcat (extfname, path_st.ext);
- X strcat (extfname, "zz"); /* *.? -> *.?zz */
- X } else { /* length is 2 or 3 */
- X if (length == 2) /* allow .aa, .ab, etc. */
- X path_st.ext[2] = path_st.ext[1];
- X path_st.ext[1] = 'z';
- X strcat (extfname, path_st.ext); /* *.?? -> *.?z? */
- X }
- X }
- X#endif /* ifndef PORTABLE */
- X#endif /* ifndef OOZ */
- X
- X
- X if (overwrite) {
- X this_han = CREATE(extfname, F_RDWR);
- X } else {
- X if (exists (extfname)) {
- X present = 1;
- X this_han = -1;
- X } else
- X this_han = CREATE(extfname, F_RDWR);
- X }
- X if (this_han == -1) {
- X if (present == 1) { /* if file exists already */
- X do {
- X
- X#ifdef OOZ
- X putstr ("Overwrite "); putstr (extfname);
- X putstr (" (Yes/No/All)? ");
- X#else
- X printf ("Overwrite %s (Yes/No/All)? ", extfname);
- X#endif
- X fflush (stdin);
- X fgets (ans, 3, stdin);
- X strlwr (ans);
- X } while (*ans != 'y' && *ans != 'n' && *ans != 'a');
- X
- X /* NOTE: We use CREATE even if we are trying to overwrite
- X the file, because a data path utility (Search or Dpath)
- X could have fooled us before. */
- X if (*ans == 'a')
- X overwrite++;
- X if (*ans == 'y' || *ans == 'a') {
- X this_han = CREATE(extfname, F_RDWR);
- X error_message = 1; /* give error message if open fails */
- X } else {
- X error_message = 0; /* user said 'n', so no error message */
- X }
- X } else {
- X error_message = 1; /* Real error -- give error message */
- X }
- X } /* end if */
- X } /* end if */
- X
- X if (this_han == -1) { /* file couldn't be opened */
- X if (error_message == 1) {
- X unlink (extfname);
- X#ifdef OOZ
- X prterror ('e', could_not_open, extfname, " for output.\n");
- X#else
- X prterror ('e', "Can't open %s for output.\n", extfname);
- X#endif
- X
- X#ifndef PORTABLE
- X /* if error was due to full disk, abort */
- X if (space(0, &alloc_size) < alloc_size)
- X#endif
- X prterror ('f', disk_full, (char *) NULL, (char *) NULL);
- X
- X }
- X } else if (lseek (zoo_han, direntry.offset, 0) == -1L) {
- X prterror ('e', "Could not seek to file data.\n");
- X close_han (this_han);
- X } else {
- X#ifndef PORTABLE
- X /* check Dos's free disk space if we seem to be running low
- X (within 1 cluster of being full) */
- X if (tofile && disk_space < direntry.org_size + alloc_size) {
- X disk_space = space (0, &alloc_size);
- X if (disk_space < alloc_size) {
- X close_han (this_han);
- X unlink (extfname);
- X prterror ('f', disk_full, (char *) NULL, (char *) NULL);
- X }
- X }
- X#endif
- X if (tofile && disk_space < direntry.org_size) {
- X#ifdef PORTABLE
- X ;
- X#else
- X#ifdef OOZ
- X prterror ('e', no_space, extfname, ".\n");
- X#else
- X prterror ('e', no_space, extfname);
- X#endif
- X
- X unlink (extfname); /* delete any created file */
- X#endif /* portable */
- X
- X } else {
- X
- X#ifndef OOZ
- X#ifndef PORTABLE
- X if (fast_ext) { /* fast ext -> create header */
- X void make_tnh();
- X struct tiny_header tiny_header;
- X make_tnh(&tiny_header, &direntry);
- X write (this_han, (char *) &tiny_header, sizeof (tiny_header));
- X
- X if (direntry.cmt_size != 0) { /* copy comment */
- X long save_pos;
- X save_pos = tell (zoo_han);
- X lseek (zoo_han, direntry.comment, 0);
- X getfile (zoo_han, this_han,
- X (long) direntry.cmt_size, 0);
- X lseek (zoo_han, save_pos, 0);
- X }
- X }
- X#endif /* ifndef PORTABLE */
- X#endif /* ifndef OOZ */
- X
- X crccode = 0; /* Initialize CRC before extraction */
- X#ifdef OOZ
- X putstr (extfname);
- X {
- X register int i;
- X for (i = strlen(direntry.fname); i < 13; i++)
- X putstr (" ");
- X putstr ("-- ");
- X }
- X#else
- X if (!pipe) {
- X#ifdef PORTABLE
- X prterror ('m', "%-14s -- ", extfname);
- X#else
- X if (fast_ext)
- X prterror ('m', "%-12s ==> %-12s -- ",
- X direntry.fname, extfname);
- X else
- X prterror ('m', "%-12s -- ", extfname);
- X#ifdef COMMENT
- X prterror ('m',
- X fast_ext ? "%-12s ==> %-12s -- " : "%-12s -- ",
- X direntry.fname, extfname);
- X#endif /* COMMENT */
- X#endif /* PORTABLE */
- X
- X } else { /* must be pipe */
- X prterror ('M', "\n\n********\n%s\n********\n", direntry.fname);
- X
- X#ifdef COMMENT
- X#ifdef SETMODE
- X MODE_BIN(this_han); /* make std output binary so
- X ^Z won't cause error */
- X#endif
- X#endif
- X }
- X#endif /* OOZ */
- X
- X#ifndef NOSIGNAL
- X#ifndef OOZ
- X if (tofile)
- X#endif /* not OOZ */
- X {
- X oldsignal = signal (SIGINT, SIG_IGN);
- X if (oldsignal != SIG_IGN)
- X signal (SIGINT, ctrl_c); /* Trap ^C & erase partial file */
- X }
- X#endif /* not NOSIGNAL */
- X
- X if (direntry.packing_method == 0)
- X /* 4th param 1 means CRC update */
- X status = getfile (zoo_han, this_han, direntry.size_now, 1);
- X
- X#ifndef OOZ
- X else if (fast_ext)
- X /* 4th param 0 means no CRC update */
- X status = getfile (zoo_han, this_han, direntry.size_now, 0);
- X#endif
- X
- X
- X else if (direntry.packing_method == 1)
- X status = lzd (zoo_han, this_han); /* uncompress */
- X else {
- X#ifdef OOZ
- X prterror ('e', "File ", whichname,
- X ": impossible packing method.\n", "");
- X#else
- X prterror ('e', "File %s: impossible packing method.\n",
- X whichname);
- X#endif
- X unlink(extfname);
- X goto loop_again;
- X }
- X
- X
- X#ifndef NOSIGNAL
- X#ifndef OOZ
- X if (tofile)
- X#endif /* not OOZ */
- X signal (SIGINT, oldsignal);
- X#endif /* not NOSIGNAL */
- X
- X#ifdef COMMENT
- X#ifndef OOZ
- X#ifdef SETMODE
- X if (pipe)
- X MODE_TEXT(this_han); /* restore text mode */
- X#endif
- X#endif
- X#endif
- X
- X#ifndef OOZ
- X if (tofile) {
- X#endif
- X /* set date/time of file being extracted */
- X#ifdef NIXTIME
- X close_han (this_han);
- X setutime (extfname, direntry.date, direntry.time);
- X#else
- X settime (this_han, direntry.date, direntry.time);
- X close_han (this_han);
- X#endif
- X#ifndef OOZ
- X }
- X#endif
- X if (status != 0) {
- X if (tofile)
- X unlink (extfname);
- X if (status == 1) {
- X memerr();
- X /* To avoid spurious errors due to ^Z being sent to screen,
- X we don't check for I/O error if output was piped */
- X } else if (!pipe && (status == 2 || status == 3)) {
- X#ifdef OOZ
- X prterror ('e', no_space, direntry.fname, ".\n");
- X#else
- X prterror ('e', no_space, direntry.fname);
- X#endif
- X }
- X } else {
- X /* file extracted, so update disk space. */
- X /* we subtract the original size of the file, rounded
- X UP to the nearest multiple of the disk allocation
- X size. */
- X#ifndef PORTABLE
- X {
- X unsigned long temp;
- X temp = (direntry.org_size + alloc_size) / alloc_size;
- X disk_space -= temp * alloc_size;
- X }
- X#endif
- X
- X#ifdef OOZ
- X if (direntry.file_crc != crccode)
- X putstr ("extracted \007WARNING: Bad CRC.\n");
- X else
- X putstr ("extracted\n");
- X#else
- X if (!fast_ext && direntry.file_crc != crccode) {
- X badcrc_count++;
- X if (!pipe) {
- X if (!null_device)
- X prterror ('M', "extracted ");
- X prterror ('w', bad_crc, direntry.fname);
- X }
- X else { /* duplicate to standard error */
- X static char stars[] = "\n******\n";
- X putstr (stars);
- X prterror ('w', bad_crc, direntry.fname);
- X putstr (stars);
- X fprintf (stderr, "WARNING: ");
- X fprintf (stderr, bad_crc, direntry.fname);
- X }
- X } else
- X if (!pipe)
- X prterror ('M', null_device ? "OK\n" : "extracted\n");
- X#endif
- X
- X } /* end if */
- X } /* end if */
- X } /* end if */
- X } /* end if */
- X
- Xloop_again:
- X lseek (zoo_han, next_ptr, 0); /* ..seek to next dir entry */
- X} /* end while */
- X
- Xclose (zoo_han);
- Xif (!matched)
- X putstr (no_match);
- X
- X#ifndef OOZ
- Xif (badcrc_count) {
- X prterror ('w', "%d File(s) with bad CRC.\n", badcrc_count);
- X exit (1);
- X} else if (null_device)
- X prterror ('m', "Archive seems OK.\n");
- X#endif
- X
- X} /* end zooext */
- X
- X/* close_han() */
- X/* closes a handle if and only if we aren't sending output to
- X a pipe or to the null device */
- X
- Xvoid close_han (handle)
- Xint handle;
- X{
- X if (tofile)
- X close (handle);
- X}
- X
- X/* Ctrl_c() is called if ^C is hit while a file is being extracted.
- X It closes the files, deletes it, and exits. */
- Xint ctrl_c()
- X{
- X#ifndef NOSIGNAL
- X signal (SIGINT, SIG_IGN); /* ignore any more */
- X#endif
- X close (this_han);
- X unlink (extfname);
- X exit (1);
- X}
- X
- X/* make_tnh copies creates a tiny_header */
- Xvoid make_tnh (tiny_header, direntry)
- Xstruct tiny_header *tiny_header;
- Xstruct direntry *direntry;
- X{
- X tiny_header->tinytag = TINYTAG;
- X tiny_header->type = 1;
- X tiny_header->packing_method = direntry->packing_method;
- X tiny_header->date = direntry->date;
- X tiny_header->time = direntry->time;
- X tiny_header->file_crc = direntry->file_crc;
- X tiny_header->org_size = direntry->org_size;
- X tiny_header->size_now = direntry->size_now;
- X tiny_header->major_ver = direntry->major_ver;
- X tiny_header->minor_ver = direntry->minor_ver;
- X tiny_header->cmt_size = direntry->cmt_size;
- X strcpy (tiny_header->fname, direntry->fname);
- X}
- SHAR_EOF
- fi
- if test -f 'zoofns.h'
- then
- echo shar: "will not over-write existing file 'zoofns.h'"
- else
- sed 's/^X//' << \SHAR_EOF > 'zoofns.h'
- X/* @(#) zoofns.h 1.7 87/05/03 16:02:33 */
- X
- X/*
- XThe contents of this file are hereby released to the public domain.
- X
- X -- Rahul Dhesi 1986/11/14
- X*/
- X
- X
- X/* Defines function declarations for all Zoo functions */
- X
- X#ifdef LINT_ARGS
- Xlong calc_ofs(char *);
- Xchar *addext (char *, char *);
- Xchar *choosefname (struct direntry *);
- Xchar *combine (char[], char *, char *);
- Xchar *emalloc (unsigned int);
- Xchar *erealloc (char *, unsigned int);
- Xchar *findlast (char *, char *);
- Xchar *fixfname (char *);
- Xchar *fullpath (struct direntry *);
- Xchar *getstdin ();
- Xchar *lastptr (char *);
- Xchar *nameptr (char *);
- Xchar *newcat (char *, char *);
- Xchar *memset (char *, int, unsigned);
- Xchar *nextfile (int, char *, int);
- Xint addfile (int, int);
- Xint cfactor (long, long);
- Xint chname (char *, char *);
- Xint cmpnum (unsigned int, unsigned int, unsigned int, unsigned int);
- Xint ctrl_c();
- Xint exists (char *);
- Xint frd_zooh (struct zoo_header *, FILE *);
- Xint frd_dir (struct direntry *, FILE *);
- Xint fwr_dir (struct direntry *, FILE *);
- Xint fwr_zooh (struct zoo_header *, FILE *);
- Xint getfile (int, int, long, int);
- Xint handle_break();
- Xint kill_files (char *[], int);
- Xint lzc (int, int);
- Xint lzd (int, int);
- Xint match_half (char *, char *);
- Xint match (char *, char *);
- Xint readdir (struct direntry *, FILE *, int);
- Xint settime (int, unsigned int, unsigned int);
- Xint strcmpi (char *, char *);
- Xint rd_zooh (struct zoo_header *, int);
- Xint rd_dir (struct direntry *, int);
- Xint wr_zooh (struct zoo_header *, int);
- Xint wr_dir (struct direntry *, int);
- Xlong inlist (char *, unsigned int *, unsigned int *, int);
- Xlong tell (int);
- Xunsigned long space (int, int *);
- Xvoid addbfcrc(char *, int);
- Xvoid addfname (char *, long, unsigned int, unsigned int);
- Xvoid basename (char *, char []);
- Xvoid break_off();
- Xvoid close_han (int);
- Xvoid comment (char *, char *);
- Xvoid extension (char *, char []);
- Xvoid fcbpath (struct dta_t *, char *, char *);
- Xvoid fixslash (char *);
- Xvoid makelist (int, char *[], char *[], int, char *, char *, char *, int *);
- Xvoid memerr();
- Xvoid newdir (struct direntry *);
- Xvoid parse (struct path_st *, char *);
- Xvoid prterror(int, char *, );
- Xvoid rootname (char *, char *);
- Xvoid skip_files (FILE *, unsigned int *, unsigned int *, int *,
- X char [], long *);
- Xvoid writedir (struct direntry *, FILE *);
- Xvoid writenull (int, int);
- Xvoid zooadd(char *, int, char **, char *);
- Xvoid zoodel(char *, char *, int);
- Xvoid zooext(char *, char *);
- Xvoid zoolist(char **, char *, int);
- Xvoid zoopack (char *, char *);
- X
- X#else
- X/* if no LINT_ARGS */
- X
- Xlong calc_ofs();
- Xchar *addext ();
- Xchar *choosefname ();
- Xchar *combine ();
- Xchar *emalloc ();
- Xchar *erealloc ();
- Xchar *findlast ();
- Xchar *fixfname ();
- Xchar *fullpath ();
- Xchar *getstdin ();
- Xchar *lastptr ();
- Xchar *nameptr ();
- Xchar *newcat ();
- Xchar *memset ();
- Xchar *nextfile ();
- Xint addfile ();
- Xint cfactor ();
- Xint chname ();
- Xint cmpnum ();
- Xint ctrl_c();
- Xint exists ();
- Xint frd_zooh ();
- Xint frd_dir ();
- Xint fwr_dir ();
- Xint fwr_zooh ();
- Xint getfile ();
- Xint handle_break();
- Xint kill_files ();
- Xint lzc ();
- Xint lzd ();
- Xint match_half ();
- Xint match ();
- Xint readdir ();
- Xint settime ();
- Xint strcmpi ();
- Xint rd_zooh ();
- Xint rd_dir ();
- Xint wr_zooh ();
- Xint wr_dir ();
- Xlong inlist ();
- Xlong tell ();
- Xunsigned long space ();
- Xvoid addbfcrc();
- Xvoid addfname ();
- Xvoid basename ();
- Xvoid break_off();
- Xvoid close_han ();
- Xvoid comment ();
- Xvoid extension ();
- Xvoid fcbpath ();
- Xvoid fixslash ();
- Xvoid makelist ();
- Xvoid memerr();
- Xvoid newdir ();
- Xvoid parse ();
- Xvoid prterror();
- Xvoid rootname ();
- Xvoid skip_files ();
- Xvoid writedir ();
- Xvoid writenull ();
- Xvoid zooadd();
- Xvoid zoodel();
- Xvoid zooext();
- Xvoid zoolist();
- Xvoid zoopack ();
- X#endif /* end of no LINT_ARGS */
- SHAR_EOF
- fi
- exit 0
- # End of shell archive
- --
- Rahul Dhesi UUCP: {ihnp4,seismo}!{iuvax,pur-ee}!bsu-cs!dhesi
-
- --
-
- Rich $alz
- Cronus Project, BBN Labs rsalz@bbn.com
- Moderator, comp.sources.unix sources@uunet.uu.net
-