/*--------------------------------------------------------------------------*/
/* Yet another semi-useful utility: REDATE *.PAK                            */
/* Sets the file time and date for the output of NoGate's PAK.EXE files to  */
/* the time and date of newest member file in a PAK archive.                */
/*                                                                          */
/* If you break it, you can keep both parts. This just fixes a small hassle */
/* for people converting from SEA ARC format to NoGate's PAK format.        */
/*                                                                          */
/* This program was written in Turbo C 2.0. The command line for TCC would  */
/* be something like:                                                       */
/* tcc -v- -f- -DTURBOC -K -G -Z -d -mt -lt redate.c                        */
/* For Microsoft C 5.1 try this:                                            */
/* cl /Ox redate.c                                                          */
/*                                                                          */
/* Copyright 1989, Doug Boone. FidoNet 119/5                                */
/*                                                                          */
/* 4-16-89 Added support for ZOO and LZH files. Already have ZIP/PAK/ARC    */
/* files covered.                                                           */
/*--------------------------------------------------------------------------*/


#include    <stdio.h>
#include    <string.h>
#include    <ctype.h>
#include    <time.h>
#include	<dos.h>
#ifdef TURBOC
#include	<dir.h>
#endif
#include    <io.h>
#include    <fcntl.h>
#include    <dos.h>
#include    <sys\types.h>
#include    <sys\stat.h>
/* You don't need everything in archdr.h, but I don't want to trim it. */

#include	"archdr.h"


unsigned    int     mbrtime;
unsigned    int     mbrdate;

main(int argc, char *argv[])
{
    int     i;
    int     done;
#ifdef TURBOC
    struct  ffblk   ffblk;
#else
    struct  find_t  cfile;
#endif
	char    name[80];
    int     infile;		/* file handle */
	char    *firstchar;
	char	apath[80];
	char	*result;
    int     success;
	union	REGS	regs;

    if (argc < 2) {
		printf ("\nFixes the date for PAK/ARC/ZIP/ZOO/LZH files\n\n");
        exit(1);
		}
	firstchar = (char *) malloc(1);

	for (i=1; i<argc; i++) {
		strcpy(apath,argv[i]);
		result = strrchr(apath,'\\');
		if (result != NULL)
			*++result = '\0';
		else {
			result = strrchr(apath,':');
			if (result !=NULL)
				*++result = '\0';
			else
				apath[0] = '\0';
			}
		if (strncmp(argv[i],".",1)==0)
			strcpy(argv[i],"*.*");
#ifdef TURBOC
        done = findfirst(argv[i],&ffblk,0);
#else
        done = _dos_findfirst(argv[i],_A_NORMAL,&cfile);
#endif
		while (done == 0) {
			strcpy(name,apath);
#ifdef TURBOC
            strcat(name,ffblk.ff_name);
#else
            strcat(name,cfile.name);
#endif
			printf("Resetting file date on %s",name);
            infile = open(name,O_RDONLY|O_BINARY);
            if (infile > 0)
				success = read(infile,firstchar,1);
			lseek(infile,0L,SEEK_SET);
			firstchar[0] = toupper(firstchar[0]);
			mbrtime = 0;
			mbrdate = 0;
            switch(firstchar[0]) {
                case 0x1a:  success = checkpak(infile); break;
				case 'P':   success = checkzip(infile); break;
                case 'Z':   success = checkzoo(infile); break;
                default :   success = checklzh(infile); break;
                }
            if (success<0)
                printf("\n%s Not an archive file\n\n",name);
			else {
				regs.h.ah = 0x57;
				regs.h.al = 0x01;
				regs.x.bx = infile;
				regs.x.cx = mbrtime;
				regs.x.dx = mbrdate;
				int86(0x21,&regs,&regs);
    			printf(" to %2d/%02d/%02d  %02d:%02d:%02d\n",
				    ((mbrdate >> MONTH_SHIFT) & MONTH_MASK),
                    (mbrdate & DAY_MASK),
				    ((mbrdate >> YEAR_SHIFT) + DOS_EPOCH),
                    ((mbrtime >> 11) & 0x1f),
				    ((mbrtime >> 5) & 0x3f),
                    (mbrtime &0x1f)*2);
				}
            close(infile);
#ifdef TURBOC
            done = findnext(&ffblk);
#else
            done = _dos_findnext(&cfile);
#endif
            }		/* end of findfirst/findnext loop */
		}		/* end of for loop */
	free(firstchar);
	exit(0);
}


