[comp.sources.unix] v11i016: File archive program, Part07/07

rs@uunet.UU.NET (Rich Salz) (08/19/87)

Submitted-by: iuvax!bsu-cs!dhesi@seismo.CSS.GOV (Rahul Dhesi)
Posting-number: Volume 11, Issue 16
Archive-name: zoo/Part07

#! /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:
#	zoolist.c
#	zoomem.h
#	zoopack.c
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'zoolist.c'
then
	echo shar: "will not over-write existing file 'zoolist.c'"
else
sed 's/^X//' << \SHAR_EOF > 'zoolist.c'
X#ifndef LINT
Xstatic char sccsid[]="@(#) zoolist.c 1.12 87/05/29 12:56:18";
X#endif /* LINT */
X
X/*
XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
X*/
X#include "options.h"
X#include "portable.h"
X#include "zoomem.h"  /* to get ZOOCOUNT */
X
X/* Lists files in archive */
X#include "zoo.h"
X#include "errors.i"
X#include <stdio.h>
X#include "various.h"
X#include "zoofns.h"
X
Xstatic char tot_fmt[] = "%8lu %3u%% %8lu  %4d file"; 
Xstatic char tot_line[] = 
X   /* "------------  --------  ---  --------  --------- --------\n"; */
X   "--------  --- --------  --------- --------\n";
X
Xstatic char dbl_percent[] = "Archive %s:  %s";
X
X#ifdef LINT_ARGS
Xvoid show_comment (struct direntry *, FILE *, int, char *);
Xint ver_too_high (struct zoo_header *);
X#endif
X
Xvoid zoolist (argv, option, argc)
Xchar **argv, *option;
Xint argc;
X{
Xchar whichname[PATHSIZE];  /* which name to use */
Xchar *this_zoo;            /* currently matched archive name */
Xregister FILE *zoo_file;
Xchar *flist[ZOOCOUNT];       /* list of ptrs to input archive names */
Xint fptr;                  /* will point to within list of archive names */
X
Xstruct direntry direntry;
Xstruct zoo_header zoo_header;
Xint size_factor;
Xchar packing[9];
Xunsigned long tot_org_siz = 0L, tot_siz_now = 0L;
Xint   tot_sf;
Xint file_count = 0;
Xint del_count = 0;                  /* number of deleted entries */
Xint bad_pack;                 /* 1 if packing method is unknown */
Xstatic char *month_list="000JanFebMarAprMayJunJulAugSepOctNovDec";
Xstatic char dashes[] = "------------\n";
Xint year, month, day, hours, min, sec;
Xint list_deleted = 0;         /* list deleted files too */
Xint fast = 0;                 /* fast list */
Xint column;                   /* for column printing */
Xlong fiz_ofs = 0;             /* offset where to start */
Xint verb_list = 0;            /* if verbose listing needed */
Xint show_name = 0;            /* if archive name to be included in listing */
Xint zoocount = 1;             /* number of archives to list */
Xint biglist = 0;              /* multiarchive listing */
Xint longest;                  /* length of longest archive name */
X
Xwhile (*option) {
X   switch (*option) {
X      case 'a': show_name++; break;
X      case 'd': list_deleted++; break;
X      case 'f': fast++; break;
X      case 'c':
X      case 'v': verb_list++; break;
X      case 'l': break;
X      case 'L': biglist++; zoocount = argc; break;
X      case '@': 
X         ++option;
X         fiz_ofs = calc_ofs(option); 
X         goto no_more;
X      default:
X         prterror ('w', option_ignored, *option);
X   }
X   option++;
X}
X
Xno_more:  /* come from exit from while loop above */
X
Xif (fast && show_name) {      /* don't allow 'a' with 'f' */
X   show_name = 0;
X   prterror ('w', option_ignored, 'a');
X}
X
X#ifdef WILDCARD
X   /* For each archive name supplied, if it is not a char range and
X      does not contain a dot, append "*.zoo". */
X   {
X      int i;
X      for (i = 0; i < argc;  i++) {
X         if (strchr (nameptr (argv[i]), EXT_CH) == NULL && 
X                           !match_half (nameptr (argv[0]), "?-?"))
X            argv[i] = newcat (argv[i], "*.zoo");
X      }
X   }
X#endif
X
Xmakelist (zoocount, argv, flist,        ZOOCOUNT-2,   (char *) NULL,".","..", &longest);
X/*        ^argc     ^argv ^list_pointer ^max_no_files   ^exclude */
X
Xfor (fptr = 0;  (this_zoo = flist[fptr]) != NULL; fptr++) {
X   int ercount;                  /* count of errors */
X   int entrycount;               /* count of directory entries */
X   int column;                   /* for column printing */
X   int expl_deleted;             /* explain what D means */
X   int expl_comment;             /* explain what comment means */
X   int expl_ver;                 /* Explain what V means */
X   int expl_star;                /* Explain what * means */
X   int first_time;               /* first time through loop for an archive */
X
X   ercount = entrycount = column = del_count =
X      expl_deleted = expl_comment = expl_ver = expl_star = 0;
X   first_time = 1;
X
X#ifndef WILDCARD
X   /* Add default extension if none supplied */
X   if (strchr (nameptr (this_zoo), EXT_CH) == NULL)
X      this_zoo = newcat (this_zoo, EXT_DFLT);
X#endif
X
X   zoo_file = fopen (this_zoo, FRDSTR);
X
X   if (zoo_file == NULL) {
X      prterror ('e', could_not_open, this_zoo);
X      continue;
X   } else if (!show_name)
X      printf ("\nArchive %s:\n", this_zoo);
X   
Xif (fiz_ofs != 0L) {                /* if offset specified, start there */
X   prterror('m', "Starting at %ld\n", fiz_ofs);
X   fseek (zoo_file, fiz_ofs, 0);
X} else {
X   if (frd_zooh (&zoo_header, zoo_file) == -1 ||
X                                             zoo_header.zoo_tag != ZOO_TAG) {
X      prterror ('e', dbl_percent, this_zoo, invalid_header);
X      goto loop_end;
X   }
X   /* Seek to the beginning of the first directory entry */
X   if (fseek (zoo_file, zoo_header.zoo_start, 0) != 0) {
X      ercount++;
X      prterror ('e', dbl_percent, this_zoo, bad_directory);
X      goto loop_end;
X   }
X   if (!show_name && ver_too_high (&zoo_header)) {
X      ercount++;
X      if (ercount < 2) {
X         prterror ('w', dbl_percent, this_zoo, "");
X         prterror ('M', wrong_version, zoo_header.major_ver, zoo_header.minor_ver);
X      }
X   }
X} /* end if (fiz_ofs !- 0L) */
X
X   /* Now we print information about each file in the archive */
X   
X   if (!show_name) { /* initialize for each file only if not disk catalog */
X      tot_org_siz = 0L;  
X      tot_siz_now = 0L;
X      file_count = 0;
X      del_count = 0;
X   }
X
X   while (1) {
X      if (readdir (&direntry, zoo_file, 0) == -1) {
X         prterror ('F', dbl_percent, this_zoo, bad_directory);
X         goto givesummary;
X      }
X      if (direntry.zoo_tag != ZOO_TAG) {
X         long currpos, zoolength;
X         prterror ('F', dbl_percent, this_zoo, invalid_header);
X         if ((currpos = ftell (zoo_file)) != -1L)
X            if (fseek (zoo_file, 0L, 2) == 0)
X               if ((zoolength = ftell (zoo_file)) != -1L)
X                  printf (cant_process, zoolength - currpos);              
X         goto givesummary;
X      }
X   
X      if (direntry.next == 0L)      /* EXIT on end of chain */
X         break;                                 
X      else
X         entrycount++;              /* Number of directory entries */
X   
X      if (direntry.deleted)
X         ++del_count;
X      
X		/* Into whichname put the combined pathname + filename */
X		strcpy (whichname, fullpath (&direntry));
X#ifdef DEBUG
X      printf("matching against [%s] and [%s]\n", 
X               nameptr(whichname), whichname);
X#endif
X
X      if ( ( (list_deleted && direntry.deleted) ||
X               (list_deleted < 2 && !direntry.deleted)
X           ) 
X              && (biglist || needed(whichname))) {
X   
X         file_count++;
X   
X         if (direntry.packing_method > MAX_PACK) {
X            bad_pack = 1;
X            expl_ver = 1;
X         }  else
X            bad_pack = 0;
X      
X         size_factor = cfactor (direntry.org_size, direntry.size_now);
X   
X         year  =  ((unsigned int) direntry.date >> 9) & 0x7f;
X         month =  ((unsigned int) direntry.date >> 5) & 0x0f;
X         day   =  direntry.date        & 0x1f;
X   
X         hours =  ((unsigned int) direntry.time >> 11)& 0x1f;
X         min   =  ((unsigned int) direntry.time >> 5) & 0x3f;
X         sec   =  ((unsigned int) direntry.time & 0x1f) * 2;
X   
X         if (fast) {
X            if ((column++ % 5) == 0 && !first_time)
X               fputchar ('\n');
X            printf("%-12s  ", direntry.fname);
X				fflush (stdout);
X   
X         } else {
X            if (first_time && !show_name) {     /* print archive header */
X               printf ("Length    CF  Size Now  Date      Time\n");
X               printf (tot_line);
X            }
X            printf ("%8lu %3u%% %8lu  %2d %-.3s %02d %02d:%02d:%02d",  
X                     direntry.org_size, 
X                     size_factor, direntry.size_now, 
X                     day, &month_list[month*3], 
X                     (day && month) ?  (year+80) % 100 : 0,
X                     hours, min, sec);
X               tot_org_siz += direntry.org_size;
X               tot_siz_now += direntry.size_now;
X   
X            if (direntry.cmt_size) {
X               expl_comment++;
X               printf ("C");
X            } else
X               printf (" ");
X   
X            if (direntry.deleted) {
X               expl_deleted++;
X               printf ("D");
X            }  else
X               printf (" ");
X            if (list_deleted)
X               printf (" ");
X            if (show_name)
X               printf ("%-*s ", longest, this_zoo);
X
X				/* new code to get around a common compiler bug */
X				printf (whichname);
X				if (direntry.dir_crc != 0) {
X					expl_star++;
X					printf ("*");
X				}
X
X            if (bad_pack)
X               printf (" (V%d.%d)", direntry.major_ver, direntry.minor_ver);
X            printf ("\n");
X         }
X         first_time = 0;
X   
X         /* if verbose listing requested show any comment.  f overrrides v */
X         if (verb_list && !fast)
X            show_comment (&direntry, zoo_file, 0, (char *) NULL);
X      }
X   
X      fseek (zoo_file, direntry.next, 0); /* ..seek to next dir entry */
X   } /* end while */
X   
X   givesummary:
X   
X   if (!show_name) {
X      if (fast) {
X         if (file_count) {
X            if (del_count)
X               printf ("\n-----\n");
X            else
X               fputchar ('\n');
X         }
X         if (del_count)
X            printf ("%d deleted.\n", del_count);
X      }
X      if (!fast && file_count) {
X         tot_sf = cfactor (tot_org_siz, tot_siz_now);
X         printf (tot_line);
X      
X         printf (tot_fmt, tot_org_siz, tot_sf, tot_siz_now, file_count);
X			if (file_count > 1)
X				printf ("s\n");
X			else
X				printf ("\n");
X         
X         if (del_count || expl_ver || expl_deleted || expl_comment)
X            printf (dashes);
X      }
X   
X      if (!fast) {
X         if (del_count) {
X            if (expl_deleted)
X               printf ("D: deleted file.\n");
X            else {
X               if (del_count == 1)
X                  printf ("There is 1 deleted file.\n");
X               else
X                  printf ("There are %d deleted files.\n", del_count);
X            }
X         }
X      }
X      if (expl_comment && !fast && !verb_list) 
X         printf ("C: file has attached comment.\n");
X      if (expl_ver && !fast)
X         printf ("V: minimum version of Zoo needed to extract this file.\n");
X      if (expl_star && !fast)
X         printf ("*: directory entry may be corrupted.\n");
X      if (!file_count)
X         printf ("Zoo:  %s", no_match);
X      
X      if (!entrycount && !fiz_ofs)
X         printf ("(The archive is empty.)\n");
X   } /* end if (show_name) */
Xloop_end:            /* jump here on badly structured archive */
X   fclose (zoo_file);
X} /* end for */
X
Xif (show_name) {
X   if (file_count) {
X      tot_sf = cfactor (tot_org_siz, tot_siz_now);
X      printf (tot_line);
X      printf (tot_fmt, tot_org_siz, tot_sf, tot_siz_now, file_count);
X		if (file_count > 1)
X			printf ("s\n");
X		else
X			printf ("\n");
X   } 
X}
X
Xif (!file_count)
X   exit (1);            /* Consider it an error if there were no files */
X} /* zoolist() */
X
SHAR_EOF
fi
if test -f 'zoomem.h'
then
	echo shar: "will not over-write existing file 'zoomem.h'"
