/*************************************************************
* Give a directory of an ADAM disk
**************************************************************
* 1.00	12/1/94	Chris Braymen	Creation under Borland C 3.1
**************************************************************/

#define TRUE	1
#define FALSE 	0
#define BUFSIZE		1024

#define	BDRESET	       	0x00
#define	BDSTATUS       	0x01
#define	BDREAD	       	0x02
#define	BDWRITE	       	0x03
#define	BDVERIFY       	0x04
#define	BDFORMAT       	0x05

#define	FLOPPY1	       	0x00
#define	HEAD0	       		0x00
#define 	HEAD1					0x01
#define	ONESECTOR			0x01



#include	<stdio.h>
#include <stdlib.h>
#include <string.h>
#include	<bios.h>
#include	<ctype.h>
#include	"adamfcb.h"


#define MAX_FCB	8*NUM_FCB_IN_BLOCK   /* maximum # of directory entries */

unsigned char	buffer[BUFSIZE];
struct 	EOS_FCB	myDir[MAX_FCB];
char		deletedFlag=FALSE;
char		longFlag=FALSE;

char version[] = "v1.00";

/*******************
* Prototypes
********************/
int  processArgs(int,char**);
int  readDirectory(void);
int  verifyEOS(unsigned char*);
void showNames(void);
void showFCB(int);
void showVol(void);
void showShort(int);
void showLong(int);
void showFlags(unsigned char);
void showHole(int);

#include	"readblk.c"

int main(argv,argc)
	int	argv;
	char	*argc[];
{
	int	block;

	if(!processArgs(argv,argc)) {
		printf("\nDIRADAM %s - Public Domain from Bonafide Systems\n\n",version);
		printf("Usage: DIRADAM <-d> <-l>\n\n");
		printf("-d option shows deleted files\n");
		printf("-l option shows directory long form\n\n");
		exit(0);
	}

	if(readDirectory()) {
		printf("Error reading directory\n");
		exit(0);
	}
	showNames();
	return 0;
}

/*******************************************************
* processArgs - process the command line args
*		sets globals longFlag and deletedFlag
********************************************************/
processArgs(argv,argc)
	int	argv;
	char	*argc[];
{
	int	i;
	int	exitFlag=TRUE;

	for(i=1;i<argv;i++) {
		if(*(argc[i])=='-') {
			switch(*(argc[i]+1)) {
				case 'L':
				case 'l':
					longFlag=TRUE;
					break;
				case 'D':
				case 'd':
					deletedFlag=TRUE;
					break;
				default:
					printf("Bad argument: %s\n",argc[i]);
					exitFlag=FALSE;
			} /* switch */
		} /* if "-" */
		else {
			printf("Bad argument: %s\n",argc[i]);
			exitFlag=FALSE;
		}
	}
	return(exitFlag);
}


/*****************************************************
* readDirectory
*	reads the EOS directory in the myDir array of FCB structures
*	returns 0 if OK, BIOSDISK error code if error
*****************************************************/
readDirectory()
{
   int	result,i,j,done=FALSE;
   int	fcbCount=0;
   int	dirBlocks,blockCount=1;
   char	*bytePtr;

   if(result=readBlock(blockCount,buffer))	/* read directory block */
		return(result);

   if((dirBlocks=verifyEOS(buffer))==0)		/* get directory size */
		return(0xFF);									/* our error code */
   if(dirBlocks * NUM_FCB_IN_BLOCK >  MAX_FCB)
		return(0xFF);

   while(!done) {
		if(blockCount>dirBlocks)               	/* no "Hole" found */
        	return(0xFF);
		if(result=readBlock(blockCount,buffer))	/* read directory block */
			return(result);								/* error return */
		for(i=0;i<NUM_FCB_IN_BLOCK;i++) {
			bytePtr=(char*)&myDir[fcbCount];
			for(j=0;j<FCB_SIZE;j++) {             /* copy FCB to structure */
				*bytePtr = buffer[i*FCB_SIZE+j];
				bytePtr++;
			}
			if (myDir[fcbCount].status==HOLE)
			done=TRUE;
			fcbCount++;
		}
		blockCount++;
   }
   return(0);
}

/****************************************************
* verifyEOS - Verifies that the media is an EOS media
*	      and returns the size of the directory.
*	      0 if Error.
*****************************************************/
int verifyEOS(buffer)
	unsigned char buffer[];
{
   int  Count;

   for (Count=0; Count<4; Count++) {
      if (DirChk[Count] != buffer[Count+13]) { 
			return(0);
      }
   }
   return(buffer[12] & 0x7F); /* mask out bit 7 */
}



