/* zoodel.c */
/*
Copyright (C) 1986 Rahul Dhesi -- All rights reserved
*/
#include "options.h"
/* Deletes or undeletes entries from an archive.  choice=1 requests
   deletion and choice=0 requests undeletion. */
#include "portable.h"
#include <stdio.h>
#include "various.h" /* may not be needed */
#include "zoo.h"
#include "zoofns.h"
#include "errors.i"

#ifndef NOSIGNAL
#include <signal.h>
#endif

extern int quiet;

void zoodel (zoo_path, option, choice)
char *zoo_path;
char *option;
int choice;
{
#ifndef NOSIGNAL
   int (*oldsignal)();        /* to save previous SIGINT handler */
#endif
   int delcount = 0;          /* how many entries we [un]deleted */
   char matchname[PATHSIZE];  /* will hold full pathname */
   register FILE *zoo_file;
   struct zoo_header zoo_header;
   struct direntry direntry;
   unsigned int latest_date = 0;      /* so we can set time of archive later */
   unsigned int latest_time = 0;
   int pack = 0;              /* pack after deletion? */
   int file_deleted = 0;      /* any files deleted? */
   int one = 0;               /* del/undel one file only */
   int done;                  /* loop control */   
while (*(++option)) {
   switch (*option) {
      case 'P': pack++; break;            /* pack after adding */
      case 'q': quiet++; break;           /* be quiet */
      case '1': one++; break;             /* del or undel only one file */
      default:
         prterror ('f', inv_option, *option);
   }
} /* end while */

   /* Open archive for read/write/binary access.  It must already exist */
   if ((zoo_file = fopen (zoo_path, FRWSTR)) == NULL) {
      prterror ('f', could_not_open, zoo_path);
   }
   
   /* read archive header */
   frd_zooh (&zoo_header, zoo_file);
   /* fread ((char *) &zoo_header, sizeof(zoo_header), 1, zoo_file); */
   if ((zoo_header.zoo_start + zoo_header.zoo_minus) != 0L)
      prterror ('f', failed_consistency);
   fseek (zoo_file, zoo_header.zoo_start, 0); /* seek to where data begins */
   
   done = 0;            /* loop not done yet */
   /* Go into loop deleting requested entries */
   while (1) {
      long this_dir_offset;
      this_dir_offset = ftell (zoo_file);    /* save pos'n of this dir entry */
      frd_dir (&direntry, zoo_file);
      /* fread ((char *) &direntry, sizeof (direntry), 1, zoo_file); */
      if (direntry.zoo_tag != ZOO_TAG) {
         prterror ('f', bad_directory);
      }
      if (direntry.next == 0L) {                /* END OF CHAIN */
         break;                                 /* EXIT on end of chain */
      }
      
      /* Now [un]delete this entry if it isn't already [un]deleted and 
         if filename matches.  WARNING: convention of choice=1 for
         deleted entry must be same as in direntry definition in zoo.h */
   
      /* Test for "done" so if "one" option requested, [un]del only 1 file */
      /* But we go through the whole archive to adjust archive time */

      combine (matchname,
                direntry.dirlen > 0 ? direntry.dirname : "",
               (direntry.namlen > 0) ? direntry.lfname : direntry.fname
              );

      if (!done && direntry.deleted != choice && 
                                             needed(matchname)) {
         prterror ('m', "%-14s -- ", matchname);
         delcount++;
         direntry.deleted = choice;
         if (choice) 
            file_deleted++;      /* remember if any files actually deleted */

         fseek (zoo_file, this_dir_offset, 0);

#ifndef NOSIGNAL
         oldsignal = signal (SIGINT, SIG_IGN);  /* disable ^C for write */
#endif
         if (fwr_dir (&direntry, zoo_file) == -1)
         /* if (fwrite ((char *) &direntry, sizeof(direntry), 1, zoo_file) < 1) */
            prterror ('f', "Could not write to archive\n");
#ifndef NOSIGNAL
         signal (SIGINT, oldsignal);
#endif
         prterror ('M', choice ? "deleted\n" : "undeleted\n");
         if (one)
            done = 1;            /* if 1 option, done after 1 file */
      }

      /* remember most recent date and time if entry is not deleted */
      if (!direntry.deleted)
         if (direntry.date > latest_date ||
            (direntry.date == latest_date && direntry.time > latest_time)) {
               latest_date = direntry.date;
               latest_time = direntry.time;
         }
      fseek (zoo_file, direntry.next, 0); /* ..seek to next dir entry */
   } /* endwhile */

   if (!delcount)
      printf ("Zoo:  No files matched.\n");
   else {
#ifdef NIXTIME
      fclose (zoo_file);
      setutime (zoo_path, latest_date, latest_time);
#else
      fflush (zoo_file);         /* superstition:  might help time stamp */
      settime (fileno(zoo_file), latest_date, latest_time);
#endif
   }

#ifndef NIXTIME
fclose (zoo_file);
#endif

if (file_deleted && pack) {   /* pack if files were deleted and user asked */
   prterror ('M', "-----\nNow packing...\n");
   zoopack (zoo_path, "PP");
}

}