/* ====================================================================
 * start of list arc contents processing
 * ====================================================================
 */
int checkpak(int arc)		/* list files in archive */
{
	struct 	heads *hdr;		/* header data */
	char	*ver = " ";
    long    new_pos;
    char    method[11];


    hdr = (struct heads *) malloc(sizeof(struct heads));

	lseek(arc,1L,SEEK_SET);
	read(arc,ver,1);
	while (*ver > 0 && *ver < 11) {

		read(arc,hdr,sizeof(struct heads));
        if (mbrdate < hdr->mbrdate) {
            mbrdate = hdr->mbrdate;
            mbrtime = hdr->mbrtime;
            }
        if (mbrdate == hdr->mbrdate &&
            mbrtime < hdr->mbrtime)
            mbrtime = hdr->mbrtime;

		lseek(arc,hdr->mbrsize+1L,SEEK_CUR);
		read(arc,ver,1);
        };		/* End of while loop */
	free(hdr);
    return(0);
}

checkzip(int infile)
{
    struct  ID_Hdr          *ID;
    struct  Local_Hdr       *local;
    int     handle;
	int		check;


    ID = (struct ID_Hdr *) malloc(sizeof(struct ID_Hdr));
	local = (struct Local_Hdr *) malloc(sizeof(struct Local_Hdr));
	lseek(infile,0,SEEK_SET);
    do {
        check = read(infile,(void *)ID,sizeof(struct ID_Hdr));
        if (ID->Head_Type == LOCAL_HEADER) {
			if ((check = read(infile,(void *)local,sizeof(struct Local_Hdr))) != -1) {
                if (mbrdate < local->mod_date) {
                    mbrdate = local->mod_date;
                    mbrtime = local->mod_time;
                    }
                if (mbrdate == local->mod_date &&
					mbrtime < local->mod_time)
                    mbrtime = local->mod_time;

				lseek(infile,local->size_now+((long)(local->name_length + local->Xfield_length)),SEEK_CUR);
                }		/* End of one entry */
			}		/* End of grabbing local directory entries */
		else
			check = 0;
        } while(check >0 && !eof(infile));		/* End of file */
	free(ID);
	free(local);
    return(0);
}

/* Handle a ZOO archive */

int checkzoo(int fhandle)
{
	struct	zoo_header	*main_head;
	struct	direntry	*one_head;
	int 	result;

	main_head = (struct zoo_header *) malloc(sizeof(struct zoo_header));
	one_head = (struct direntry *) malloc(sizeof(struct direntry));

	result = read(fhandle,(void *)main_head,sizeof(struct zoo_header));
	if ((strnicmp(main_head->text,"ZOO",3)) != 0) {
        free(main_head);
        free(one_head);
		return(-1);
		}
	lseek(fhandle,main_head->zoo_start,SEEK_SET);
	result = read(fhandle,(void *)one_head,sizeof(struct direntry));
	do {
		if (result == sizeof(struct direntry)) {
                if (mbrdate < one_head->date) {
                    mbrdate = one_head->date;
                    mbrtime = one_head->time;
                    }
                if (mbrdate == one_head->date &&
					mbrtime < one_head->time)
                    mbrtime = one_head->time;

			lseek(fhandle,one_head->next,SEEK_SET);
			}
		result = read(fhandle,one_head,sizeof(struct direntry));
		} while ((one_head->offset != 0L) &&
			(result == sizeof(struct direntry)));
    free(one_head);
	free(main_head);
    return(0);
}


checklzh(int handle)
{
    struct  Lharc_Hdr   *local;
	int		check;

    local = (struct Lharc_Hdr *) malloc(sizeof(struct Lharc_Hdr));

	if ((check = read(handle,(void *)local,sizeof(struct Lharc_Hdr))) ==
		sizeof(struct Lharc_Hdr)) {
			if (!((strncmp(local->type,"-lh",3) == 0) &&
				(local->type[4] == '-'))) {
				free(local);
				return(-1);
				}
			}
	else {
		free(local);
		return(-1);
		}
    do {
		if (mbrdate < local->date) {
			mbrdate = local->date;
			mbrtime = local->time;
			}
		if (mbrdate == local->date &&
			mbrtime < local->time)
			mbrtime = local->time;

		lseek(handle,local->size_now+local->name_len+2L,SEEK_CUR);
		check = read(handle,(void *)local,sizeof(struct Lharc_Hdr));
		} while(check >1 && !eof(handle));		/* End of file */
	free(local);
	return(0);
}




