HFS library for AUX (part 2 of 2)

William Roberts liam at cs.qmc.ac.uk
Tue Aug 16 02:56:37 AEST 1988


#         This is a shar archive.
#         Remove everything above and including the cut line.
#         Then run the rest of the file through sh.
#--------cut--------cut--------cut--------cut--------cut--------
#! /bin/sh
#  shar:  Shell Archiver
#         Run the following with /bin/sh to create:
#             bstar.c
#             disc.h
#             extents.c
#             fcb.c
#             files.c
#             maccopy.c
#             macdir.h
#             macfile.h
#             rootblock.c
#             stat.c
#             undodefs.h
#             unixdir.c
# This archive created: Mon Aug 15 17:53:11 WET DST 1988
echo shar: extracting "bstar.c" '('8900 chars')'
if test -f bstar.c
then
    echo shar: will not overwrite existing file "bstar.c"
else
cat << \SHAR_EOF > bstar.c
#include "disc.h"

short GetNextByteFrom(Tree)
bstar *Tree;
{
	return Tree->BSfcb->AllocationBuffer[Tree->BytePos++];
}

short GetNext2BytesFrom(Tree)
bstar *Tree;
{
	short result;
	result=*(short *)(&Tree->BSfcb->AllocationBuffer[Tree->BytePos]);
	Tree->BytePos+=2;
	return result;
}

long GetNext4BytesFrom(Tree)
bstar *Tree;
{
	long result;
	result=*(long *)(&Tree->BSfcb->AllocationBuffer[Tree->BytePos]);
	Tree->BytePos+=4;
	return result;
}

SkipNextNBytesFrom(Distance,Tree)
int     Distance;
bstar   *Tree;
{
	Tree->BytePos+=Distance;
}

		/* Tree Start Record - go to record 'n' in current block */

void TreeStartRecord(RecordNumber,Tree)
bstar *Tree;
short RecordNumber;
{
	if (RecordNumber>=Tree->NDNRecs) {
		printf("bstar-Bad directory record access number\n");
		exit(-1);
	}
	Tree->CurrentRecordNumber=RecordNumber;
	Tree->BytePos=Tree->BSfcb->DeviceInfo.DRALBLKSIZ-(2*(RecordNumber+1));
	Tree->BytePos=GetNext2BytesFrom(Tree);
#ifdef DEBUGBSTAR
	printf("bstar-Record %d at %3d  :",RecordNumber,Tree->BytePos);
#endif
}



void ReadBStarBlock(BlockNumber,Btree)
long BlockNumber;
bstar *Btree;
{
	GotoBlock(Btree->BSfcb,BlockNumber);
	GetAllocationBlock(Btree->BSfcb);

#ifdef DEBUGBSTAR
	printf("bstar-Block %d read.\n",BlockNumber);
#endif

	Btree->BytePos=0;
	Btree->CurrentRecordNumber=0;
	Btree->CurrentSearchBlock=BlockNumber;

	Btree->NDFLink=GetNext4BytesFrom(Btree);
	Btree->NDBLink=GetNext4BytesFrom(Btree);
	Btree->NDType=GetNextByteFrom(Btree);
	Btree->NDLevel=GetNextByteFrom(Btree);
	Btree->NDNRecs=GetNext2BytesFrom(Btree);
}





void MoveToNextDirEntry(Btree)
bstar *Btree;
{
	Btree->CurrentRecordNumber++;
	if (Btree->CurrentRecordNumber >= Btree->NDNRecs) {
		if (Btree->NDFLink==0) {
				Btree->RecordFound=NOTFOUND;
				return;
		}
		ReadBStarBlock(Btree->NDFLink,Btree);
	}
}

			/* cache for device/root block number */
static  char    LastDeviceName[100];
static  int     LastRootBlockNumber;


int GetRootBlockNumber(devicename,dirp)
bstar   *dirp;
{
	int     block=0;
	int     found=9999;

	if (strcmp(devicename,LastDeviceName)==0)
		return LastRootBlockNumber;

	while   (found!=0) {
		ReadBStarBlock(++block,dirp);
		found=dirp->NDFLink+dirp->NDBLink;
		if (dirp->NDLevel==0) found=9999;       /* not found if unused node */
	}
#ifdef DEBUGBSTAR
	printf("bstar-ROOT-BLOCK-LOCATED AT %d  level %d\n",block,dirp->NDLevel);
#endif

	strcpy(LastDeviceName,devicename);
	LastRootBlockNumber=block;
					/* root node is the             */
	return  block;                  /* only single block in level   */
}

long ReadLinkNode(dirp)
bstar *dirp;
{
	long    pid;
	GetNext2BytesFrom(dirp);
	pid=GetNext4BytesFrom(dirp);
#ifdef DEBUGBSTAR
	printf("bstar-ReadLinkNode pid %d - %s\n",pid,
		(char *)(&dirp->BSfcb->AllocationBuffer[dirp->BytePos +1]) );
#endif
	SkipNextNBytesFrom(32,dirp);
	dirp->Pointer=GetNext4BytesFrom(dirp);
	SkipNextNBytesFrom((-36),dirp); /* move pointer to name part */
	return pid;
}

int     CheckNodeName(name,dirp) /* return -1,0,1 if name < = > nodename */
char *name;
bstar *dirp;
{
int     c,byte,nbyte;
int     isresource=0;

	SkipNextNBytesFrom(1,dirp); /* skip name length */
	if (name[0]=='%') isresource=1; /* skip '%'in name */

	for (c=0;c<31;c++) {
		byte=GetNextByteFrom(dirp);
		nbyte=name[c+isresource];

		if (byte>='a' && byte<='z') byte-=32;
		if (nbyte>='a' && nbyte<='z') nbyte-=32;

		if (nbyte=='?') return (-1);

		if (nbyte<byte) return (-1);
		if (nbyte>byte) return (1);
		if (byte=='\0') return (0);
	}
	return 1;
}



void FindFileNumber(Number,name,dirp)
long    Number;
char    *name;
bstar   *dirp;
{
	int     record;
	int     block=(-1);
	long    NodeKey;

#ifdef DEBUGBSTAR
	printf("bstar-FindFileNumber %4d %s\n",Number,name);
#endif
	ReadBStarBlock(dirp->RootBlockNumber,dirp);
	dirp->RecordFound=FOUND;
	while (dirp->NDLevel > 1) {
		record=0;
		block=(-1);
		do {
			if (record>=dirp->NDNRecs) {
				if (block<1) {
					dirp->RecordFound=NOTFOUND;
					return;
				}
				ReadBStarBlock(block,dirp);
				record=(-1);
			} else {
				TreeStartRecord(record,dirp);
				if ((NodeKey=ReadLinkNode(dirp)) > Number) {
					if (block<1) {
						dirp->RecordFound=NOTFOUND;
						return;
					}
					ReadBStarBlock(block,dirp);
					record=(-1);
				} else
				if (NodeKey==Number) {
					if (CheckNodeName(name,dirp)<0) {
						/* nodename>name */
						if (block<1) {
						  dirp->RecordFound=NOTFOUND;
						  return;
						}
						ReadBStarBlock(block,dirp);
						record=(-1);
					} else {
						block=dirp->Pointer;
						record++;
					}
				} else {
					block=dirp->Pointer;
					record++;
				}
			}
		} while (record>0);
	}

		/* now at leaf node level, so skip to PID>=Number */

	for (TreeStartRecord(0,dirp);ReadCatTreeEntry(dirp)<Number;) {
		MoveToNextDirEntry(dirp);
		TreeStartRecord(dirp->CurrentRecordNumber,dirp);
	}
}





