home *** CD-ROM | disk | FTP | other *** search
- /* $Revision Header * Header built automatically - do not edit! *************
- *
- * (C) Copyright 1991 by Olaf Barthel
- *
- * Name .....: Flat-Handler.c
- * Created ..: Saturday 11-May-91 17:55
- * Revision .: 3
- *
- * Date Author Comment
- * ========= ======== ====================
- * 26-Jul-91 Olsen Added ACTION_COPY_DIR
- * 11-Jul-91 Olsen Minor fixes.
- * 11-May-91 Olsen Created this file!
- *
- * $Revision Header ********************************************************/
-
- /* Standard FS error types. */
-
- enum { ERR_WRITEPROTECT,ERR_NODISK,ERR_UNREADABLE,ERR_WRITEERROR };
-
- /* This is a link node used both for locks and filehandles. */
-
- struct FlatNode
- {
- struct FlatNode *fn_Succ; /* Vanilla node head. */
- struct FlatNode *fn_Pred;
-
- ULONG fn_UniqueID; /* A unique ID. */
-
- LONG fn_Mode; /* Either shared or exclusive. */
-
- struct DeviceNode *fn_DevInfo; /* Pointer to a device node,
- * needed by ExNext and the like.
- */
- ULONG fn_BlockSize; /* Size of a block (512 bytes are standard). */
- ULONG fn_FirstBlock; /* The first accessible block. */
- ULONG fn_NumBlocks; /* Maximum number of available blocks. */
-
- LONG fn_Position; /* Current file position in bytes. */
- struct FileLock fn_Lock; /* A dummy file lock. */
-
- UBYTE fn_Name[40]; /* Name of this file. */
-
- struct MsgPort *fn_DiskPort; /* Driver data. */
- struct IOExtTD *fn_DiskRequest;
- APTR fn_DiskBuffer;
-
- BYTE fn_CheckCount; /* The disk state is checked
- * every tenth r/w attempt,
- * this byte keeps the count.
- */
- };
-
- /* This list keeps all the locks and filehandles. */
-
- struct List FlatList;
-
- /* Each open/lock call increments this counter to
- * guarantee that each item receives a unique identifier.
- */
-
- ULONG UniqueCounter = 0;
-
- /* Shared library identifiers. */
-
- struct ExecBase *SysBase = NULL;
- struct DosLibrary *DOSBase = NULL;
- struct IntuitionBase *IntuitionBase = NULL;
-
- /* Prototypes for this module. */
-
- LONG __saveds HandlerEntry(VOID);
-
- LONG __regargs DoRead(struct FlatNode *FlatNode,LONG Size,UBYTE *Buffer,struct Process *Caller);
- LONG __regargs DoWrite(struct FlatNode *FlatNode,LONG Size,UBYTE *Buffer,struct Process *Caller);
-
- UBYTE * __regargs BaseName(UBYTE *String);
-
- UBYTE __regargs Local2Upper(UBYTE c);
- UBYTE __regargs StrCmp(UBYTE *a,UBYTE *b);
-
- struct FlatNode * __regargs FindFlatNodeByID(ULONG UniqueID);
- struct FlatNode * __regargs FindFlatNodeByName(UBYTE *Name);
-
- VOID __regargs BtoCStr(UBYTE *Name,BSTR String,LONG MaxLength);
-
- LONG __regargs ShowRequest(APTR WindowPtr,BYTE Type,UBYTE *Drive);
-
- struct DeviceNode * __regargs FindDevice(struct DeviceNode *LastNode,struct FileSysStartupMsg **Startup,struct DosEnvec **DosEnvec,UBYTE *Name);
-
- VOID __regargs DeleteNode(struct FlatNode *FlatNode);
- struct FlatNode * __regargs CreateNode(LONG Type,UBYTE *Name);
-
- VOID __regargs ReturnPacket(struct DosPacket *Packet,ULONG Res1,ULONG Res2,struct Process *HandlerProc);
- struct DosPacket * __regargs WaitPacket(struct Process *HandlerProc);
-
- /* HandlerEntry():
- *
- * Entry point for this module.
- */
-
- LONG __saveds
- HandlerEntry()
- {
- struct Process *HandlerProc;
-
- struct FileHandle *FileHandle;
- struct FileLock *FileLock;
-
- LONG ReadBytes,WriteBytes,Bytes;
- LONG NewPosition;
- struct FileInfoBlock *FileInfo;
- UBYTE *FileName;
- UBYTE NameBuffer[257];
-
- struct DosPacket *FlatPacket;
- struct DeviceNode *FlatDevNode;
-
- struct FlatNode *FlatNode;
-
- /* Set up SysBase. */
-
- SysBase = *(struct ExecBase **)4;
-
- /* Know who we are. */
-
- HandlerProc = (struct Process *)SysBase -> ThisTask;
-
- /* Started from Shell (oops!)? */
-
- if(!HandlerProc -> pr_CLI)
- {
- /* Wait for startup packet. */
-
- FlatPacket = WaitPacket(HandlerProc);
-
- /* Clear the list. */
-
- NewList(&FlatList);
-
- /* Pick up the pointer to our DeviceNode. */
-
- FlatDevNode = (struct DeviceNode *)BADDR(FlatPacket -> dp_Arg3);
-
- /* Install ourselves at the other hand. */
-
- FlatDevNode -> dn_Task = &HandlerProc -> pr_MsgPort;
-
- /* Open DOS; we are not making DOS calls but
- * rather use the base to scan for block-
- * mapped devices.
- */
-
- if(!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",0)))
- {
- ReturnPacket(FlatPacket,DOSFALSE,FlatPacket -> dp_Res2,HandlerProc);
- goto FallOff;
- }
-
- /* Open Intuition; we might want to put up
- * auto-requesters.
- */
-
- if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0)))
- {
- ReturnPacket(FlatPacket,DOSFALSE,FlatPacket -> dp_Res2,HandlerProc);
- goto FallOff;
- }
-
- /* Initialization finished, now return the
- * startup packet.
- */
-
- ReturnPacket(FlatPacket,DOSTRUE,FlatPacket -> dp_Res2,HandlerProc);
-
- /* Go into loop waiting for data packets. */
-
- FOREVER
- {
- /* Wait for packet. */
-
- FlatPacket = WaitPacket(HandlerProc);
-
- /* Examine the packet type. */
-
- switch(FlatPacket -> dp_Type)
- {
- /* Obtain a filelock. */
-
- case ACTION_LOCATE_OBJECT:
-
- /* Convert the file name. */
-
- BtoCStr(NameBuffer,FlatPacket -> dp_Arg2,256);
-
- /* Are we to return a lock
- * to a file or a lock to the
- * root directory?
- */
-
- if(FileName = BaseName(NameBuffer))
- {
- /* Look for a file of this name. */
-
- if(FlatNode = FindFlatNodeByName(FileName))
- {
- /* See if the file is currently locked. */
-
- if((FlatNode -> fn_Mode != FlatPacket -> dp_Arg3) || (FlatPacket -> dp_Arg3 == EXCLUSIVE_LOCK && FlatNode -> fn_Mode == EXCLUSIVE_LOCK))
- {
- ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_IN_USE,HandlerProc);
- break;
- }
- }
-
- /* Create a new item and add it to the list. */
-
- if(FlatNode = CreateNode(FlatPacket -> dp_Arg3,FileName))
- {
- AddTail(&FlatList,(struct Node *)FlatNode);
-
- /* Initialize the default data so DOS will
- * get along with us.
- */
-
- FlatNode -> fn_Lock . fl_Access = FlatPacket -> dp_Arg3;
- FlatNode -> fn_Lock . fl_Task = &HandlerProc -> pr_MsgPort;
- FlatNode -> fn_Lock . fl_Volume = MKBADDR(FlatDevNode);
- FlatNode -> fn_Lock . fl_Key = FlatNode -> fn_UniqueID;
-
- FlatPacket -> dp_Res1 = MKBADDR(&FlatNode -> fn_Lock);
-
- strcpy(FlatNode -> fn_Name,FileName);
-
- ReturnPacket(FlatPacket,FlatPacket -> dp_Res1,FlatPacket -> dp_Res2,HandlerProc);
- }
- else
- ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
- }
- else
- {
- if(FlatNode = CreateNode(FlatPacket -> dp_Arg3,NULL))
- {
- AddTail(&FlatList,(struct Node *)FlatNode);
-
- FlatNode -> fn_Lock . fl_Access = FlatPacket -> dp_Arg3;
- FlatNode -> fn_Lock . fl_Task = &HandlerProc -> pr_MsgPort;
- FlatNode -> fn_Lock . fl_Volume = MKBADDR(FlatDevNode);
- FlatNode -> fn_Lock . fl_Key = FlatNode -> fn_UniqueID;
-
- FlatPacket -> dp_Res1 = MKBADDR(&FlatNode -> fn_Lock);
-
- ReturnPacket(FlatPacket,FlatPacket -> dp_Res1,FlatPacket -> dp_Res2,HandlerProc);
- }
- else
- ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
- }
-
- break;
-
- /* Free a lock obtained above. */
-
- case ACTION_FREE_LOCK:
-
- /* Is the lock part of the list? */
-
- if(FlatPacket -> dp_Arg1)
- {
- if(FlatNode = FindFlatNodeByID(((struct FileLock *)BADDR(FlatPacket -> dp_Arg1)) -> fl_Key))
- {
- Remove((struct Node *)FlatNode);
-
- DeleteNode(FlatNode);
- }
- }
-
- FlatPacket -> dp_Res1 = DOSTRUE;
-
- ReturnPacket(FlatPacket,FlatPacket -> dp_Res1,FlatPacket -> dp_Res2,HandlerProc);
-
- break;
-
- /* Duplicate a shared lock. */
-
- case ACTION_COPY_DIR:
-
- /* Make sure a ZERO lock gives
- * a more or less valid return
- * code.
- */
-
- FlatPacket -> dp_Res1 = 0;
- FlatPacket -> dp_Res2 = 0;
-
- /* Are we to duplicate a non-ZERO lock? */
-
- if(FlatPacket -> dp_Arg1)
- {
- FileLock = (struct FileLock *)BADDR(FlatPacket -> dp_Arg1);
-
- /* Try to find the corresponding list entry. */
-
- if(FlatNode = FindFlatNodeByID(FileLock -> fl_Key))
- {
- /* Only shared locks may be duplicated. */
-
- if(FlatNode -> fn_Mode == EXCLUSIVE_LOCK)
- {
- FlatPacket -> dp_Res1 = DOSFALSE;
- FlatPacket -> dp_Res2 = ERROR_OBJECT_IN_USE;
- }
- else
- {
- struct FlatNode *AnotherNode;
-
- /* Create a new node. */
-
- if(FlatNode -> fn_Name[0])
- AnotherNode = CreateNode(SHARED_LOCK,FlatNode -> fn_Name);
- else
- AnotherNode = CreateNode(SHARED_LOCK,NULL);
-
- /* Did we get what we wanted? */
-
- if(AnotherNode)
- {
- /* Not quite so unique I suppose. */
-
- AnotherNode -> fn_UniqueID = FlatNode -> fn_UniqueID;
-
- /* Add the freshly created lock
- * to the list.
- */
-
- AddTail(&FlatList,(struct Node *)AnotherNode);
-
- /* Fill in the Lock data. */
-
- AnotherNode -> fn_Lock . fl_Access = SHARED_LOCK;
- AnotherNode -> fn_Lock . fl_Task = &HandlerProc -> pr_MsgPort;
- AnotherNode -> fn_Lock . fl_Volume = MKBADDR(FlatDevNode);
- AnotherNode -> fn_Lock . fl_Key = AnotherNode -> fn_UniqueID;
-
- /* Successful return. */
-
- FlatPacket -> dp_Res1 = MKBADDR(&AnotherNode -> fn_Lock);
- }
- else
- {
- /* Failed to create node. */
-
- FlatPacket -> dp_Res1 = DOSFALSE;
- FlatPacket -> dp_Res2 = ERROR_NO_FREE_STORE;
- }
- }
- }
- else
- {
- /* Couldn't find the lock. */
-
- FlatPacket -> dp_Res1 = DOSFALSE;
- FlatPacket -> dp_Res2 = ERROR_OBJECT_NOT_FOUND;
- }
- }
-
- ReturnPacket(FlatPacket,FlatPacket -> dp_Res1,FlatPacket -> dp_Res2,HandlerProc);
-
- break;
-
- /* Examine a file. */
-
- case ACTION_EXAMINE_OBJECT:
-
- /* Get filelock and fileinfoblock in handy variables. */
-
- FileLock = (struct FileLock *)BADDR(FlatPacket -> dp_Arg1);
- FileInfo = (struct FileInfoBlock *)BADDR(FlatPacket -> dp_Arg2);
-
- /* Are both identifiers valid? */
-
- if(FileLock && FileInfo)
- {
- BYTE Success = FALSE;
-
- /* Can we find the item? */
-
- if(FlatNode = FindFlatNodeByID(FileLock -> fl_Key))
- {
- struct FileSysStartupMsg *Startup;
- struct DosEnvec *DosEnvec;
-
- /* Is it a file or a directory? */
-
- if(FlatNode -> fn_Name[0])
- {
- /* Find the approriate device. */
-
- if(FlatNode -> fn_DevInfo = FindDevice(NULL,&Startup,&DosEnvec,FlatNode -> fn_Name))
- {
- struct MsgPort *DiskPort;
-
- /* Create device driver data. */
-
- if(DiskPort = (struct MsgPort *)CreatePort(NULL,0))
- {
- struct IOExtTD *DiskRequest;
-
- if(DiskRequest = (struct IOExtTD *)CreateExtIO(DiskPort,sizeof(struct IOExtTD)))
- {
- BtoCStr(NameBuffer,Startup -> fssm_Device,256);
-
- if(!OpenDevice(NameBuffer,Startup -> fssm_Unit,DiskRequest,Startup -> fssm_Flags))
- {
- /* We are actually faking part of the data
- * to be returned in the fileinfoblock.
- * This isn't Unix and there are only two
- * kinds of directory entries: files and
- * directories. The protection bits are by
- * default configured to mimic the state of
- * the corresponding drive. If not write-
- * enabled, the file will have the write
- * access-bit cleared, if there is no disk
- * in the drive, the read bit will be cleared,
- * the file size will be zero as well.
- */
-
- memset(FileInfo,0,sizeof(struct FileInfoBlock));
-
- FileInfo -> fib_DiskKey = FileLock -> fl_Key;
- FileInfo -> fib_DirEntryType = -3;
- FileInfo -> fib_Protection = FIBF_EXECUTE|FIBF_DELETE;
- FileInfo -> fib_Size = (DosEnvec -> de_HighCyl - DosEnvec -> de_LowCyl + 1) * DosEnvec -> de_BlocksPerTrack * DosEnvec -> de_Surfaces * (DosEnvec -> de_SizeBlock << 2);
- FileInfo -> fib_NumBlocks = (DosEnvec -> de_HighCyl - DosEnvec -> de_LowCyl + 1) * DosEnvec -> de_BlocksPerTrack * DosEnvec -> de_Surfaces;
-
- /* The rest is mocked up or cleared
- * with zeroes, a disk may not have
- * a valid root block on it.
- */
-
- DateStamp(&FileInfo -> fib_Date);
-
- memcpy(FileInfo -> fib_FileName,BADDR(FlatNode -> fn_DevInfo -> dn_Name),((UBYTE *)BADDR(FlatNode -> fn_DevInfo -> dn_Name))[0] + 1);
-
- DiskRequest -> iotd_Req . io_Command = TD_PROTSTATUS;
-
- if(!DoIO(DiskRequest))
- {
- if(DiskRequest -> iotd_Req . io_Actual)
- FileInfo -> fib_Protection |= FIBF_WRITE;
- }
-
- DiskRequest -> iotd_Req . io_Command = TD_CHANGESTATE;
-
- if(!DoIO(DiskRequest))
- {
- if(DiskRequest -> iotd_Req . io_Actual)
- {
- FileInfo -> fib_Protection |= FIBF_READ|FIBF_WRITE;
-
- FileInfo -> fib_Size = FileInfo -> fib_NumBlocks = 0;
- }
- }
-
- Success = TRUE;
-
- CloseDevice(DiskRequest);
- }
-
- DeleteExtIO(DiskRequest);
- }
-
- DeletePort(DiskPort);
- }
- }
- }
- else
- {
- /* This is very much the same as above,
- * but this time it's the root directory
- * we will create.
- */
-
- memset(FileInfo,0,sizeof(struct FileInfoBlock));
-
- FileInfo -> fib_DiskKey = FileLock -> fl_Key;
- FileInfo -> fib_DirEntryType = 1;
- FileInfo -> fib_Protection = FIBF_EXECUTE;
- FileInfo -> fib_Size = 0;
- FileInfo -> fib_NumBlocks = 0;
-
- DateStamp(&FileInfo -> fib_Date);
-
- strcpy(FileInfo -> fib_FileName,"\4FLAT");
-
- Success = TRUE;
- }
- }
-
- if(Success)
- {
- FlatPacket -> dp_Res1 = DOSTRUE;
-
- ReturnPacket(FlatPacket,FlatPacket -> dp_Res1,FlatPacket -> dp_Res2,HandlerProc);
- }
- else
- ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
- }
- else
- ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
-
- break;
-
- /* Examine the next directory entry (if available). */
-
- case ACTION_EXAMINE_NEXT:
-
- /* This works very much the same as above, with the
- * exception that we are trying to gather information
- * on the next available DosList Device entry.
- */
-
- FileLock = (struct FileLock *)BADDR(FlatPacket -> dp_Arg1);
- FileInfo = (struct FileInfoBlock *)BADDR(FlatPacket -> dp_Arg2);
-
- if(FileLock && FileInfo)
- {
- BYTE Success = FALSE;
-
- if(FlatNode = FindFlatNodeByID(FileLock -> fl_Key))
- {
- struct FileSysStartupMsg *Startup;
- struct DosEnvec *DosEnvec;
-
- if(FlatNode -> fn_DevInfo = FindDevice(FlatNode -> fn_DevInfo,&Startup,&DosEnvec,NULL))
- {
- struct MsgPort *DiskPort;
-
- if(DiskPort = (struct MsgPort *)CreatePort(NULL,0))
- {
- struct IOExtTD *DiskRequest;
-
- if(DiskRequest = (struct IOExtTD *)CreateExtIO(DiskPort,sizeof(struct IOExtTD)))
- {
- BtoCStr(NameBuffer,Startup -> fssm_Device,256);
-
- if(!OpenDevice(NameBuffer,Startup -> fssm_Unit,DiskRequest,Startup -> fssm_Flags))
- {
- memset(FileInfo,0,sizeof(struct FileInfoBlock));
-
- FileInfo -> fib_DiskKey = FileLock -> fl_Key;
- FileInfo -> fib_DirEntryType = -1;
- FileInfo -> fib_Protection = FIBF_EXECUTE|FIBF_DELETE;
- FileInfo -> fib_Size = (DosEnvec -> de_HighCyl - DosEnvec -> de_LowCyl + 1) * DosEnvec -> de_BlocksPerTrack * DosEnvec -> de_Surfaces * (DosEnvec -> de_SizeBlock << 2);
- FileInfo -> fib_NumBlocks = (DosEnvec -> de_HighCyl - DosEnvec -> de_LowCyl + 1) * DosEnvec -> de_BlocksPerTrack * DosEnvec -> de_Surfaces;
-
- DateStamp(&FileInfo -> fib_Date);
-
- memcpy(FileInfo -> fib_FileName,BADDR(FlatNode -> fn_DevInfo -> dn_Name),((UBYTE *)BADDR(FlatNode -> fn_DevInfo -> dn_Name))[0] + 1);
-
- DiskRequest -> iotd_Req . io_Command = TD_PROTSTATUS;
-
- if(!DoIO(DiskRequest))
- {
- if(DiskRequest -> iotd_Req . io_Actual)
- FileInfo -> fib_Protection |= FIBF_WRITE;
- }
-
- DiskRequest -> iotd_Req . io_Command = TD_CHANGESTATE;
-
- if(!DoIO(DiskRequest))
- {
- if(DiskRequest -> iotd_Req . io_Actual)
- {
- FileInfo -> fib_Protection |= FIBF_READ|FIBF_WRITE;
-
- FileInfo -> fib_Size = FileInfo -> fib_NumBlocks = 0;
- }
- }
-
- Success = TRUE;
-
- CloseDevice(DiskRequest);
- }
-
- DeleteExtIO(DiskRequest);
- }
-
- DeletePort(DiskPort);
- }
- }
- else
- {
- ReturnPacket(FlatPacket,DOSFALSE,ERROR_NO_MORE_ENTRIES,HandlerProc);
- break;
- }
- }
-
- if(Success)
- {
- FlatPacket -> dp_Res1 = DOSTRUE;
-
- ReturnPacket(FlatPacket,FlatPacket -> dp_Res1,FlatPacket -> dp_Res2,HandlerProc);
- }
- else
- ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
- }
- else
- ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
-
- break;
-
- /* Open any file for reading/writing. */
-
- case ACTION_FINDINPUT:
- case ACTION_FINDOUTPUT:
- case ACTION_FINDUPDATE:
-
- /* Convert the file name. */
-
- BtoCStr(NameBuffer,FlatPacket -> dp_Arg3,256);
-
- if(FileName = BaseName(NameBuffer))
- {
- LONG Mode;
-
- /* Only the MODE_OLDFILE type allows
- * shared data access.
- */
-
- if(FlatPacket -> dp_Type == ACTION_FINDINPUT)
- Mode = SHARED_LOCK;
- else
- Mode = EXCLUSIVE_LOCK;
-
- FileHandle = (struct FileHandle *)BADDR(FlatPacket -> dp_Arg1);
-
- /* Is there already a lock or filehandle by this
- * name?
- */
-
- if(FlatNode = FindFlatNodeByName(FileName))
- {
- /* If so, is it locked? */
-
- if((FlatNode -> fn_Mode != Mode) || (Mode == EXCLUSIVE_LOCK && FlatNode -> fn_Mode == EXCLUSIVE_LOCK))
- {
- ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_IN_USE,HandlerProc);
- break;
- }
- }
-
- /* Create a new list entry. */
-
- if(FlatNode = CreateNode(Mode,FileName))
- {
- AddTail(&FlatList,(struct Node *)FlatNode);
-
- FileHandle -> fh_Arg1 = FlatNode -> fn_UniqueID;
-
- /* Turn on the disk motor. */
-
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = TD_MOTOR;
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Length = 1;
-
- DoIO(FlatNode -> fn_DiskRequest);
-
- ReturnPacket(FlatPacket,DOSTRUE,FlatPacket -> dp_Res2,HandlerProc);
- }
- else
- ReturnPacket(FlatPacket,DOSFALSE,ERROR_NO_FREE_STORE,HandlerProc);
- }
- else
- ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
-
- break;
-
- /* Close a file opened above. */
-
- case ACTION_END:
-
- /* Find the node. */
-
- if(FlatNode = FindFlatNodeByID(FlatPacket -> dp_Arg1))
- {
- /* Turn off the motor. */
-
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = TD_MOTOR;
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Length = 0;
-
- DoIO(FlatNode -> fn_DiskRequest);
-
- Remove((struct Node *)FlatNode);
-
- DeleteNode(FlatNode);
- }
-
- ReturnPacket(FlatPacket,DOSTRUE,0,HandlerProc);
- break;
-
- /* Read a couple of bytes from a file. */
-
- case ACTION_READ:
-
- /* Do we have a valid filehandle? */
-
- if(FlatNode = FindFlatNodeByID(FlatPacket -> dp_Arg1))
- {
- ReadBytes = FlatPacket -> dp_Arg3;
-
- /* Reading across the data media size? */
-
- if(FlatNode -> fn_Position + ReadBytes > (FlatNode -> fn_BlockSize * FlatNode -> fn_NumBlocks))
- ReadBytes = -1;
-
- FlatPacket -> dp_Res2 = 0;
-
- /* Read a few bytes. */
-
- if(ReadBytes > 0)
- {
- if(Bytes = DoRead(FlatNode,ReadBytes,(APTR)FlatPacket -> dp_Arg2,FlatPacket -> dp_Port -> mp_SigTask))
- FlatNode -> fn_Position += Bytes;
-
- FlatPacket -> dp_Res1 = Bytes;
- }
- else
- {
- if(ReadBytes == 0)
- FlatPacket -> dp_Res1 = 0;
- else
- FlatPacket -> dp_Res1 = -1;
- }
-
- ReturnPacket(FlatPacket,FlatPacket -> dp_Res1,FlatPacket -> dp_Res2,HandlerProc);
- }
- else
- ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_WRONG_TYPE,HandlerProc);
-
- break;
-
- /* Write a few bytes to a file. */
-
- case ACTION_WRITE:
-
- if(FlatNode = FindFlatNodeByID(FlatPacket -> dp_Arg1))
- {
- WriteBytes = FlatPacket -> dp_Arg3;
-
- if(FlatNode -> fn_Position + WriteBytes > (FlatNode -> fn_BlockSize * FlatNode -> fn_NumBlocks))
- WriteBytes = -1;
-
- FlatPacket -> dp_Res2 = 0;
-
- if(WriteBytes > 0)
- {
- if(Bytes = DoWrite(FlatNode,WriteBytes,(APTR)FlatPacket -> dp_Arg2,FlatPacket -> dp_Port -> mp_SigTask))
- FlatNode -> fn_Position += Bytes;
-
- FlatPacket -> dp_Res1 = Bytes;
- }
- else
- {
- if(WriteBytes == 0)
- FlatPacket -> dp_Res1 = 0;
- else
- FlatPacket -> dp_Res1 = -1;
- }
-
- ReturnPacket(FlatPacket,FlatPacket -> dp_Res1,FlatPacket -> dp_Res2,HandlerProc);
- }
- else
- ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_WRONG_TYPE,HandlerProc);
-
- break;
-
- /* Move the r/w pointer inside a file. */
-
- case ACTION_SEEK:
-
- if(FlatNode = FindFlatNodeByID(FlatPacket -> dp_Arg1))
- {
- if(FlatPacket -> dp_Arg3 == OFFSET_BEGINNING)
- NewPosition = FlatPacket -> dp_Arg2;
-
- if(FlatPacket -> dp_Arg3 == OFFSET_CURRENT)
- NewPosition = FlatNode -> fn_Position + FlatPacket -> dp_Arg2;
-
- if(FlatPacket -> dp_Arg3 == OFFSET_END)
- NewPosition = FlatNode -> fn_Position - FlatPacket -> dp_Arg2;
-
- if(NewPosition < 0 || NewPosition > (FlatNode -> fn_BlockSize * FlatNode -> fn_NumBlocks))
- {
- FlatPacket -> dp_Res1 = -1;
- FlatPacket -> dp_Res2 = ERROR_SEEK_ERROR;
- }
- else
- {
- FlatPacket -> dp_Res1 = FlatNode -> fn_Position;
-
- FlatNode -> fn_Position = NewPosition;
- }
-
- ReturnPacket(FlatPacket,FlatPacket -> dp_Res1,FlatPacket -> dp_Res2,HandlerProc);
- }
- else
- ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_WRONG_TYPE,HandlerProc);
-
- break;
-
- /* Remove the handler. */
-
- case ACTION_DIE:
-
- /* Are we allowed to remove ourselves? */
-
- if(!FlatList . lh_Head -> ln_Succ)
- {
- ReturnPacket(FlatPacket,DOSTRUE,0,HandlerProc);
-
- goto FallOff;
- }
- else
- ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_IN_USE,HandlerProc);
-
- break;
-
- /* Ignore the rest of the packets. */
-
- default:
-
- ReturnPacket(FlatPacket,DOSFALSE,ERROR_ACTION_NOT_KNOWN,HandlerProc);
- break;
- }
- }
-
- /* Cease actions, close libraries and exit. */
-
- FallOff: FlatDevNode -> dn_Task = NULL;
-
- if(IntuitionBase)
- CloseLibrary(IntuitionBase);
-
- if(DOSBase)
- CloseLibrary(DOSBase);
- }
- }
-
- /* BaseName(UBYTE *String):
- *
- * Returns the base of a filename.
- */
-
- UBYTE * __regargs
- BaseName(UBYTE *String)
- {
- if(String[0])
- {
- SHORT i;
-
- for(i = strlen(String) - 1 ; i >= 0 ; i--)
- {
- if(String[i] == ':' || String[i] == '/')
- {
- if(String[i + 1])
- return(&String[i + 1]);
- else
- return(NULL);
- }
- }
-
- return(String);
- }
- else
- return(NULL);
- }
-
- /* Local2Upper(UBYTE c):
- *
- * Convert a character to upper case.
- */
-
- UBYTE __regargs
- Local2Upper(UBYTE c)
- {
- return((UBYTE)((((c) >= 224 && (c) <= 254) || ((c) >= 'a' && (c) <= 'z')) ? (c) - 32 : c));
- }
-
- /* StrCmp(UBYTE *a,UBYTE *b):
- *
- * Do string comparison ignoring case.
- */
-
- UBYTE __regargs
- StrCmp(UBYTE *a,UBYTE *b)
- {
- for( ; Local2Upper(*a) == Local2Upper(*b) ; a++, b++)
- {
- if(!(*a))
- return(0);
- }
-
- return((UBYTE)(Local2Upper(*a) - Local2Upper(*b)));
- }
-
- /* FindFlatNodeByID(ULONG UniqueID):
- *
- * Scan the item list looking for a list entry with
- * a matching ID.
- */
-
- struct FlatNode * __regargs
- FindFlatNodeByID(ULONG UniqueID)
- {
- struct FlatNode *Node;
-
- Node = (struct FlatNode *)FlatList . lh_Head;
-
- while(Node -> fn_Succ)
- {
- if(Node -> fn_UniqueID == UniqueID)
- return(Node);
-
- Node = Node -> fn_Succ;
- }
-
- return(NULL);
- }
-
- /* FindFlatNodeByName(UBYTE *Name):
- *
- * Scan the item list looking for an entry with a
- * matching name.
- */
-
- struct FlatNode * __regargs
- FindFlatNodeByName(UBYTE *Name)
- {
- struct FlatNode *Node;
-
- Node = (struct FlatNode *)FlatList . lh_Head;
-
- while(Node -> fn_Succ)
- {
- if(!StrCmp(Node -> fn_Name,Name))
- return(Node);
-
- Node = Node -> fn_Succ;
- }
-
- return(NULL);
- }
-
- /* BtoCStr(UBYTE *Name,BSTR String,LONG MaxLength):
- *
- * Convert a BCPL string into a `C' string.
- */
-
- VOID __regargs
- BtoCStr(UBYTE *Name,BSTR String,LONG MaxLength)
- {
- UBYTE *Src,Length;
-
- if(Src = (UBYTE *)BADDR(String))
- {
- if((Length = Src[0]) > MaxLength)
- Length = MaxLength;
-
- Src++;
-
- while(Length--)
- *Name++ = *Src++;
-
- *Name = 0;
- }
- }
-
- /* ShowRequest(APTR WindowPtr,BYTE Type,UBYTE *Drive):
- *
- * If trouble shows up, behave like the standard
- * FS and complain.
- */
-
- LONG __regargs
- ShowRequest(APTR WindowPtr,BYTE Type,UBYTE *Drive)
- {
- STATIC struct IntuiText DiskWriteProtected[3] =
- {
- {0,1,JAM2,15, 5,NULL,"Disk in drive", &DiskWriteProtected[1]},
- {0,1,JAM2,15,15,NULL,"################################", &DiskWriteProtected[2]},
- {0,1,JAM2,15,25,NULL,"is write protected", NULL}
- };
-
- STATIC struct IntuiText DiskNotPresent[2] =
- {
- {0,1,JAM2,15, 5,NULL,"No disk present in drive", &DiskNotPresent[1]},
- {0,1,JAM2,15,15,NULL,"################################", NULL}
- };
-
- STATIC struct IntuiText DiskUnreadable[3] =
- {
- {0,1,JAM2,15, 5,NULL,"Disk in drive", &DiskUnreadable[1]},
- {0,1,JAM2,15,15,NULL,"################################", &DiskUnreadable[2]},
- {0,1,JAM2,15,25,NULL,"is unreadable", NULL}
- };
-
- STATIC struct IntuiText DiskWriteError[2] =
- {
- {0,1,JAM2,15, 5,NULL,"Error writing to drive", &DiskWriteError[1]},
- {0,1,JAM2,15,15,NULL,"################################", NULL}
- };
-
- STATIC struct IntuiText Retry =
- {
- 0,1,JAM2,7,3,NULL,"Retry",NULL
- };
-
- STATIC struct IntuiText Cancel =
- {
- 0,1,JAM2,7,3,NULL,"Cancel",NULL
- };
-
- /* A -1 will result in cancelling the
- * requester.
- */
-
- if(WindowPtr != (APTR)-1)
- {
- struct IntuiText *BodyText;
- SHORT i;
-
- /* Install the right alert type. */
-
- switch(Type)
- {
- case ERR_WRITEPROTECT: BodyText = DiskWriteProtected;
- break;
-
- case ERR_NODISK: BodyText = DiskNotPresent;
- break;
-
- case ERR_UNREADABLE: BodyText = DiskUnreadable;
- break;
-
- case ERR_WRITEERROR: BodyText = DiskWriteError;
- break;
- }
-
- /* Add the drive name. */
-
- for(i = 0 ; BodyText[1] . IText[i] = Local2Upper(Drive[i + 1]) ; i++);
-
- /* Show the requester. */
-
- return((LONG)AutoRequest(WindowPtr,BodyText,&Retry,&Cancel,DISKINSERTED,NULL,320,72));
- }
-
- return(FALSE);
- }
-
- /* FindDevice():
- *
- * Find a DeviceNode entry in the DosList.
- */
-
- struct DeviceNode * __regargs
- FindDevice(struct DeviceNode *LastNode,struct FileSysStartupMsg **Startup,struct DosEnvec **DosEnvec,UBYTE *Name)
- {
- struct DeviceNode *DevInfo;
- STATIC UBYTE NameBuffer[257];
-
- Forbid();
-
- if(LastNode)
- DevInfo = (struct DeviceNode *)BADDR(LastNode -> dn_Next);
- else
- DevInfo = (struct DeviceNode *)BADDR(((struct DosInfo *)BADDR(((struct RootNode *)DOSBase -> dl_Root) -> rn_Info)) -> di_DevInfo);
-
- while(DevInfo)
- {
- if(DevInfo -> dn_Type == DLT_DEVICE && DevInfo -> dn_Task && DevInfo -> dn_Startup)
- {
- if(Name)
- {
- BtoCStr(NameBuffer,DevInfo -> dn_Name,256);
-
- if(!StrCmp(NameBuffer,Name))
- {
- if(Startup)
- *Startup = (struct FileSysStartupMsg *)BADDR(DevInfo -> dn_Startup);
-
- if(DosEnvec)
- *DosEnvec = (struct DosEnvec *)BADDR(((struct FileSysStartupMsg *)BADDR(DevInfo -> dn_Startup)) -> fssm_Environ);
-
- Permit();
-
- return(DevInfo);
- }
- }
- else
- {
- if(Startup)
- *Startup = (struct FileSysStartupMsg *)BADDR(DevInfo -> dn_Startup);
-
- if(DosEnvec)
- *DosEnvec = (struct DosEnvec *)BADDR(((struct FileSysStartupMsg *)BADDR(DevInfo -> dn_Startup)) -> fssm_Environ);
-
- Permit();
-
- return(DevInfo);
- }
- }
-
- DevInfo = (struct DeviceNode *)BADDR(DevInfo -> dn_Next);
- }
-
- Permit();
-
- return(NULL);
- }
-
- /* DeleteNode(struct FlatNode *FlatNode):
- *
- * Delete a freshly created item node freeing
- * all associated resources.
- */
-
- VOID __regargs
- DeleteNode(struct FlatNode *FlatNode)
- {
- if(FlatNode -> fn_DiskBuffer)
- FreeMem(FlatNode -> fn_DiskBuffer,FlatNode -> fn_BlockSize);
-
- if(FlatNode -> fn_DiskRequest)
- {
- if(FlatNode -> fn_DiskRequest -> iotd_Req . io_Device)
- CloseDevice(FlatNode -> fn_DiskRequest);
-
- DeleteExtIO(FlatNode -> fn_DiskRequest);
- }
-
- if(FlatNode -> fn_DiskPort)
- DeletePort(FlatNode -> fn_DiskPort);
-
- FreeMem(FlatNode,sizeof(struct FlatNode));
- }
-
- /* CreateNode(LONG Type,UBYTE *Name):
- *
- * Create an item node with given characteristics,
- * can be either shared or exclusive access, if a name
- * is given will open the approriate device driver.
- */
-
- struct FlatNode * __regargs
- CreateNode(LONG Type,UBYTE *Name)
- {
- struct FlatNode *FlatNode;
-
- if(FlatNode = (struct FlatNode *)AllocMem(sizeof(struct FlatNode),MEMF_PUBLIC|MEMF_CLEAR))
- {
- if(Name)
- {
- struct DeviceNode *DevInfo;
- struct FileSysStartupMsg *Startup;
- struct DosEnvec *DosEnvec;
-
- /* Try to find the device. */
-
- if(!(DevInfo = FindDevice(NULL,&Startup,&DosEnvec,Name)))
- {
- DeleteNode(FlatNode);
-
- return(NULL);
- }
-
- /* Create a MsgPort, this is where a
- * potential problem exists: since all
- * MsgPorts refer to the handler process,
- * we will run out of signal bits if
- * more than app. 16 files/locks are open at
- * the same time.
- */
-
- if(!(FlatNode -> fn_DiskPort = (struct MsgPort *)CreatePort(NULL,0)))
- {
- DeleteNode(FlatNode);
-
- return(NULL);
- }
-
- /* Create a device request. */
-
- if(!(FlatNode -> fn_DiskRequest = (struct IOExtTD *)CreateExtIO(FlatNode -> fn_DiskPort,sizeof(struct IOExtTD))))
- {
- DeleteNode(FlatNode);
-
- return(NULL);
- }
-
- /* Open the device driver. */
-
- if(OpenDevice(&((UBYTE *)BADDR(Startup -> fssm_Device))[1],Startup -> fssm_Unit,FlatNode -> fn_DiskRequest,Startup -> fssm_Flags))
- {
- DeleteNode(FlatNode);
-
- return(NULL);
- }
-
- /* Inquire the unit data. */
-
- FlatNode -> fn_BlockSize = DosEnvec -> de_SizeBlock << 2;
- FlatNode -> fn_FirstBlock = DosEnvec -> de_LowCyl * DosEnvec -> de_BlocksPerTrack * DosEnvec -> de_Surfaces;
- FlatNode -> fn_NumBlocks = (DosEnvec -> de_HighCyl - DosEnvec -> de_LowCyl + 1) * DosEnvec -> de_BlocksPerTrack * DosEnvec -> de_Surfaces;
-
- /* Create a r/w buffer. */
-
- if(!(FlatNode -> fn_DiskBuffer = (APTR)AllocMem(FlatNode -> fn_BlockSize,DosEnvec -> de_BufMemType)))
- {
- DeleteNode(FlatNode);
-
- return(NULL);
- }
-
- strcpy(&FlatNode -> fn_Name[1],Name);
- }
-
- FlatNode -> fn_Mode = Type;
- FlatNode -> fn_UniqueID = UniqueCounter++;
- }
-
- return(FlatNode);
- }
-
- /* ReturnPacket():
- *
- * Return a standard DOS packet to its sender.
- */
-
- VOID __regargs
- ReturnPacket(struct DosPacket *Packet,ULONG Res1,ULONG Res2,struct Process *HandlerProc)
- {
- struct MsgPort *ReplyPort;
-
- ReplyPort = Packet -> dp_Port;
-
- Packet -> dp_Res1 = Res1;
- Packet -> dp_Res2 = Res2;
-
- Packet -> dp_Port = &HandlerProc -> pr_MsgPort;
-
- Packet -> dp_Link -> mn_Node . ln_Name = (APTR)Packet;
- Packet -> dp_Link -> mn_Node . ln_Succ = NULL;
- Packet -> dp_Link -> mn_Node . ln_Pred = NULL;
-
- PutMsg(ReplyPort,Packet -> dp_Link);
- }
-
- /* WaitPacket(struct Process *HandlerProc):
- *
- * Wait for packet arrival.
- */
-
- struct DosPacket * __regargs
- WaitPacket(struct Process *HandlerProc)
- {
- struct Message *DOSMsg;
-
- WaitPort(&HandlerProc -> pr_MsgPort);
-
- DOSMsg = (struct Message *)GetMsg(&HandlerProc -> pr_MsgPort);
-
- return((struct DosPacket *)DOSMsg -> mn_Node . ln_Name);
- }
-
- /* DoRead():
- *
- * Read a few bytes from a file.
- */
-
- LONG __regargs
- DoRead(struct FlatNode *FlatNode,LONG Size,UBYTE *Buffer,struct Process *Caller)
- {
- LONG Block,Length,BytesRead = 0,Offset = FlatNode -> fn_Position;
- UBYTE *DiskBuffer = FlatNode -> fn_DiskBuffer;
-
- /* Time for a check? */
-
- if(!FlatNode -> fn_CheckCount)
- {
- FOREVER
- {
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = TD_CHANGESTATE;
-
- /* Is there still a disk in the drive? */
-
- if(!DoIO(FlatNode -> fn_DiskRequest))
- {
- if(FlatNode -> fn_DiskRequest -> iotd_Req . io_Actual)
- {
- if(!ShowRequest(Caller -> pr_WindowPtr,ERR_NODISK,FlatNode -> fn_Name))
- return(0);
- }
- else
- break;
- }
- }
- }
-
- if(FlatNode -> fn_CheckCount++ == 10)
- FlatNode -> fn_CheckCount = 0;
-
- /* Convert offset from bytes into blocks. */
-
- Block = Offset / FlatNode -> fn_BlockSize;
- Offset = Offset % FlatNode -> fn_BlockSize;
-
- if(Size > 0)
- {
- /* Read the data block by block... */
-
- while(Size > 0)
- {
- Retry: FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = CMD_READ;
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Offset = Block * FlatNode -> fn_BlockSize + FlatNode -> fn_FirstBlock;
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Length = FlatNode -> fn_BlockSize;
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Data = DiskBuffer;
-
- /* Read the block. */
-
- if(DoIO(FlatNode -> fn_DiskRequest))
- {
- if(ShowRequest(Caller -> pr_WindowPtr,ERR_UNREADABLE,FlatNode -> fn_Name))
- goto Retry;
- else
- return(BytesRead);
- }
-
- Length = FlatNode -> fn_BlockSize - Offset;
-
- if(Length > Size)
- Length = Size;
-
- /* Copy the data. */
-
- memcpy(Buffer,&DiskBuffer[Offset],Length);
-
- Buffer = &Buffer[Length];
-
- Size -= Length;
-
- BytesRead += Length;
-
- Block++;
-
- Offset = 0;
- }
- }
-
- return(BytesRead);
- }
-
- /* DoWrite():
- *
- * Write a few bytes to a file.
- */
-
- LONG __regargs
- DoWrite(struct FlatNode *FlatNode,LONG Size,UBYTE *Buffer,struct Process *Caller)
- {
- LONG Block,Length,BytesWritten = 0,Offset = FlatNode -> fn_Position;
- UBYTE *DiskBuffer = FlatNode -> fn_DiskBuffer;
-
- /* Time for a check? */
-
- if(!FlatNode -> fn_CheckCount)
- {
- FOREVER
- {
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = TD_CHANGESTATE;
-
- /* Is there a disk in the drive? */
-
- if(!DoIO(FlatNode -> fn_DiskRequest))
- {
- if(FlatNode -> fn_DiskRequest -> iotd_Req . io_Actual)
- {
- if(!ShowRequest(Caller -> pr_WindowPtr,ERR_NODISK,FlatNode -> fn_Name))
- return(0);
- }
- else
- break;
- }
- }
-
- FOREVER
- {
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = TD_PROTSTATUS;
-
- /* Is the disk write enabled? */
-
- if(!DoIO(FlatNode -> fn_DiskRequest))
- {
- if(FlatNode -> fn_DiskRequest -> iotd_Req . io_Actual)
- {
- if(!ShowRequest(Caller -> pr_WindowPtr,ERR_WRITEPROTECT,FlatNode -> fn_Name))
- return(0);
- }
- else
- break;
- }
- }
- }
-
- if(FlatNode -> fn_CheckCount++ == 10)
- FlatNode -> fn_CheckCount = 0;
-
- /* Convert offset from bytes into blocks. */
-
- Block = Offset / FlatNode -> fn_BlockSize;
- Offset = Offset % FlatNode -> fn_BlockSize;
-
- if(Size > 0)
- {
- while(Size > 0)
- {
- Retry1: if(Offset)
- {
- /* The data to write is smaller
- * than a block, so we'll have to
- * read the block to write to first,
- * copy the data over and write the
- * block back.
- */
-
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = CMD_READ;
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Offset = Block * FlatNode -> fn_BlockSize + FlatNode -> fn_FirstBlock;
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Length = FlatNode -> fn_BlockSize;
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Data = DiskBuffer;
-
- if(DoIO(FlatNode -> fn_DiskRequest))
- {
- if(ShowRequest(Caller -> pr_WindowPtr,ERR_UNREADABLE,FlatNode -> fn_Name))
- goto Retry1;
- else
- return(BytesWritten);
- }
-
- Length = FlatNode -> fn_BlockSize - Offset;
-
- if(Length > Size)
- Length = Size;
-
- memcpy(&DiskBuffer[Offset],Buffer,Length);
-
- Retry2: FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = CMD_WRITE;
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Offset = Block * FlatNode -> fn_BlockSize + FlatNode -> fn_FirstBlock;
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Length = FlatNode -> fn_BlockSize;
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Data = DiskBuffer;
-
- if(DoIO(FlatNode -> fn_DiskRequest))
- {
- if(ShowRequest(Caller -> pr_WindowPtr,ERR_WRITEERROR,FlatNode -> fn_Name))
- goto Retry2;
- else
- return(BytesWritten);
- }
-
- Buffer = &Buffer[Length];
-
- Size -= Length;
-
- BytesWritten += Length;
-
- Block++;
-
- Offset = 0;
- }
- else
- {
- if(Size > FlatNode -> fn_BlockSize)
- Length = FlatNode -> fn_BlockSize;
- else
- {
- if(Size < FlatNode -> fn_BlockSize)
- memset(DiskBuffer,0,FlatNode -> fn_BlockSize);
-
- Length = Size;
- }
-
- memcpy(DiskBuffer,Buffer,Length);
-
- Retry3: FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = CMD_WRITE;
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Offset = Block * FlatNode -> fn_BlockSize + FlatNode -> fn_FirstBlock;
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Length = FlatNode -> fn_BlockSize;
- FlatNode -> fn_DiskRequest -> iotd_Req . io_Data = DiskBuffer;
-
- if(DoIO(FlatNode -> fn_DiskRequest))
- {
- if(ShowRequest(Caller -> pr_WindowPtr,ERR_WRITEERROR,FlatNode -> fn_Name))
- goto Retry1;
- else
- return(BytesWritten);
- }
-
- Buffer = &Buffer[Length];
-
- Size -= Length;
-
- BytesWritten += Length;
-
- Block++;
- }
- }
- }
-
- return(BytesWritten);
- }
-