else
sed 's/^X//' << \SHAR_EOF > 'zoomem.h'
X/* @(#) zoomem.h 1.2 87/05/03 16:02:44 */
X
X/*
XThe contents of this file are hereby released to the public domain.
X
X                           -- Rahul Dhesi 1986/11/14
X
XDefines parameters used for memory allocation.  
X
X   Xenix notes:  Under Xenix release 3.0 on an Intel 310 machine with an
X   80286 cpu, memory is very tight when the small memory model is used. 
X   Ooz won't fit if the buffers are 2 K for input and 6 K for output.  
X   It does fit if both input and output buffers are 1 K each.  Under
X   the large memory model there is no problem.  Zoo requires the large
X   memory model.
X
X   AT&T 3B2:  There seem to be no problem at all.  Buffers can always
X   be 8192 each.
X*/
X
X#ifdef OOZ
X#define  IN_BUF_SIZE       8192
X#define  OUT_BUF_SIZE      8192
X#else
X#define  IN_BUF_SIZE       8192
X#define  OUT_BUF_SIZE      8192
X#endif
X
X#define  MEM_BLOCK_SIZE    (IN_BUF_SIZE + OUT_BUF_SIZE)
X
X/* 
XLIST_SIZE is the size of the list built by Zoo to hold all filenames
Xencountered in an archive.  This is used to know when to replace an
Xalready existing file.  The date and time stored with the filename is
Xused in comparisons when an archive update has been requested.  To 
Xadd a file to an archive, the archive must not already have more than
XLIST_SIZE files in it.
X
XZOOCOUNT is the number of archive names that may be matched by the
Xarchive filespec specified for a list.
X
XMAXADD is the number of filenames that may be added to an archive
Xat one go.  The total number of files that an archive may contain
Xis not determined by MAXADD but is determined by LIST_SIZE.
X
XIf USE_MALLOC is defined it tells the memory allocation routine 
Xemalloc() not to bother with maintaining its own memory blocks but just to 
Xpass on requests to the library function malloc().  If USE_MALLOC is not 
Xdefined, emalloc() does its own memory management to save overhead on a 
Xmachine with limited memory.
X*/
X
X#ifdef   SMALL_MEM
X#define  LIST_SIZE  (200)
X#define  ZOOCOUNT   (30)
X#define  MAXADD     (100)
X#define  USE_MALLOC
X#endif
X
X#ifdef   MED_MEM
X#define  LIST_SIZE  (400)
X#define  ZOOCOUNT   (50)
X#define  MAXADD     (200)
X#define  USE_MALLOC
X#endif
X
X#ifdef   BIG_MEM
X#define  LIST_SIZE  (4000)
X#define  ZOOCOUNT   (400)
X#define  MAXADD     (4000)
X#define  USE_MALLOC
X#endif
X
X/* Customizable sizes */
X#ifdef   SPEC_MEM
X#define  LIST_SIZE   (600)
X#define  ZOOCOUNT    (100)
X#define  MAXADD      (400)
X#endif
X
Xextern char *out_buf_adr;              /* global I/O buffer */
SHAR_EOF
fi
if test -f 'zoopack.c'
then
	echo shar: "will not over-write existing file 'zoopack.c'"