/* ********************************************************************************
 * ***                  There now follows the file entry readers                ***
 * ******************************************************************************** */



ReadDirInfo(Tree)
bstar *Tree;
{
	SkipNextNBytesFrom(4,Tree);
	Tree->DirEntry.d_fileno=GetNext4BytesFrom(Tree);
	Tree->ctime=MacTimeToUnixTime(GetNext4BytesFrom(Tree));
	Tree->mtime=MacTimeToUnixTime(GetNext4BytesFrom(Tree));
	Tree->atime=MacTimeToUnixTime(GetNext4BytesFrom(Tree));
	Tree->FileLength=512;
}

ReadFileInfo(Tree)
bstar *Tree;
{
long    LengthR,LengthD;
long    EStart,ELength;
char    tempname[32];
int     c;

	SkipNextNBytesFrom(1,Tree);             /* flags */
	SkipNextNBytesFrom(1,Tree);             /* file type */
	SkipNextNBytesFrom(16,Tree);            /* 16 bytes finder info */
	Tree->DirEntry.d_fileno=GetNext4BytesFrom(Tree);
	SkipNextNBytesFrom(2,Tree);
	LengthD=GetNext4BytesFrom(Tree);
	SkipNextNBytesFrom(4,Tree);
	SkipNextNBytesFrom(2,Tree);
	LengthR=GetNext4BytesFrom(Tree);
	SkipNextNBytesFrom(4,Tree);
	Tree->ctime=MacTimeToUnixTime(GetNext4BytesFrom(Tree));
	Tree->mtime=MacTimeToUnixTime(GetNext4BytesFrom(Tree));
	Tree->atime=MacTimeToUnixTime(GetNext4BytesFrom(Tree));
	SkipNextNBytesFrom(16,Tree);
	SkipNextNBytesFrom(2,Tree);

	/* now sort out for Resource or Data file */
			/* Entry with both is Data only */
			/* Resource program is considered else where */
	if (LengthD>0) {        /* data fork */
		Tree->FileLength=LengthD;
		for (c=0;c<3;c++) {
			EStart=GetNext2BytesFrom(Tree);
			ELength=GetNext2BytesFrom(Tree);
			SetExtent(&Tree->Extents[c],EStart,ELength);
		}
	}

	if (LengthR>0 && LengthD>0) { /* copy info to fake dir entry */
		CopyDirToFake(Tree);
	}

	if (LengthR>0) {        /* Resource fork */
		Tree->FileLength=LengthR;
/* This adds a '%' to the start of the name */
/* not realy needed, but there for compatability */
		strcpy(tempname,"%");
		strcat(tempname,Tree->DirEntry.d_name);
		strcpy(Tree->DirEntry.d_name,tempname);
		Tree->DirEntry.d_namlen++;

		SkipNextNBytesFrom(12,Tree);
		for (c=0;c<3;c++) {
			EStart=GetNext2BytesFrom(Tree);
			ELength=GetNext2BytesFrom(Tree);
			SetExtent(&Tree->Extents[c],EStart,ELength);
		}
	}
}

ReadLinkInfo(Tree)
bstar *Tree;
{
	SkipNextNBytesFrom(8,Tree);
	MakeUpDir(Tree,"..",GetNext4BytesFrom(Tree));

	CopyDirToFake(Tree);
	MakeUpDir(Tree,".",Tree->CurrentWorkingDirectory);
}

long ReadCatTreeEntry(Tree)
bstar *Tree;
{
	int     c;
	int     keylength;
	int     BytesToSkip;

	Tree->FakeType=0;
	keylength=GetNextByteFrom(Tree);
	GetNextByteFrom(Tree);          /* ignored byte */
	Tree->ParID=GetNext4BytesFrom(Tree);    /* parent ID*/

	Tree->DirEntry.d_namlen=GetNextByteFrom(Tree);
	for (c=0;c<Tree->DirEntry.d_namlen;c++)
		Tree->DirEntry.d_name[c]=GetNextByteFrom(Tree);
	Tree->DirEntry.d_name[c]=NULL;  /* end marker = NULL */

#ifdef DEBUGBSTAR
	printf("Name read = %s (pid=%d)\n",Tree->DirEntry.d_name,Tree->ParID);
#endif

	BytesToSkip=keylength-Tree->DirEntry.d_namlen-6;
	while (BytesToSkip-->0)
		GetNextByteFrom(Tree);
	if ((Tree->BytePos %2) != 0)
		GetNextByteFrom(Tree);  /* skip to even byte */

	Tree->FileType=GetNextByteFrom(Tree);
	SkipNextNBytesFrom(1,Tree);             /* ignore next byte */
	switch (Tree->FileType) {
		case 1: ReadDirInfo(Tree);break;
		case 2: ReadFileInfo(Tree);break;
		case 3: ReadLinkInfo(Tree);break;
		default : printf("bstar-ReadCatTreeEntry:Bad directory entry %d\n",Tree->FileType);
			exit(-1);               /* PROGRAM GONE WRONG or BAD DISC */
			break;
	}
	return Tree->ParID;
}


CopyDirToFake(Tree)
bstar *Tree;
{
int     c;

	for (c=0;c<3;c++)
		Tree->FakeExtents[c]=Tree->Extents[c];
	Tree->FakeLength=Tree->FileLength;
	Tree->FakeType=Tree->FileType;
	Tree->FakeDirEntry=Tree->DirEntry;
}

CopyDirFromFake(Tree)
bstar *Tree;
{
int     c;

	for (c=0;c<3;c++)
		Tree->Extents[c]=Tree->FakeExtents[c];
	Tree->FileLength=Tree->FakeLength;
	Tree->FileType=Tree->FakeType;
	Tree->DirEntry=Tree->FakeDirEntry;
	Tree->FakeType=0;
}

SHAR_EOF
if test 8900 -ne `wc -c < bstar.c`
then
    echo shar: error transmitting "bstar.c" '('should be 8900 chars')'
else
    echo bstar.c
fi
fi
echo shar: extracting "disc.h" '('3972 chars')'
if test -f disc.h
then
    echo shar: will not overwrite existing file "disc.h"
