Path: utzoo!attcan!uunet!mcvax!ukc!eagle!icdoc!qmc-cs!liam From: liam@cs.qmc.ac.uk (William Roberts) Newsgroups: comp.unix.aux Subject: HFS library for AUX (part 2 of 2) Message-ID: <585@sequent.cs.qmc.ac.uk> Date: 15 Aug 88 16:56:37 GMT Reply-To: liam@cs.qmc.ac.uk (William Roberts) Organization: CS Dept, Queen Mary College, University of London, UK. Lines: 1828 # 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 (nbytebyte) 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)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;cDirEntry.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 #include #include #include #include #ifndef rewinddir #include #endif #ifndef S_IFMT #include #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 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 #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) { 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 maccopy.c #include "macfile.h" #include "undodefs.h" #include #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 \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) 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 #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 || locDirEntryNumber) { /* rewind */ FindFileNumber(dirp->CurrentWorkingDirectory,NullName,dirp); dirp->FakeType=0; } for (c=0;cDirEntryNumber-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;(cCurrentWorkingDirectory=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@cs.qmc.ac.uk (gw: cs.ucl.edu) Queen Mary College UUCP: liam@qmc-cs.UUCP LONDON, UK Tel: 01-975 5250