else
sed 's/^X//' << \SHAR_EOF > 'zoopack.c'
X#ifndef LINT
X/* @(#) zoopack.c 1.12 87/05/29 12:56:31 */
Xstatic char sccsid[]="@(#) zoopack.c 1.12 87/05/29 12:56:31";
X#endif /* LINT */
X
X/*
XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
X*/
X#include "options.h"
X/* Packs an archive.  The sequence is:
X   1. Copy all files from current archive to new one.
X   2. If the user didn't want a backup, delete the old archive
X      else rename it to same name with extension of .BAK.
X   3. Rename temporary archive to old name.
X*/
X
X/* define this to make packing noisless except for dots */
X#define QUIETPACK 1
X
X
X#include "portable.h"
X#include <stdio.h>
X#include "various.h"
X#include "zoo.h"
X#include "zoofns.h"
X#include "errors.i"
X#ifndef NOSIGNAL
X#include <signal.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 NOFCNTL
X#include <file.h>
X#else
X#include <fcntl.h>
X#endif
X
Xstruct zoo_header zoo_header = {
X   TEXT,
X   ZOO_TAG,
X   (long) SIZ_ZOOH,
X   (long) (-SIZ_ZOOH),
X   MAJOR_VER,
X   MINOR_VER
X};
Xchar file_leader[] = FILE_LEADER;
Xextern int quiet;
Xint break_hit;
X
X#ifdef LINT_ARGS
Xint ver_too_high (struct zoo_header *);
X#else
Xint ver_too_high();
X#endif
X
Xvoid zoopack(zoo_path, option)
Xchar *zoo_path, *option;
X{
Xstatic char temp_file[PATHSIZE] = "XXXXXX";
X#ifndef NOSIGNAL
Xint (*oldsignal)();
X#endif
Xregister int zoo_han;                     /* handle for open archive */
Xregister FILE *zoo_file;                  /* stream for open archive */
Xint new_han;                              /* handle of destination archive */
Xlong next_ptr;                            /* pointer to within archive */
Xlong new_dir_pos;                         /* ditto */
Xstruct direntry direntry;                 /* directory entry */
Xstruct zoo_header old_zoo_header;         /* just for reading old header */
Xint status;                               /* error status */
Xint nobackup = 0;                         /* keep backup */
Xint force = 0;                            /* force overwrite of old backup */
Xint extcount = 0;                         /* how many files moved */
Xchar backup_name[PATHSIZE];               /* name of backup */
Xint bad_header = 0;                       /* if archive has bad header */
Xint latest_date = 0;                      /* latest date on any file moved */
Xint latest_time = 0;                      /*  ...likewise */
Xint curr_dir = 0;									/* create backup in curr dir */
Xstatic char partial_msg[] =
X   "Partially packed archive left in %s.\n";
X
Xwhile (*option) {
X   switch (*option) {
X      case 'P': force++; break;
X      case 'E': nobackup++; break;
X      case 'q': quiet++; break;
X		case '.': curr_dir++; break;
X      default:
X         prterror ('f', inv_option, *option);
X   }
X   option++;
X}
Xif (force == 1)         /* force only if P was doubled */
X   force--;
X
Xzoo_path = addext (zoo_path, EXT_DFLT);      /* add default extension */
X
X/* Create a backup name by replacing any extension by backup extension. */
Xstrcpy (backup_name, zoo_path);
X{
X   char *temp;
X   if (temp = strrchr (backup_name,EXT_CH))      /* if dot found */
X      strcpy (temp, BACKUP_EXT);                /* replace old extension */
X   else
X      strcat (backup_name, BACKUP_EXT);         /* else just append */
X}
X
X/* Open original archive for read-only access */
Xzoo_file = fopen(zoo_path, FRDSTR);
Xzoo_han = OPEN(zoo_path, F_READ);	/* different open */
X
Xif (zoo_file == NULL || zoo_han == -1)
X   prterror ('f', could_not_open, zoo_path);
X
X/* Read the header of the old archive. */
Xfrd_zooh(&old_zoo_header, zoo_file);
X/* fread ((char *) &old_zoo_header, sizeof(old_zoo_header), 1, zoo_file); */
X
Xif ((old_zoo_header.zoo_start + old_zoo_header.zoo_minus) != 0L) {
X   prterror ('w', failed_consistency);
X   ++bad_header;                    /* remember for future error message */
X}
X
X/* Refuse to pack it if its version number is higher than we can accept */
Xif (ver_too_high (&old_zoo_header))
X   prterror ('f', wrong_version, old_zoo_header.major_ver,
X                                    old_zoo_header.minor_ver);
X
Xfseek (zoo_file, old_zoo_header.zoo_start, 0); /* seek to where data begins */
X
X/* Now see if the archive already exists with the backup extension.  If so,
X   give an error message and abort.  However, we skip this test if the user
X   specified overwriting the backup */
X
Xif (!force) {
X   if (exists (backup_name))
X      prterror ('f', "File %s already exists.  Delete it or use PP option.\n",
X                      backup_name);
X}
X
X/*
XOpen the new archive by a temporary name.  If not otherwise specified,
Xwe open the new archive in the same directory as the original.  But if
Xthe curr_dir switch was given, we leave temp_file unchanged, and it
Xwas already initialized to be just the template XXXXXX.
X*/
Xif (!curr_dir) {
X	strcpy (temp_file, zoo_path);          /* original archive name */
X	*nameptr (temp_file) = '\0';           /* ... minus original filename */
X	strcat (temp_file, "XXXXXX");          /* ... plus XXXXXX */
X}
Xmktemp (temp_file);                    /* ... and make unique */
X
Xnew_han = CREATE(temp_file, F_RDWR);
Xif (new_han == -1)
X   prterror ('f', "Could not create temporary file %s.\n", temp_file);
X
X/* Write the header of the new archive, updated with our own data */
Xwr_zooh (&zoo_header, new_han);
X/* write (new_han, (char *) &zoo_header, sizeof(zoo_header)); */
Xlseek (new_han, zoo_header.zoo_start, 0);       /* position to add files */
X
X/* Now we loop through the old archive's files and add each to the new
Xarchive.  The only changes needed are to update the .next and .offset
Xfields of the directory entry. */
X
Xwhile (1) {
X
X   frd_dir(&direntry, zoo_file);
X/* fread ((char *) &direntry, sizeof (direntry), 1, zoo_file); */
X
X   if (direntry.zoo_tag != ZOO_TAG) {
X      long currpos, zoolength;
X      prterror ('F', bad_directory);
X      if (bad_header) {    /* bad headers means don't save temp file */
X         close (new_han);
X         unlink (temp_file);
X      } else {
X         writenull (new_han, MAXDIRSIZE);    /* write final null entry */
X         printf (partial_msg, temp_file);
X         if ((currpos = ftell (zoo_file)) != -1L)
X            if (fseek (zoo_file, 0L, 2) == 0)
X               if ((zoolength = ftell (zoo_file)) != -1L)
X                  printf (cant_process, zoolength - currpos);
X      }
X      exit (1);
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   if (!direntry.deleted) {
X#ifdef QUIETPACK
X/* nothing */
X#else
X      prterror ('m', "%-14s -- ",
X         direntry.namlen > 0 ? direntry.lfname : direntry.fname);
X#endif
X
X      if (lseek (zoo_han, direntry.offset, 0) == -1L) {
X         prterror ('f', "Could not seek to file data.\n");
X      } else {
X         extcount++;          /* update count of files extracted */
X
X         /* write a directory entry for this file */
X         new_dir_pos = tell (new_han);   /* new direntry pos in new archive */
X
X         /*
X         Write a null directory entry to preserve integrity in case of
X         program being interrupted.  Note:  I don't think it is
X         necessary to save direntry.next but I haven't checked.
X
X         Old code was:
X         writenull(new_han, SIZ_DIRL + direntry.var_dir_len);
X         */
X         {
X            long oldnext;
X            oldnext = direntry.next;
X            direntry.next = 0L;
X            wr_dir(&direntry, new_han);
X            direntry.next = oldnext;
X         }
X
X         lseek (zoo_han, direntry.offset, 0);     /* where to start copying */
X         /* Write file leader and remember position of new file data */
X         write (new_han, file_leader, SIZ_FLDR);
X         direntry.offset = tell(new_han);
X         status = getfile (zoo_han, new_han, direntry.size_now, 0);
X         /* if no error copy any comment attached to file */
X         if (status == 0 && direntry.cmt_size != 0) {
X            lseek (zoo_han, direntry.comment, 0);  /* seek to old comment  */
X            direntry.comment = tell (new_han);  /* location of new comment */
X            status = getfile (zoo_han, new_han,
X                                 (long) direntry.cmt_size, 0);
X         }
X
X         if (status != 0) {
X            if (status == 1) {
X               memerr();
X            } else
X               if (status == 2 || status == 3) {
X                  prterror ('F', disk_full);
X                  printf (partial_msg, temp_file);
X                  exit (1);
X               } else
X                  prterror ('f', internal_error);
X         } else {
X            if (latest_date < direntry.date ||
X                     (latest_date == direntry.date &&
X                           latest_time < direntry.time))  {
X               latest_date = direntry.date;
X               latest_time = direntry.time;
X            }
X         }
X         direntry.next = tell (new_han);
X         lseek (new_han, new_dir_pos, 0);    /* position to write direntry */
X
X         break_hit = 0;
X#ifndef NOSIGNAL
X         oldsignal = signal (SIGINT, SIG_IGN);
X         if (oldsignal != SIG_IGN)
X            signal (SIGINT, handle_break);
X#endif
X
X         if (wr_dir (&direntry, new_han) != -1 &&
X            write (new_han, file_leader, SIZ_FLDR) != -1) {
X#ifdef QUIETPACK
X            /* prterror ('M', "."); */ ;
X#else
X            prterror ('M', "moved\n");
X#endif
X         } else
X            prterror ('f', "Write to temporary packed archive %s failed.\n", temp_file);
X#ifndef NOSIGNAL
X         signal (SIGINT, oldsignal);
X#endif
X         if (break_hit)
X            exit (1);
X
X         lseek (new_han, direntry.next, 0);  /* back to end of new archive */
X      }  /* end if (lseek ... */
X   } /* end if (!direntry.deleted) */
X
Xfseek (zoo_file, next_ptr, 0);   /* ..seek to next dir entry */
X} /* end while */
X
Xfclose (zoo_file);
X
X/* write a final null entry */
Xwritenull (new_han, MAXDIRSIZE);
X
X#ifdef NIXTIME
Xclose (new_han);
Xsetutime (temp_file, latest_date, latest_time);
X#else
Xsettime (new_han, latest_date, latest_time);    /* adjust its time */
Xclose (new_han);
X#endif
X
X/* Important note:  At this point, it is assumed that the archive was
X   packed and written to a new file without error.  If control reaches
X   here without the new archive having been written properly, then
X   loss of data due to deletion of the original file could occur.  In
X   other words, if something went wrong, execution MUST NOT reach here. */
X
Xif (extcount == 0) {
X   unlink (temp_file);
X   prterror ('m', "No files moved.\n");
X} else {
X   char new_name[FNAMESIZE];
X   /* (a) if user requested, delete original, else rename it to
X   *.bak.  (b) rename temp file to same base name as zoo_file. */
X
X#ifdef QUIETPACK
X   /* prterror('M', "\n"); */
X#endif
X
X   unlink (backup_name);    /* remove any previous backup in any case */
X   if (nobackup)
X      unlink (zoo_path);
X   else
X      chname (backup_name, zoo_path);
X
X	/* if we are packing into current directory, we will rename temp file
X		to same basename but without the preceding pathname */
X	if (curr_dir)
X		zoo_path = nameptr (zoo_path);		/* strip pathname */
X
X   if (chname (zoo_path, temp_file)) {
X      prterror ('w', "Renaming error.  Packed archive is now in %s.\n", temp_file);
X      exit (1);
X   }
X} /* end if */
X
X} /* end zoopack() */
X
X
X/* handle_break() */
X/* Sets break_hit to 1 when called */
Xint handle_break()
X{
X#ifndef NOSIGNAL
X   signal (SIGINT, SIG_IGN);     /* ignore future control ^Cs for now */
X   break_hit = 1;
X#endif
X}
X
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