else
cat << \SHAR_EOF > disc.h
/*
 * A/UX HFS library. Version 1.0
 *
 * Copyright: Matthew Kempthorne-Ley-Edwards, August 1988
 *
 * for  Department of Computer Science
 *      Queen Mary College
 *      London  E1 4NS
 *      UK
 *
 * This software is provisional and carries no guarantee of fitness
 * for any purpose. It may be freely copied provided this copyright
 * message included in any such distribution. It may not be sold or
 * incorporated into any product without prior permission of both
 * the author and Queen Mary College.
 */

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <string.h>

#ifndef rewinddir
#include <sys/dir.h>
#endif
#ifndef S_IFMT
#include <sys/stat.h>
#endif


#define DEFDISCFILE "/dev/dsk/c0d0s16"


#define SECTORLENGTH 512

typedef struct extent {
	u_short Start;
	u_short Length;
	} extent ;

typedef struct device { /* Device info - read from first sector of device */
	char    DeviceName[100];
	int     RootBlockNumber;        /* Block number of root block   */
					/*      in cat tree     */
	int     DeviceFile;             /* File of open device  */
	int     DRALBLKSIZ; /* Allocation Block size ( bytes ) */
	int     DRALBLST;
	extent  DRCTEXTREC[3]; /* Cat tree file extents 0,1,2 */
	} device ;

/* The complete FCB can be made up from the DeviceName and FileIDs & Position in file */

typedef struct fcb {

	/* internal working info */
	device  DeviceInfo;     /* root sector & device info */
	extent  Extent[3];  /* 0,1,2 extents */

	/* current position in file handlers */
	int     CurrentExtentNumber;
	int     CurrentAllocationInExtent;
	int     CurrentPosInAllocation;
	u_char  *AllocationBuffer;
	int     CurrentAllocationInBuffer;
	long    CurrentPos;

	/* info that could be found from the above */
	int     StartBlock;             /* = fcb(ext[curext].start */
	int     AllocationBlockNumber;   /* = StartBlock+fcbCurAlinExt */

	int     FileID;
	int     DirID;
	long    LengthOfFile;

	} fcb ;

typedef struct bstar {

	fcb     *BSfcb;
	long    NDFLink;
	long    NDBLink;
	short   NDType;
	short   NDLevel;
	short   NDNRecs;

	int     CurrentSearchBlock;     /* used in OpenDir name lookup */
	short   RecordFound;
	long    Pointer;
	int     RootBlockNumber;

	int     CurrentRecordNumber;
	long    CurrentWorkingDirectory;
	int     DirEntryNumber;
	short   BytePos;

			/* info about dir entry */

	struct direct DirEntry;
	long    ParID;                  /* dir number of owning dir */
	short   FileType;               /* filetype number 0.1.2 */
	long    FileLength;
	long    mtime,ctime,atime;      /* times of modify,create,archive */

	extent  Extents[3];

			/* info about fake entry ( ie "." or resource part
			   that is not realy in the dir ) */

	short   FakeType;
	extent  FakeExtents[3];
	long    FakeLength;
	struct  direct  FakeDirEntry;

	} bstar;

#define MacTimeToUnixTime(x) x+((70*365+17)*24*60*60)


#define FOUND 1
#define NOTFOUND 0

/* fcb defs */
fcb *OpenFile(),*GetCatExtentFCB(),*OpenCatFile();

/* bstar defs */
short GetNextByteFrom();
short GetNext2BytesFrom();
long GetNext4BytesFrom();
void TreeStartRecord();
void ReadBStarBlock();
void AdvanceTreeSearch();
long ReadCatTreeEntry();

/* rootblock defs */
device OpenDeviceFile();

#define Unix_open(nam,mod,x)            open(nam,mod,x)
#define Unix_read(id,buf,len)           read(id,buf,len)
#define Unix_write(id,buf,len)          write(id,buf,len)
#define Unix_lseek(id,offset,otype)     lseek(id,offset,otype)
#define Unix_close(id)                  close(id)

#define Unix_FILE                       FILE
#define Unix_fopen(name,type)           fopen(name,type)
#define Unix_fseek(id,offset,ptype)     fseek(id,offset,ptype)
#define Unix_fread(buf,len,size,id)     fread(buf,len,size,id)
#define Unix_fwrite(buf,len,size,id)    fwrite(buf,len,size,id)
#define Unix_fclose(id)                 fclose(id)
#define Unix_rewind(id)                 rewind(id)
#define Unix_ftell(id)                  ftell(id)

SHAR_EOF
if test 3972 -ne `wc -c < disc.h`
then
    echo shar: error transmitting "disc.h" '('should be 3972 chars')'
else
    echo disc.h
fi
fi
echo shar: extracting "extents.c" '('4837 chars')'
if test -f extents.c
then
    echo shar: will not overwrite existing file "extents.c"
else
cat << \SHAR_EOF > extents.c
#include "disc.h"

ReadNAllocationBlocks(Number,BlockNumber,address,Device)
long BlockNumber;
char *address[];
device *Device;
{
#ifdef DEBUGEXTENTS
	printf("extents-ReadNAllocationBlocks %d\n",BlockNumber);
#endif
	ReadNSectors(Number,Device->DRALBLKSIZ/SECTORLENGTH*
	    (BlockNumber+Device->DRALBLST),address,Device->DeviceFile);
}

SetExtent(Extent,num1,num2) /* #### TO BE REMOVED ##### */
extent *Extent;
int num1,num2;
{
	Extent->Start=num1;
	Extent->Length=num2;
}

fcb *GetCatExtentFCB(DeviceName)
char *DeviceName;
{
fcb     *FileControlBlock;
device  Device;
extent  ex0,ex1,ex2;

	Device=OpenDeviceFile(DeviceName); /* Find whereabouts of CAT file */
	ex0=Device.DRCTEXTREC[0];
	ex1=Device.DRCTEXTREC[1];
	ex2=Device.DRCTEXTREC[2];
	CloseDeviceFile(Device);           /* Will be reopened in OpenFile */

	FileControlBlock=OpenFile(ex0,ex1,ex2,1,0,0,DeviceName);
	return FileControlBlock;
}

GetAllocationBlock(FileControlBlock)
fcb *FileControlBlock;
{

/*
	FileControlBlock->AllocationBlockNumber =
		FileControlBlock->Extent[FileControlBlock->CurrentExtentNumber].Start
		+ FileControlBlock->CurrentAllocationInExtent ;
*/

	if (FileControlBlock->AllocationBlockNumber !=
	  (FileControlBlock->CurrentAllocationInBuffer)) {
		ReadNAllocationBlocks(1,FileControlBlock->AllocationBlockNumber,
			FileControlBlock->AllocationBuffer,
			&FileControlBlock->DeviceInfo);
		FileControlBlock->CurrentAllocationInBuffer=FileControlBlock->
			AllocationBlockNumber;
	}
}

