/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* |_o_o|\\ Copyright (c) 1987 The Software Distillery. All Rights Reserved */ /* |. o.| || This program may not be distributed without the permission of */ /* | . | || the authors: BBS: */ /* | o | || John Toebes Dave Baker John Mainwaring */ /* | . |// */ /* ====== */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef MANX #define U_ARGS(a) () /* No support for prototypes - oh well */ #else #define U_ARGS(a) a /* prototype checking to ensure all is well */ #include #include #endif /* Unfortunately the 4.1 memcmp doesn't seem to work correctly so just */ /* tell the compiler not to use the builtin function */ #ifdef memcmp #undef memcmp int memcmp(char *, char *, int); #endif #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif #undef GLOBAL /* my version of BADDR() has no problems with casting */ #undef BADDR #define BADDR(x) ((APTR)((long)x << 2)) #define MKBADDR(x) ((BPTR)((long)x >> 2)) #define ACTION_FIND_WRITE 1004L #define ACTION_FIND_INPUT 1005L /* please refer to DOS Tech. Ref. */ #define ACTION_FIND_OUTPUT 1006L #define ACTION_END 1007L #define ACTION_SEEK 1008L #ifndef ACTION_MORE_CACHE #define ACTION_MORE_CACHE 18L #endif #ifndef ACTION_FLUSH #define ACTION_FLUSH 27L #endif #define ACTION_SET_FILE_DATE 34L #define ACTION_SET_RAW_MODE 994L #define DOS_FALSE 0L #define DOS_TRUE -1L /* BCPL "TRUE" */ typedef long KEY; typedef int (*fptr)(); /* handler support routines */ #define BUFSIZE 488 #define BLOCKSIZE 488 /* We define this because the AmigaDos one is so deficient in types */ struct EFileHandle { struct EFileHandle *efh_Next; /* Next efh in system. */ long efh_CurPos; /* Current position in block */ KEY efh_CurKey; /* Key of current block */ long efh_CurBlock; /* Sequence number of current block */ struct FileLock *efh_Lock; /* Lock of file to be accessed */ long efh_CurExtBlock; /* Current extension block number */ KEY efh_ExtBlockKey; /* Key of current extension block */ long efh_Protect; /* Current protection attributes */ }; typedef struct EFileHandle *EFH; /* We define this because the AmigaDos one is so deficient in types */ struct XFileHandle { struct Message *fh_Link; /* Not used - for user to link on his list */ struct MsgPort *fh_Port; /* Reply port for packet */ struct MsgPort *fh_Type; /* Process ID of handler process */ char *fh_Buf; /* Buffer for file I/O */ char *fh_Pos; /* Current position in buffer */ char *fh_End; /* Pointer to end of buffer */ fptr fh_Funcs; /* Function to call to fill buffer */ fptr fh_Func2; /* Function to call to empty buffer */ fptr fh_Func3; /* Function to call when file is closed */ EFH fh_Args; /* For Internal Use - Root of file */ LONG fh_Arg2; /* For Internal Use - Block of Current pos */ }; #define FileHandle XFileHandle #define BLOCKSPERENTRY 72 #define HASHTABLESIZE 72 #define COMMENTSIZE 23 #define NAMESIZE 16*4 #define VOLNAMESIZE 13*4 #define BITMAPSIZE 26 struct DirBlock { long db_Type; long db_OwnKey; long db_HighSeq; /* Highest Sequence number */ long db_HashTableSize; long db_FirstData; long db_CheckSum; long db_HashTable[HASHTABLESIZE]; long db_Spare1; /* Start of bitmap pages on root */ long db_Spare2; long db_Protect; /* Protection bits */ long db_Size; long db_Comment[COMMENTSIZE]; long db_Days; long db_Minutes; long db_Ticks; char db_Name[NAMESIZE]; long db_HashChain; long db_Parent; long db_Extension; long db_SecondaryType; }; struct FileBlock { long fb_Type; long fb_OwnKey; long fb_HighSeq; long fb_DataBlockCount; long fb_FirstData; long fb_CheckSum; long fb_DataBlock[BLOCKSPERENTRY]; long fb_Spare1; long fb_Spare2; long fb_Protect; long fb_Size; long fb_Comment[COMMENTSIZE]; long fb_Days; long fb_Minutes; long fb_Ticks; char fb_Name[NAMESIZE]; long fb_HashChain; long fb_Parent; long fb_Extension; long fb_SecondaryType; }; struct RootBlock { long rb_Type; long rb_OwnKey; /* Always Zero */ long rb_HighSeq; /* Highest Sequence number */ long rb_HashTableSize; long rb_fill1; long rb_CheckSum; long rb_HashTable[HASHTABLESIZE]; long rb_BitMapFlag; long rb_BitMapPages[BITMAPSIZE]; long rb_AltDays; long rb_AltMinutes; long rb_AltTicks; char rb_Name[VOLNAMESIZE]; long rb_CreateDays; long rb_CreateMinutes; long rb_CreateTicks; long rb_HashChain; long rb_Parent; long rb_Extension; long rb_SecondaryType; }; struct DataBlock { long db_Type; long db_Header; long db_SeqNum; long db_DataSize; long db_NextData; long db_CheckSum; long db_Data[122]; }; /* Primary types that appear as first longword in a block */ #define T_SHORT 2 /* Primary type - Root, UserDir, FileHeader blocks */ #define T_LONG 4 /* Unused - indicates long files */ #define T_DATA 8 /* Primary type for Data blocks */ #define T_LIST 16 /* Primary type for file list blocks */ #define T_DELETED 1 /* Bit to indicate a deleted block */ /* Secondary types that appear as the last longword in a block */ #define ST_ROOT 1 /* Secondary type for root block */ #define ST_USERDIR 2 /* Secondary type for a user directory */ #define ST_FILE -3 /* Secondary type for a file */ #define ST_BITMAP 99 /* Bitmap type for checksum */ #define OLDFILE 8 #define NEWFILE 16 #ifdef DEBUG /* Debugging routines */ void myputbstr U_ARGS((char *,)); void myputlstr U_ARGS((char *,)); void myprintf U_ARGS((char *,)); void xwrite U_ARGS((char *, int)); int sprintf U_ARGS((char *, char *,)); #define BUG(a) myprintf a; #define BUGBSTR(a,b) myputbstr(a,b); #define BUGLSTR(a,b,c) myputlstr(a,b,c); #else #define BUG(a) #define BUGBSTR(a,b) #define BUGLSTR(a,b,c) #endif extern struct DosLibrary *DOSBase; #define alloc(a,b) DosAllocMem(a,b) #define free(p) DosFreeMem(p) typedef struct TimerPacket { struct timerequest tm_req; struct DosPacket tm_pkt; }; typedef struct DskChngPacket { struct IOExtTD dc_req; struct Interrupt dc_int; }; typedef struct DiskEnvironment { ULONG de_sizeblock; ULONG de_blkspertrk; ULONG de_reservedblks; ULONG de_numblks; ULONG de_lowcyl; ULONG de_uppercyl; ULONG de_numbufs; ULONG de_membuftype; }; typedef struct BlockBuffer{ char *bb_blk; /* ptr to data buffer associated */ UBYTE bb_used; /* used flag */ UBYTE bb_priority; /* blk priority */ UBYTE bb_dirty; /* dirty minded blk */ ULONG bb_key; /* key associated with this block */ }; typedef struct Bitmap { SHORT bm_blocks; /* number of disk blocks required */ SHORT bm_dirty; /* bitmap modification flag */ ULONG *bm_bitmap; /* pointer to bitmap in memory */ }; typedef struct global { struct DosPacket *pkt; /* the packet we are processing */ struct TimerPacket *timerpkt; /* pkt used for timer request */ struct timerequest *systimepkt; /* pkt for getting the current time */ struct DskChngPacket *dskchngpkt; /* pkt used for diskchange */ struct DeviceNode *node; /* our device node */ struct DeviceList *volume; /* currently mounted volume */ struct Process *self; /* my process */ struct MsgPort *port; /* our message port */ struct DiskEnvironment dskenv; /* stuff need for the device */ struct BlockBuffer *blkbuf; /* ptr to allocated blks for buffers */ struct Bitmap bitmap; /* ptr to bitmap data */ struct IOExtTD *devreq; /* device io request pointer */ struct MsgPort *devport; /* msg port for device io */ EFH AllHandles; /* Chain of all known file handles */ char *devname; /* pointer to device name */ long ErrorCount; /* Error count for current volume */ long DiskChange; /* Current disk change number */ long Root; /* Root block on current volume */ KEY prevkey; /* Previous key in a search */ int run; /* flag to continue running */ int reply; /* flag to inhibit replying to message */ long diskstatus; /* Status of disk in the drive */ long diskstate; /* Status of disk in the drive */ long unitnum; /* Unit number of drive */ long changedisk; /* Flag to indicate a disk change */ UBYTE deviotimeout; /* device io timeout for r/w */ /* These are the fields of the autorequest structure we want to create */ struct IntuiText line1; /* Top Line of requester */ struct IntuiText line2; /* Second Line of requester */ struct IntuiText line3; /* Bottom Line of requester */ struct IntuiText retrytxt; /* Retry information */ struct IntuiText canceltxt; /* CANCEL information */ char buf3[16]; /* Buffer to hold unit information */ }* GLOBAL; /* Routines in buff.c called directly from io.c */ int initbuf U_ARGS((GLOBAL, int, int)); void termbuf U_ARGS((GLOBAL, EFH)); /* Bitmap.c */ int AllocBitMap U_ARGS((GLOBAL)); int FreeBitMap U_ARGS((GLOBAL)); int CountBlocks U_ARGS((GLOBAL)); void DoCheckSum U_ARGS((GLOBAL,char *)); void WriteBitMap U_ARGS((GLOBAL)); void SetBlock U_ARGS((GLOBAL,KEY)); void FreeBlock U_ARGS((GLOBAL, KEY)); KEY AllocateBlock U_ARGS((GLOBAL, KEY, int /* type */)); /* file.c */ void ActDelete U_ARGS((GLOBAL, struct DosPacket *)); void ActRename U_ARGS((GLOBAL, struct DosPacket *)); void ActSetComment U_ARGS((GLOBAL, struct DosPacket *)); void ActSetProtection U_ARGS((GLOBAL, struct DosPacket *)); /* io.c */ void ActFindwrite U_ARGS((GLOBAL, struct DosPacket *)); void ActFindin U_ARGS((GLOBAL, struct DosPacket *)); void ActFindout U_ARGS((GLOBAL, struct DosPacket *)); void ActEnd U_ARGS((GLOBAL, struct DosPacket *)); void ActRead U_ARGS((GLOBAL, struct DosPacket *)); void ActWrite U_ARGS((GLOBAL, struct DosPacket *)); void ActSeek U_ARGS((GLOBAL, struct DosPacket *)); int unsafe U_ARGS((GLOBAL, EFH, int)); /* dir.c */ void ActCreateDir U_ARGS((GLOBAL, struct DosPacket *)); void ActExamine U_ARGS((GLOBAL, struct DosPacket *)); void ActExNext U_ARGS((GLOBAL, struct DosPacket *)); void ActParent U_ARGS((GLOBAL, struct DosPacket *)); /* databuff.c */ char *GetBlock U_ARGS((GLOBAL, KEY)); char *ModBlock U_ARGS((GLOBAL, KEY)); int FindBuffer U_ARGS((GLOBAL,KEY, long)); int AllocBlkBuffs U_ARGS((GLOBAL, long)); void FreeBlkBuffs U_ARGS((GLOBAL)); void FlushOne U_ARGS((GLOBAL,long)); void FlushBuffers U_ARGS((GLOBAL,KEY)); /* Subs.c */ struct DosPacket *taskwait U_ARGS((GLOBAL)); void initdebug U_ARGS((void)); void retpkt U_ARGS((GLOBAL, struct DosPacket *)); char *DosAllocMem U_ARGS((GLOBAL, long)); void DosFreeMem U_ARGS((char *)); /* Disk.c */ int AddDskChngInt U_ARGS((GLOBAL)); void RemDskChngInt U_ARGS((GLOBAL)); int Motor U_ARGS((GLOBAL, int)); int ResetDrive U_ARGS((GLOBAL)); int ReadPhy U_ARGS((GLOBAL, char *, KEY)); int WritePhy U_ARGS((GLOBAL, char *, KEY)); void demanddisk U_ARGS((GLOBAL)); /* mount.c */ void DisMount U_ARGS((GLOBAL)); void Mount U_ARGS((GLOBAL)); /* lock.c */ long GetKey U_ARGS((struct global *,struct FileLock *)); struct FileLock *CreateLock U_ARGS((GLOBAL, KEY, long)); void freelock U_ARGS((GLOBAL, struct FileLock *)); void ActLock U_ARGS((GLOBAL, struct DosPacket *)); void ActDupLock U_ARGS((GLOBAL, struct DosPacket *)); void ActUnLock U_ARGS((GLOBAL, struct DosPacket *)); /* Process.c */ void ActDie U_ARGS((GLOBAL, struct DosPacket *)); void ActInhibit U_ARGS((GLOBAL, struct DosPacket *)); void ActFlush U_ARGS((GLOBAL, struct DosPacket *)); void ActTimer U_ARGS((GLOBAL, struct DosPacket *)); /* volume.c */ void ActCurentVol U_ARGS((GLOBAL, struct DosPacket *)); void ActRenameDisk U_ARGS((GLOBAL, struct DosPacket *)); void ActDiskInfo U_ARGS((GLOBAL, struct DosPacket *)); void ActInfo U_ARGS((GLOBAL, struct DosPacket *)); void GetVolInfo U_ARGS((GLOBAL, struct InfoData *)); /* device.c */ int GetDevice U_ARGS((GLOBAL, struct FileSysStartupMsg *)); int InitDevice U_ARGS((GLOBAL)); int TermDevice U_ARGS((GLOBAL)); /* inhibit.c */ int inhibit U_ARGS((struct MsgPort *, long)); long sendpkt U_ARGS((struct MsgPort *, long, long*, long)); /* timer.c */ int OpenTimer U_ARGS((GLOBAL)); void PostTimerReq U_ARGS((GLOBAL)); void GetDateStamp U_ARGS((GLOBAL, struct DateStamp *)); void MakeDateStamp U_ARGS((struct timeval *, struct DateStamp *)); /* dos1_2.c */ int IsSameName U_ARGS((char *, char *, int)); KEY NextKey U_ARGS((GLOBAL, KEY, struct FileInfoBlock *, KEY)); KEY ParentKey U_ARGS((GLOBAL, KEY)); int hash U_ARGS((char *, int)); int parse U_ARGS((char **, int *, char *)); long GetProtect U_ARGS((GLOBAL, KEY)); int SetProtect U_ARGS((GLOBAL, KEY, long /*Protection*/)); int GetType U_ARGS((GLOBAL, KEY)); int SetCommentStr U_ARGS((GLOBAL, KEY, char *)); int GetInfo U_ARGS((GLOBAL, KEY, struct FileInfoBlock *)); KEY FindDir U_ARGS((GLOBAL, KEY, char **, int *)); KEY FindEntry U_ARGS((GLOBAL, KEY, char *, int)); KEY MakeEntry U_ARGS((GLOBAL, KEY, char *, int, int)); KEY LocateEntry U_ARGS((GLOBAL, KEY, char * /* Name */)); KEY CreateEntry U_ARGS((GLOBAL, KEY, char * /* Name */, int /* Mode */, int /* Type */)); int FreeDataChain U_ARGS((GLOBAL, KEY)); KEY SeekDataChain U_ARGS((GLOBAL, EFH, long)); KEY AppendDataChain U_ARGS((GLOBAL, EFH, long)); long GetFileSize U_ARGS((GLOBAL, EFH)); int UpdateFile U_ARGS((GLOBAL, EFH, long, long)); void GETDATA U_ARGS((char *, long, char *, long)); void PUTDATA U_ARGS((char *, long, char *, long)); KEY BlockKey U_ARGS((GLOBAL, EFH, long, int)); void SetDateInfo U_ARGS((GLOBAL, struct DirBlock *)); KEY GetParent U_ARGS((GLOBAL, KEY)); int GetExtInfo U_ARGS((GLOBAL, KEY, struct ExtInfoBlock *)); int SetExtInfo U_ARGS((GLOBAL, KEY, struct ExtInfoBlock *)); int FreeDirEntry U_ARGS((GLOBAL, KEY)); int RenameDisk U_ARGS((GLOBAL, char *)); int DeleteEntry U_ARGS((GLOBAL, KEY, char *)); int RenameEntry U_ARGS((GLOBAL, KEY, KEY, char *, char *)); KEY LinkDir U_ARGS((GLOBAL, KEY, KEY, int)); /* Directory/File level maintainence */ KEY MakeEntry U_ARGS((GLOBAL,KEY, char *, int, int)); KEY NextDataBlock U_ARGS((GLOBAL, KEY)); /* Requester routine */ int request U_ARGS((GLOBAL, int, char *)); #define REQ_MUST 0 #define REQ_ERROR 1 #define REQ_GENERAL 2