/********************************************************
* showNames
********************************************************/
void showNames()
{
   int	i;

   showVol();   		    /* show volume info */

   if(longFlag) {
      printf("flags    t name       start alloc used  bytes date       \n");
      printf("-------- - ---------- ----- ----- ----- ----- -----------\n");
   }

   i=1;    /* start past VOLUME entry */
   while(i<MAX_FCB && myDir[i].status != HOLE) {
      if (myDir[i].status & DELETED) {            /* is file deleted? */
			if (deletedFlag) {
				showFCB(i);
			}
      }
      else {
			showFCB(i);
      }
      i++;
   }
   if(myDir[i].status==HOLE) {
		showHole(i);
   }
   else
		printf("\n\nNo 'HOLE' found!\n");
}


/************************************************
* showFCB
************************************************/
void showFCB(fcbNum)
   int     fcbNum;
{
   if (longFlag)
      showLong(fcbNum);
   else
      showShort(fcbNum);
}


/**************************************************
* showVol - displays volume information
**************************************************/
void showVol()
{
   int  Count;

   printf("\n\nVolume: ");
   for (Count=0; Count<11; Count++) {
      if(isprint(myDir[0].fileName[Count])) {
			putchar(myDir[0].fileName[Count]);
      }
   }
   printf(" %u",myDir[0].status & 0x7F); /* mask out bit 7 of dir size */
   printf(" %u\n\n",myDir[0].blocksAllocated);
}

/***************************************************
* showShort - prints short version of directory entry
****************************************************/
void showShort(Count)
   int	Count;
{
   char *strPtr;

   if (myDir[Count].status & LOCKED)
       putchar('*');
   else
       putchar(' ');

   /* find the end of the string */
   strPtr=myDir[Count].fileName;
   while(*strPtr != 3)
      strPtr++;

   *strPtr='\0';		     /* mark end of string */
   strPtr--;			     /* pt to last char in string */
   if (isprint(*strPtr)) {
      printf("%c ",*strPtr);
      *strPtr='\0';
   }
   else
      printf("  ");                  /* for strange types */

   printf("%-6u",myDir[Count].blocksAllocated);
   printf("%-11s",myDir[Count].fileName);
   if(myDir[Count].status & DELETED)
       printf("[deleted]");
   putchar('\n');		
}

/***************************************************
* showLong - prints long version of directory entry
**************************************************/
void showLong(Count)
   int	Count;
{
   char *strPtr;

   showFlags(myDir[Count].status);

   /* find the end of the string */
   strPtr=myDir[Count].fileName;
   while(*strPtr != 3)
      strPtr++;

   *strPtr='\0';		     /* mark end of string */
   strPtr--;			     /* pt to last char in string */
   if (isprint(*strPtr)) {
      printf("%c ",*strPtr);
      *strPtr='\0';
   }
   else
      printf("  ");                  /* for strange types */

   printf("%-11s",myDir[Count].fileName);
   printf("%-6ld",myDir[Count].startBlock);
   printf("%-6u",myDir[Count].blocksAllocated);
   printf("%-6u",myDir[Count].blocksUsed);
   printf("%-6u",myDir[Count].bytesInLastBlock);
   printf("%u/%u/%u\n", myDir[Count].date[0],
								myDir[Count].date[1],
								myDir[Count].date[2]);
}

/********************************************************
* showFlags
*********************************************************/
void showFlags(flags)
   unsigned char	flags;
{
   int	Count;

   Count=1;
   while(Count<=128) {
      switch(flags & Count) {
	    case 0: 				
	       putchar(' ');
	       break;
	    case 1:
	       putchar('e');		
	       break;
	    case 2:
	       putchar('x');
	       break;
	    case 4:
	       putchar('d');
	       break;
	    case 8:
	       putchar('s');
	       break;
	    case 16:
	       putchar('u');
	       break;
	    case 32:
	       putchar('r');
	       break;
	    case 64:
	       putchar('w');
	       break;
	    case 128:
	       putchar('*');
	       break;
	    default:
	       putchar('?');
	       break;
      }	/* switch */
      Count*=2;
   } /* while */
   putchar(' ');
}

/****************************************************
* showHole
****************************************************/					 	
void showHole(fcbNum)
   int fcbNum;
{
   printf("\nBlocks Used     : %ld",myDir[fcbNum].startBlock);
   printf("\nBlocks Free     : %u\n",myDir[fcbNum].blocksAllocated);
}