GetAllocationBlocks(Number,stream,address)
int Number;     /* Number of allocation blocks to read */
fcb *stream;    /* fcb for file */
char *address;  /* where to put data */
{
int     NumberDone;
int     StartBlock;

	StartBlock=stream->Extent[stream->CurrentExtentNumber].Start
		+ stream->CurrentAllocationInExtent;

	NumberDone=stream->Extent[stream->CurrentExtentNumber].Length
		  -stream->CurrentAllocationInExtent;
		/* NumberDone= all allocation blocks to end of extent */
	if (NumberDone>Number) NumberDone=Number;
		/* NumberDone= number of blocks to read */

	ReadNAllocationBlocks(NumberDone,StartBlock,address,&stream->DeviceInfo);
	return NumberDone;
		/* No positional pointers are changed */
}

/* ******************************************************** */
/*                   Readers for memory buffers             */
/* ******************************************************** */


AdvanceAllocation(FileControlBlock)
fcb *FileControlBlock;
{
	FileControlBlock->CurrentPosInAllocation=0;
	FileControlBlock->AllocationBlockNumber++;
	if (FileControlBlock->CurrentAllocationInExtent++ >=
	 FileControlBlock->Extent[FileControlBlock->CurrentExtentNumber].Length)
	{
		FileControlBlock->CurrentExtentNumber++;
		if (FileControlBlock->CurrentExtentNumber >2)
		{
			printf("**** File too fragmented error *****\n");
			exit(-1);
		}
	}
}


short GetNextByte(FileControlBlock)
fcb *FileControlBlock;
{
	int AllocationBlockNumber;
	int Number;
	short byte;

#ifdef DEBUGEXTENTS
	printf("extents-GetNextByte ..");
#endif

	if (FileControlBlock->CurrentPos >= FileControlBlock->LengthOfFile)
		return EOF;

	GetAllocationBlock(FileControlBlock);

	byte=(FileControlBlock->AllocationBuffer[
		FileControlBlock->CurrentPosInAllocation++]);

#ifdef DEBUGEXTENTS
	printf("%d got\n",byte);
#endif

	if (FileControlBlock->CurrentPosInAllocation >=
				 FileControlBlock->DeviceInfo.DRALBLKSIZ)
		AdvanceAllocation(FileControlBlock);

	FileControlBlock->CurrentPos++;
	return byte;
}


GetBlockOfBytes(ptr,NBytes,stream)
char    *ptr;
int     NBytes;
fcb     *stream;
{
int     ReturnValue;
int     bytes;
int     blocks;

	if (stream->CurrentPos >= stream->LengthOfFile)
		return 0;       /* EOF */

#ifdef DEBUGEXTENTS
	printf("extents- BLOCK READ\n");
#endif

	if (stream->LengthOfFile - stream->CurrentPos < NBytes )
		NBytes=stream->LengthOfFile-stream->CurrentPos;

	ReturnValue=NBytes;

	if (stream->CurrentPosInAllocation > 0) {

		/* Now read from Current pos to end of ABlock */

		GetAllocationBlock(stream);
		bytes=(stream->DeviceInfo.DRALBLKSIZ-stream->CurrentPosInAllocation);

		bcopy(stream->AllocationBuffer[stream->CurrentPosInAllocation],ptr,bytes);
		NBytes-=bytes;
		ptr+=bytes;

		AdvanceAllocation(stream);
	}

	while (NBytes>=stream->DeviceInfo.DRALBLKSIZ) {
		/* Now read entire blocks in */

		blocks=GetAllocationBlocks(NBytes/stream->
			DeviceInfo.DRALBLKSIZ,stream,ptr);
		NBytes-=blocks*stream->DeviceInfo.DRALBLKSIZ;
		ptr+=blocks*stream->DeviceInfo.DRALBLKSIZ;

		AdvanceAllocation(stream);
	}

	if (NBytes>0) {

		/* Now read NBytes in from block */

		GetAllocationBlock(stream);
		bcopy(stream->AllocationBuffer,ptr,NBytes);
		stream->CurrentPosInAllocation=NBytes;
	}

#ifdef DEBUGEXTENTS
	printf("extents- BLOCK READ, %d Bytes read\n",ReturnValue);
#endif
	stream->CurrentPos+=ReturnValue;
	return ReturnValue;
}


SHAR_EOF
if test 4837 -ne `wc -c < extents.c`
then
    echo shar: error transmitting "extents.c" '('should be 4837 chars')'
else
    echo extents.c
fi
fi
echo shar: extracting "fcb.c" '('2958 chars')'
if test -f fcb.c
then
    echo shar: will not overwrite existing file "fcb.c"
else
cat << \SHAR_EOF > fcb.c
#include "disc.h"
#include <malloc.h>

fcb *FCB_Open(ex0,ex1,ex2,DeviceName)
extent ex0,ex1,ex2;
char    *DeviceName;
{
	fcb *FileControlBlock;
	FileControlBlock=(fcb *)malloc(sizeof(fcb));
	if (FileControlBlock==NULL) {
		fprintf(stderr,"Out of memory\n");
		exit(-1);
	}

	FileControlBlock->DeviceInfo=OpenDeviceFile(DeviceName);

	FileControlBlock->Extent[0]=ex0;
	FileControlBlock->Extent[1]=ex1;
	FileControlBlock->Extent[2]=ex2;

	FileControlBlock->AllocationBlockNumber=0;
	FileControlBlock->StartBlock=ex0.Start;

	FileControlBlock->LengthOfFile= /* Is a Default = physical length */
		FileControlBlock->DeviceInfo.DRALBLKSIZ*(
		(FileControlBlock->Extent[0].Length) +
		(FileControlBlock->Extent[1].Length) +
		(FileControlBlock->Extent[2].Length) );

	FileControlBlock->CurrentExtentNumber=0;
	FileControlBlock->CurrentAllocationInExtent=0;
	FileControlBlock->CurrentPosInAllocation=0;
	FileControlBlock->CurrentPos=0;

	FileControlBlock->AllocationBuffer=
		(u_char *)malloc(FileControlBlock->DeviceInfo.DRALBLKSIZ);
	if (FileControlBlock->AllocationBuffer==NULL) {
		fprintf(stderr,"Out of memory\n");
		exit(-1);
	}

	FileControlBlock->CurrentAllocationInBuffer=0;

	return FileControlBlock;
}

FCB_Close(ControlBlock)
fcb *ControlBlock;
{
	free(ControlBlock);
}


fcb
*OpenFile(ex0,ex1,ex2,FileID,DirID,Length,DeviceName)
extent ex0,ex1,ex2;
int FileID,DirID;
long Length;
char *DeviceName;
{
	fcb *newfcb;
	newfcb=FCB_Open(ex0,ex1,ex2,DeviceName);
	newfcb->FileID=FileID;
	newfcb->DirID=DirID;
	newfcb->LengthOfFile=Length;
	return newfcb;
}

CloseFile(FileControlBlock)
fcb *FileControlBlock;
{
	CloseDeviceFile(FileControlBlock->DeviceInfo);
	FCB_Close(FileControlBlock);
}

