/*
	PAKLIST.C	List contents of .PAK archive.

	Copyright 1988, Michael J. Housky
	Released to the Public Domain ... *no* rights reserved.
*/

/*
    Update log:
****************************************************************************
	Version 1.2, 10 September 1988: Released to public domain.
****************************************************************************
	Version 1.0, 27 August 1988: First version.
****************************************************************************
*/

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <io.h>

#include "dirfn.h"
#include "pakdefn.h"

#define BUF_SIZE	4096		/* constant buffer size */

/* ------------	Global data: */

FILE_TYPE	*file_list = NULL;	/* list of files (malloc'ed) */
unsigned char	pak_buf[BUF_SIZE];
pak_hdr		fhdr;
long		pakloc,paklen;


/*
	read_pakhdr:	Read header of .PAK member file
*/

int read_pakhdr( FILE* );

int read_pakhdr( fp )
    FILE	*fp;
{
    register int i;

    i = fgetc(fp);			/* get file marker */
    if ( i != PAK_MARK )		/* error if not correct */
	return -1;

    i = fread( (char*)&fhdr, 1, PAK_HDRLEN, fp );

    if ( i>=1 && fhdr.type==0 )
	return 1;			/* end of file mark seen */

    if ( i!=PAK_HDRLEN || fhdr.slen<0L || fhdr.olen<fhdr.slen )
	return -1;			/* invalid header seen */

    pakloc = ftell(fp);
    if ( pakloc+fhdr.slen > paklen )
	return -1;
    return 0;

} /* read_pakhdr */


/*
	pak_open:	Open a .PAK file, test for valid first header.
*/

FILE *pak_open( char* );

FILE *pak_open( fn )
    char	*fn;
{
    register int
		i;
    FILE	*fp;

/* Open the file: */

    fp = fopen( fn, "rb" );
    if ( fp==NULL )
    {
	printf("Can't open: %s\n",fn);
	return NULL;
    }
    paklen = filelength(fileno(fp));

/* Read the first header: */

    i = read_pakhdr(fp);
    if ( i )
    {
	printf("%s is not a .PAK archive\n",fn);
	fclose(fp);
	return NULL;
    }

    return fp;

} /* pak_open */    


/*
	pak_check:	Check one .PAK file by reading headers.
*/

int pak_check( char* );

int pak_check( fn )
    char	*fn;
{
    register	int i;
    FILE	*fp;
    long	l;
    static char	mo_tab [13] [4] =
    {
	"???",
	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    };

    printf("\nSearching ... %s\n\n", fn);

    fp = pak_open( fn );
    if ( fp == NULL )
	return -1;

    printf("Filename       Length     Size     Date        Time     CRC\n");
    printf("------------   ------    -----  -----------  --------  ----\n");
    /*      nnnnnnnn.xxx ssssssss ssssssss  dd-mmm-yyyy  hh:mm:ss  xxxx */
    while ( (l = pakloc+fhdr.slen) < paklen )
    {
	printf("%-12s %8ld %8ld  %2d-%3s-%02d  %2d:%02d:%02d  %04X\n",
		fhdr.fname,
		fhdr.olen,
		fhdr.slen,
		((fhdr.ddate>> 0) & 0x1F),
		mo_tab[((fhdr.ddate>> 5) & 0x0F)],
		((fhdr.ddate>> 9) & 0x7F)+1980,
		((fhdr.dtime>>11) & 0x1F),
		((fhdr.dtime>> 5) & 0x3F),
		((fhdr.dtime<< 1) & 0x3E),
		fhdr.crc);

	i = fseek( fp, l, SEEK_SET );
	if ( i )
	{
	    printf("seek error on %s\n",fn);
	    return -1;
	}

	i = read_pakhdr(fp);
	if ( i==1 )
	{				/* end of file seen */
	    fclose(fp);			/* close file */
	    return 0;			/* normal return */
	}
	if ( i<0 )
	{				/* invalid header seen */
	    fclose(fp);
	    printf("invalid header found\n");
	    return -1;
	}
	/* repeat if more files possible */
    }
    fclose(fp);
    printf("invalid file, possibly truncated\n");
    return -1;

} /* pak_check */


/*
	PAKLIST.C main program
*/


int main(int,char **);
int main( argc, argv )
    int		argc;
    char	**argv;
{
    register int
		i,j;
    long	len;
    int		addext;
    int		num_files;
    char	fpath[128];		/* full path\name of file */
    char	*fnptr;			/* location of filename in fpath */

/* First, identify self and examine paramter: */

    printf("\nPAKLIST v1.2\n");
    if ( argc<2 || !strcmp(argv[1],"?") )
    {
	printf("Usage: paklist <fname>\n");
	return 0;
    }

/* Parameter valid, find path and decide about default extension */

    strcpy( fpath, argv[1] );		/* extract path, find end */
    i = strlen(fpath);			/* index of last character */
    addext = 1;				/* presume no extension */
    while ( --i >= 0 )			/* search backward thru argument */
    {
	j = fpath[i];
	if ( j=='\\' || j==':' )
	    break;			/* colon or backslash ends search */
	if ( j=='.' )
	    addext = 0;			/* period found, no default */
    }
    fnptr = fpath+i+1;
    strupr(fpath);			/* uppercase for display */
    if ( addext )
	strcat(fpath,".PAK");		/* add default extension */

    num_files = get_files(fpath,0,&file_list);
    if (num_files < 0)
    {
	printf("Too many files: out of memory.\n");
	return(1);
    }

    if (num_files < 1)
    {
	printf("Cannot find file(s): %s\n",argv[1]);
	return(1);
    }

/* Now, list contents of each file: */

    for (i = 0; i < num_files; ++i)
    {
	strcpy( fnptr, file_list[i].filename );
	j = pak_check( fpath );
    }
    return 0;

} /* main */