fcb *OpenCatFile(DeviceName) /* #### should be # define */
char *DeviceName;
{
	return GetCatExtentFCB(DeviceName);
}

short ReadByte(FileControlBlock) /* ### should be # define */
fcb *FileControlBlock;
{
	return GetNextByte(FileControlBlock);
}

GotoBlock(FileCB,NewBlockNumber)
fcb *FileCB;
long NewBlockNumber;
{
int     NewExtentNumber=0;
int     BlockNumber=NewBlockNumber;

	while (BlockNumber>FileCB->Extent[NewExtentNumber].Length) {
		BlockNumber-=FileCB->Extent[NewExtentNumber].Length;
		NewExtentNumber++;

	}
	FileCB->CurrentExtentNumber=NewExtentNumber;
	FileCB->CurrentAllocationInExtent=BlockNumber;
	FileCB->StartBlock=FileCB->Extent[NewExtentNumber].Start;
	FileCB->AllocationBlockNumber=FileCB->StartBlock+BlockNumber;
}

GotoByte(FileCB,Position)
fcb *FileCB;
long Position;
{
	int NewBlockNumber;
	int NewExtentNumber=0;

	NewBlockNumber=Position/(FileCB->DeviceInfo.DRALBLKSIZ);

	GotoBlock(FileCB,NewBlockNumber);
	FileCB->CurrentPosInAllocation=Position % FileCB->DeviceInfo.DRALBLKSIZ;
	FileCB->CurrentPos=Position;
}

long GetPosition(FileCB)        /* #### should be # defines */
fcb *FileCB;
{
	return FileCB->CurrentPos;
}

long GetLength(FileCB)          /* #### should be # defines */
fcb *FileCB;
{
	return FileCB->LengthOfFile;
}


SHAR_EOF
if test 2958 -ne `wc -c < fcb.c`
then
    echo shar: error transmitting "fcb.c" '('should be 2958 chars')'
else
    echo fcb.c
fi
fi
echo shar: extracting "files.c" '('3512 chars')'
if test -f files.c
then
    echo shar: will not overwrite existing file "files.c"
else
cat << \SHAR_EOF > files.c
#include "macfile.h"
#include <errno.h>

#define MaxOpenFiles 20

/* *************** FILE returning file ops Open, Read, Seek ******************** */

Mac_FILE *Mac_fopen(FileName,AccessMode)
char	*FileName;
char	*AccessMode;
{
fcb	*OpenedFile;
DIR	*Dir;
char	Device[30];
char	DirDevice[32];
char	*NamePart;
int	c;

	if (strcmp(AccessMode,"r")!=0) return NULL;

	NamePart=GetDeviceNameFrom(FileName,Device);
	strcpy(DirDevice,Device);
	strcat(DirDevice,":/");

#ifdef DEBUGFILES
	printf("files-open device %s with name %s\n",Device,NamePart);
#endif
	Dir=Mac_opendir(DirDevice);
	if (LookUpFile(Dir,NamePart)==NOTFOUND) {
		Mac_closedir(Dir);
		return	NULL;
	}

	OpenedFile=OpenFile(Dir->Extents[0],Dir->Extents[1],Dir->Extents[2],
		Dir->DirEntry.d_fileno,Dir->CurrentWorkingDirectory,
		Dir->FileLength,Device);

	if (OpenedFile==NULL) return NULL;
#ifdef DEBUGFILES
	printf("files-fopen OK\n");
#endif

	return OpenedFile;
}

int Mac_fclose(MacFileRec)
Mac_FILE *MacFileRec;
{
	FCB_Close(MacFileRec);
	return 0;
}

int Mac_fseek(stream,offset,ptrname)
Mac_FILE *stream;
long offset;
int ptrname;
{
long	position;
	switch (ptrname) {
		case 0:	position=offset;break;
		case 1:	position=GetPosition(stream)+offset;break;
		case 2:	position=GetLength(stream)-offset;break;
	}
	if (position<0) position=0;
	if (position>GetLength(stream)) position=GetLength(stream);

	GotoByte(stream,position);
}

void Mac_rewind(stream)
Mac_FILE *stream;
{
	Mac_fseek(stream,0L,0);
}

long Mac_ftell(stream)
Mac_FILE *stream;
{
	return GetPosition(stream);

}

short Mac_getchar(MacFileRec)
Mac_FILE *MacFileRec;
{
	return	ReadByte(MacFileRec);
}

int Mac_fread(ptr,size,nitems,stream)
char	*ptr;
int	size,nitems;
Mac_FILE *stream;
{
	return GetBlockOfBytes(ptr,size*nitems,stream);
}


/*									 */
/* ************* NON file discripter open/read/lseek ******************* */
/*									 */


static	Mac_FILE	*Files[MaxOpenFiles];
static	int	FileNumber[MaxOpenFiles];
static  int	FilesToInit=99;

Mac_open(path,oflag,mode)
char	*path;
int	oflag,mode;
{
int	c;
Mac_FILE	*fil=NULL;

	if (FilesToInit != 0) {
		for (c=0;c<MaxOpenFiles;c++)
			FileNumber[c]=0; /* no file */
		FilesToInit=0;
	}
	if (oflag != O_RDONLY ) {
		errno=EROFS;
		return(-1);
	}
	for (c=0;(c<MaxOpenFiles && FileNumber[c]!=0);c++);
	if (c>=MaxOpenFiles) {
		errno=ENFILE;
		return(-1);
	}

	Files[c]=Mac_fopen(path,"r");

	if (Files[c]==NULL) {
		FileNumber[c]=0;
		errno=ENOENT;	/* file not found */
		return (-1);
	} else FileNumber[c]=Files[c]->FileID;


	return FileNumber[c];
}

int
Mac_read(filedes,buf,nbytes)
int filedes;
char *buf;
int nbytes;
{
Mac_FILE	*fil=NULL;
int	c;

	if (FilesToInit != 0) {
		errno=EBADF;
		return(-1);
	}

	for (c=0;c<MaxOpenFiles;c++) {
		if (FileNumber[c]==filedes) { 
			fil=Files[c];
			break;
		 }
	}

	if (fil==NULL) {
		errno=EBADF;
		return (-1);
	}
	return Mac_fread(buf,1,nbytes,fil);
}

Mac_lseek(filedes,offset,whence)
int filedes;
long offset;
int whence;
{
Mac_FILE	*fil=NULL;
int	c;

	if (FilesToInit != 0) {
		errno=EBADF;
		return(-1);
	}

	for (c=0;c<MaxOpenFiles;c++) {
		if (FileNumber[c]==filedes) fil=Files[c];
	}

	if (fil==NULL) {
		errno=EBADF;
		return (-1);
	}
	Mac_fseek(fil,offset,whence);
	return(0);

}

Mac_close(filedes)
int	filedes;
{
Mac_FILE	*fil=NULL;
int	c;

	if (FilesToInit != 0) {
		errno=EBADF;
		return(-1);
	}
	for (c=0;c<MaxOpenFiles;c++) {
		if (FileNumber[c]==filedes) fil=Files[c];
	}
	if (fil==NULL) {
		errno=EBADF;
		return (-1);
	}
	Mac_fclose(fil);
	return(0);
}



SHAR_EOF
if test 3512 -ne `wc -c < files.c`
then
    echo shar: error transmitting "files.c" '('should be 3512 chars')'
else
    echo files.c
fi
fi
echo shar: extracting "maccopy.c" '('839 chars')'
if test -f maccopy.c
then
    echo shar: will not overwrite existing file "maccopy.c"
else
cat << \SHAR_EOF > maccopy.c
#include "macfile.h"
#include "undodefs.h"

#include <malloc.h>

#define BUFSIZE 50000

main(argc,argv)
int	argc;
char	*argv[];
{
Unix_FILE	*outname;
Mac_FILE	*inname;
char		*Buffer;
int		bytes;

	if (argc!=3) {
		printf("Usage :%s <macname> <unixname>\n",argv[0]);
		exit(-1);
	}

	if ((inname=Mac_fopen(argv[1],"r"))== NULL ) {
		printf("%s not found on mac filestore\n",argv[1]);
		exit(-1);
	}	

	if ((outname=Unix_fopen(argv[2],"w"))==NULL) {
		printf("%s not writeable on unix filestore\n",argv[2]);
		Mac_fclose(inname);
		exit(-1);
	}	

	Buffer=malloc(BUFSIZE);
	if (Buffer==NULL) {
		printf("%s out of memory.\n",argv[0]);
		exit(-1);
	}

	while ((bytes=Mac_fread(Buffer,sizeof(*Buffer),BUFSIZE,inname))>0)
	{
		Unix_fwrite(Buffer,sizeof(*Buffer),bytes,outname);
	}

	Mac_fclose(inname);
	Unix_fclose(outname);

	free(Buffer);
}

SHAR_EOF
if test 839 -ne `wc -c < maccopy.c`
then
    echo shar: error transmitting "maccopy.c" '('should be 839 chars')'
else
    echo maccopy.c
fi
fi
echo shar: extracting "macdir.h" '('579 chars')'
if test -f macdir.h
then
    echo shar: will not overwrite existing file "macdir.h"
else
cat << \SHAR_EOF > macdir.h
#define stat Mac_stat
#define lstat Mac_stat

#include "disc.h"

#define DIR bstar
#define opendir(dirp)		Mac_opendir(dirp)
#define telldir(dirp)		Mac_telldir(dirp)
#define seekdir(dirp,pos)	Mac_seekdir(dirp,pos)
#undef rewinddir
#define rewinddir(dirp)		Mac_seekdir(dirp,(long)0)
#define Mac_rewinddir(dirp)	Mac_seekdir(dirp,(long)0)
#define closedir(dirp)		Mac_closedir(dirp)
#define readdir(dirp)		Mac_readdir(dirp)

extern	DIR	*Mac_opendir();
extern	struct direct *Mac_readdir();
extern	long	Mac_telldir();

extern	char	*GetPathNameFrom();
extern	char	*GetDeviceNameFrom();

SHAR_EOF
if test 579 -ne `wc -c < macdir.h`
then
    echo shar: error transmitting "macdir.h" '('should be 579 chars')'
else
    echo macdir.h
fi
fi
echo shar: extracting "macfile.h" '('568 chars')'
if test -f macfile.h
then
    echo shar: will not overwrite existing file "macfile.h"
else
cat << \SHAR_EOF > macfile.h
#include "macdir.h"

#define Mac_FILE fcb

Mac_FILE *Mac_fopen();
int	Mac_fclose();
int	Mac_fseek();
void	Mac_rewind();
long	Mac_ftell();
short	Mac_getchar();
int	Mac_fread();

#define open(nam,mod,x)		Mac_open(nam,mod,x)
#define read(id,buf,len)	Mac_read(id,buf,len)
#define lseek(id,offset,otype)	Mac_lseek(id,offset,otype)
#define close(id)		Mac_close(id)

#define fopen(name,type)	Mac_fopen(name,type)
#define fclose(id)		Mac_fclose(id)
#define fseek(id,offset,ptype)	Mac_fseek(id,offset,ptype)
#define rewind(id)		Mac_rewind(id)
#define ftell(id)		Mac_ftell(id)

SHAR_EOF
if test 568 -ne `wc -c < macfile.h`
then
    echo shar: error transmitting "macfile.h" '('should be 568 chars')'
else
    echo macfile.h
fi
fi
echo shar: extracting "rootblock.c" '('1624 chars')'
if test -f rootblock.c
then
    echo shar: will not overwrite existing file "rootblock.c"
else
cat << \SHAR_EOF > rootblock.c
#include "disc.h"

/* ***** routines for getting information from the root store **** */


/* ********** sector readers ********** */
/* 				sectors are read as a file
 *				of type device ( open/read/close )
 */

static char rootstore[SECTORLENGTH];	/* temp buffer for root sector */

device OpenDeviceFile(DeviceName)
char *DeviceName;	/* FileName of device - eg /dev/floppy0 */
{
device	Disc;
int	n;

#ifdef DEBUGUTILS
	printf("utils-File open on device %s\n",DeviceName);
#endif

	Disc.DeviceFile=Unix_open(DeviceName,O_RDONLY,0);
	if (Disc.DeviceFile<0) {
		fprintf(stderr,"Cant open device %s !\n",DeviceName);
		exit(-1);
	}
	Disc.RootBlockNumber= -1;	/* Unknown ######## */
	ReadNSectors(1,2,rootstore,Disc.DeviceFile);
	Disc.DRALBLKSIZ=*(long *)(&rootstore[20]);
	Disc.DRALBLST=*(short *)(&rootstore[28]);

	for (n=0;n<3;n++) {
		Disc.DRCTEXTREC[n]=*(extent *)(&rootstore[150+4*n]);
	}

	strcpy(Disc.DeviceName,DeviceName);
	return Disc;
}

CloseDeviceFile(Device)
device Device;
{
#ifdef DEBUGUTILS
	printf("utils-Device file closed\n");
#endif

	Unix_close(Device.DeviceFile);
}

ReadNSectors(NumberOfSectors,SectorNumber,BufferAddress,DiscFile)
int	NumberOfSectors;
int	SectorNumber;
char	*BufferAddress;
int	DiscFile;
{
#ifdef DEBUGUTILS
	printf("utils-Sector #%x read\n",SectorNumber);
#endif
	if (Unix_lseek(DiscFile,SECTORLENGTH*SectorNumber,0)<0) {
		fprintf(stderr,"Cant seek sector %d !\n",SectorNumber);
		exit(-1);
	}
	if (Unix_read(DiscFile,BufferAddress,NumberOfSectors*SECTORLENGTH)
	    <NumberOfSectors*SECTORLENGTH){ 
		fprintf(stderr,"Read fail on sector %d !\n",SectorNumber);
		exit(-1);
	}
}

SHAR_EOF
if test 1624 -ne `wc -c < rootblock.c`
then
    echo shar: error transmitting "rootblock.c" '('should be 1624 chars')'
else
    echo rootblock.c
fi
fi
echo shar: extracting "stat.c" '('1458 chars')'
if test -f stat.c
then
    echo shar: will not overwrite existing file "stat.c"
else
cat << \SHAR_EOF > stat.c
#include "macdir.h"

#define S_AREAD (S_IREAD | S_IREAD>>3 | S_IREAD>>6 )
#define S_AEXEC (S_IEXEC | S_IEXEC>>3 | S_IEXEC>>6 )

int Mac_stat(file,buffer)
char *file;
struct stat *buffer;
{
	DIR	*DirEnt;
	char	OpenDirName[30];

	file=GetDeviceNameFrom(file,OpenDirName);
	strcat(OpenDirName,":/");

#ifdef DEBUGSTAT
	printf("stat-file %s\n",file);
#endif
	DirEnt=Mac_opendir(OpenDirName);
	if (LookUpFile(DirEnt,file)==NOTFOUND) {
		Mac_closedir(DirEnt);
		return (-1);
	}

	buffer->st_ino		=DirEnt->DirEntry.d_fileno;
	buffer->st_dev		=DirEnt->BSfcb->DeviceInfo.DeviceFile;
	buffer->st_rdev		=DirEnt->CurrentWorkingDirectory;
	buffer->st_uid		=geteuid();	/* ### SHOULD CHECK NAME */
	buffer->st_gid		=getegid();	/* IN FINDER INFO ###### */
	buffer->st_ctime	=DirEnt->ctime;
	buffer->st_mtime	=DirEnt->mtime;
	buffer->st_atime	=DirEnt->atime;
	buffer->st_size		=DirEnt->FileLength;
	buffer->st_blksize	=DirEnt->BSfcb->DeviceInfo.DRALBLKSIZ;
	buffer->st_blocks	=(buffer->st_blksize-1+DirEnt->FileLength)
					/buffer->st_blksize;
	buffer->st_nlink	=1;

	switch (DirEnt->FileType) {
	case 1:
		buffer->st_mode	=S_IFDIR | S_AREAD | S_AEXEC;
		buffer->st_nlink=2; /* for . and parent */
		break;
	case 2:
		buffer->st_mode	=S_IFREG | S_AREAD;
		break;
			/* ###### should check executables ######## */
	default: printf("stat - bad file type on file %s\n",file);
	}
	Mac_closedir(DirEnt);
#ifdef DEBUGSTAT
	printf("stat-file %s done\n",file);
#endif
	return 0;
}

SHAR_EOF
if test 1458 -ne `wc -c < stat.c`
then
    echo shar: error transmitting "stat.c" '('should be 1458 chars')'
else
    echo stat.c
fi
fi
echo shar: extracting "undodefs.h" '('373 chars')'
if test -f undodefs.h
then
    echo shar: will not overwrite existing file "undodefs.h"
else
cat << \SHAR_EOF > undodefs.h
/* This MUST be included ONLY if access to the Mac & access to Unix are BOTH 
 * required, Then All open's etc MUST be prefixed with Mac_ or Unix_ 
 *		ie
 *		Mac_FILE* Mac_fopen()
 *	&	Unix_FILE* Unix_fopen()
 */


#undef open
#undef read
#undef write
#undef lseek
#undef close
#undef fopen
#undef fseek
#undef fread
#undef fwrite
#undef fclose
#undef rewind
#undef ftell
SHAR_EOF
if test 373 -ne `wc -c < undodefs.h`
then
    echo shar: error transmitting "undodefs.h" '('should be 373 chars')'
else
    echo undodefs.h
fi
fi
echo shar: extracting "unixdir.c" '('7345 chars')'
if test -f unixdir.c
then
    echo shar: will not overwrite existing file "unixdir.c"
else
cat << \SHAR_EOF > unixdir.c
#include "macdir.h"
#include <malloc.h>

#define MAXDEVICELEN 30

#define ROOTDIRNUMBER 2

/* ************************************************************ */
/*                   unix IO dir handlers                       */
/* ************************************************************ */

DIR *Mac_opendir(filename)
char *filename;
{
	int	isfound;
	char	DeviceName[MAXDEVICELEN];
	char	*dot=".";
	bstar	*DirTree=(bstar *)malloc(sizeof(bstar));

	if (DirTree==NULL) return NULL; /* out of mem */

		/* First get the device if given */

	filename=GetDeviceNameFrom(filename,DeviceName);
	if (*filename=='\0') filename=dot;

#ifdef DEBUGUNIXDIR
	printf("unixdir-OpenDir device '%s', file '%s'\n",DeviceName,filename);
#endif

		/* now open the device */

	DirTree->BSfcb=OpenCatFile(DeviceName);
	DirTree->RootBlockNumber=GetRootBlockNumber(DeviceName,DirTree);

		/* now set up open info */

	DirTree->DirEntry.d_reclen=sizeof(struct direct);
	DirTree->CurrentWorkingDirectory=ROOTDIRNUMBER;
	Mac_rewinddir(DirTree);

		/* now look up given dir name */

	isfound=LookUpFile(DirTree,filename);
	if (isfound==NOTFOUND) {
#ifdef DEBUGUNIXDIR
		printf("unixdir-LookUpFile %s not found\n",filename);
#endif
		CloseFile(DirTree->BSfcb);	/* dir not found */
		return NULL;
	}
	if (DirTree->FileType!=1) {
#ifdef DEBUGUNIXDIR
		printf("unixdir-LookUpFile %s not directory\n",filename);
#endif
		CloseFile(DirTree->BSfcb);	/* dir not found */
		return NULL;
	}
		/* Now set up info about found dir */

	DirTree->CurrentWorkingDirectory=DirTree->DirEntry.d_fileno; /* get subdir number */
	Mac_rewinddir(DirTree);

#ifdef DEBUGUNIXDIR
		printf("unixdir-OpenDir done.\n",filename);
#endif
	return	DirTree;
}

Mac_closedir(dirp)
DIR *dirp;
{
	CloseFile(dirp->BSfcb);
	free(dirp);
#ifdef DEBUGUNIXDIR
	printf("unixdir-Dir closed\n");
#endif
}


struct direct *Mac_readdir(dirp)		/* move on to next (or first) dir entry */
DIR *dirp;				/* ie read current entry         */
					/* and move on pointer is readOK */
{
	long	ParID;

					/* check to see if no more */
	if (dirp->RecordFound==NOTFOUND) return NULL;

				/* if fake entry, read that & null it */
	if (dirp->FakeType>0) {
		CopyDirFromFake(dirp);
		MoveToNextDirEntry(dirp);
	} else {
				/* Read current pointed to entry */
		TreeStartRecord(dirp->CurrentRecordNumber,dirp);
		ParID=ReadCatTreeEntry(dirp);

				/* now if PID<>ID ... no longer in dir */
		if (ParID!=dirp->CurrentWorkingDirectory)
			return NULL;
		if (dirp->FakeType==0) { 
			MoveToNextDirEntry(dirp);
		}
	}
					/* found an entry in this dir */
	dirp->DirEntryNumber++;		/* now move on counter to next dir */

#ifdef DEBUGUNIXDIR
	printf("unixdir-ReadDir found '%s'\n",dirp->DirEntry.d_name);
#endif

	return &(dirp->DirEntry);
}

long Mac_telldir(dirp)
DIR *dirp;
{
	return dirp->DirEntryNumber-1;	/* DirEntryNumber holds next number */
}

Mac_seekdir(dirp,loc)
DIR	*dirp;
long	loc;
{
	int c;
	char	*NullName="";
	if (loc==0 || loc<dirp->DirEntryNumber) { /* rewind */
		FindFileNumber(dirp->CurrentWorkingDirectory,NullName,dirp);
		dirp->FakeType=0;
	}
	for (c=0;c<loc-dirp->DirEntryNumber-1;c++) {
		if (Mac_readdir(dirp)==NULL) return;
	}
}


/* **************************************************************** */
/*                 Programs internal dir lookups                    */
/* **************************************************************** */


		/* GetDeviceNameFrom, strcpy device name from filename */
		/* Returns filename ( Everything after ':' */
char *GetDeviceNameFrom(filename,devicename)
char *filename,*devicename;
{
	int	c;
	char	*filenamepart=filename;
	char	*devicenamepart=devicename;
	for (c=0;(c<MAXDEVICELEN && *filenamepart!='\0');c++) {
		if (*filenamepart==':') {
			*devicenamepart='\0';
			return (++filenamepart);
		}
		*devicenamepart++=*filenamepart++;
	}
	strcpy(devicename,DEFDISCFILE);
	return filename;	/* no device specified */
}


/* HasItASlash - returns number of chars through string untill a '/' */
HasItASlash(filename)
char *filename;
{
	int c;
	for (c=0;c<MAXNAMLEN;c++) {
		if (filename[c]=='/') return (c+1);
		if (filename[c]=='\0') return 0;
	}	/* returns 0 if not found, or number of chars upto(inc) '/'   */
	fprintf(stderr,"unixdir-BAD FILENAME\n");
	exit(-1);
}

/* name1='/' or NULL terminated, name2=NULL terminated */
/*    rets name1 1 char after / */
char* CompareNames(name1,name2)
char *name1,*name2;
{
	for(;;) {
		while ((*name2=='/' && *name1=='/') || ( *name1=='?' && *name2!='\0')) {
			name1++;name2++; }

		if (*name1=='/' && *name2=='\0')
			return ++name1;
		if (*name1=='/') return NULL;
		if (*name1=='\0') return name1;
		if (*name2=='\0') return NULL;
		if (*name1++!=*name2++) return NULL;
	}
}


	/* StripPathNameFrom - get .../ from front of name */
	/*	returns new RHS of name & cwd changed in dirp*/
char *StripPathNameFrom(dirp,filename)
DIR *dirp;
char *filename;
{
	int	found=1;
	int	namelength;
	char	name[MAXNAMLEN];
	char	*names;
	struct direct	namestore,*dp;

	if (*filename=='/') {
		dirp->CurrentWorkingDirectory=ROOTDIRNUMBER;
		filename++;
	}

	if ((namelength=HasItASlash(filename))==0) return filename;

	/* ############# path CACHE check to be put in here ########### */

/* Name has a slash in it - so look up name up to slash to skip first bit of dir */

	strncpy(name,filename,namelength-1);
	name[namelength-1]='\0';
	FindFileNumber(dirp->CurrentWorkingDirectory,name,dirp);

#ifdef DEBUGUNIXDIR
	printf("looking for %s\n",filename);
#endif
	while (found>0) {
		dp=Mac_readdir(dirp);
		if (dp==NULL) return NULL;

		/* now compare file names */
		names=CompareNames(filename,dp->d_name);
		if (names!=NULL) 
		{
#ifdef DEBUGUNIXDIR
		printf("unixdir-match found on %s\n",filename);
#endif
			if (dirp->FileType!=1) {
				if (*names!='\0') {
					return NULL; /* not a directory */
				}
				/* name has a slash in it */
				return filename;
			}
			filename=names;
			dirp->CurrentWorkingDirectory=dirp->DirEntry.d_fileno;

#ifdef DEBUGUNIXDIR
			printf("unixdir-filename left to check = %s\n",filename);
#endif
			found=HasItASlash(filename);
			if (found>0) {
				strncpy(name,filename,found-1);
				name[found-1]='\0';
				FindFileNumber(dirp->CurrentWorkingDirectory,name,dirp);
			}
		}
	}
	return filename;
}

/* LookUpFile - returns NOTFOUND or FOUND and file info in dirp */
LookUpFile(dirp,filename)
DIR *dirp;
char *filename;
{
	filename=StripPathNameFrom(dirp,filename); /* chase path */
	if (filename==NULL) return NOTFOUND;
	return LookUpEntry(dirp,filename);	/* check file */
}

/* LookUpEntry - Looks up a filename in a dir */
LookUpEntry(dirp,filename)
DIR *dirp;
char *filename;
{
	char	*names;
	struct	direct *dp;

	if (strcmp(filename,".")==0 || (*filename=='\0')) {
		MakeUpDir(dirp,".",dirp->CurrentWorkingDirectory);
		return FOUND;
	}

	FindFileNumber(dirp->CurrentWorkingDirectory,filename,dirp);

	for(;;) {
		dp=Mac_readdir(dirp);
		if (dp==NULL) return NOTFOUND;
		/* now compare file names */
		names=CompareNames(filename,dp->d_name);
		if (names!=NULL) {
			return FOUND;
		}
	}
}

/* MakeUpDir - used to make up entries '..' and '.' */
MakeUpDir(dirp,filename,filenumber)
DIR	*dirp;
char	*filename;
long	filenumber;
{
	dirp->DirEntry.d_fileno=filenumber;
	strcpy(dirp->DirEntry.d_name,filename);
	dirp->DirEntry.d_namlen=strlen(filename);
	dirp->FileType=1;
	dirp->FileLength=512;
}


SHAR_EOF
if test 7345 -ne `wc -c < unixdir.c`
then
    echo shar: error transmitting "unixdir.c" '('should be 7345 chars')'
else
    echo unixdir.c
fi
fi
#         End of shar archive
exit 0
-- 

William Roberts         ARPA: liam at cs.qmc.ac.uk  (gw: cs.ucl.edu)
Queen Mary College      UUCP: liam at qmc-cs.UUCP
LONDON, UK              Tel:  01-975 5250



More information about the Comp.unix.aux mailing list