mirror of
https://github.com/GnoConsortium/gno.git
synced 2024-10-09 12:57:08 +00:00
7ec020a057
delimiters.
286 lines
10 KiB
C
286 lines
10 KiB
C
|
|
/*
|
|
* Copyright (c) Kopriha Software, 1990-1991
|
|
* All Rights Reserved
|
|
*
|
|
* Write.CC
|
|
*
|
|
* Description:
|
|
* This module exists to abstract the data of the file I/O
|
|
* primitives of GS/OS.
|
|
*
|
|
*
|
|
* History:Oct 13, 1990 Dave Created this file
|
|
*
|
|
* Feb 25, 1991 Dave Added I/O buffering
|
|
*
|
|
* May 26, 1991 Dave Added set EOF
|
|
*
|
|
* Jun 07, 1991 Dave Broke the single source into lots
|
|
* of small sources so we can build
|
|
* a library to use...
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* define DEBUG_CODE
|
|
* - add # to define to create the local
|
|
* debug code (IE:module)
|
|
*/
|
|
|
|
#ifndef _KS_FILEIO_
|
|
#include "ks.fileio.h"
|
|
#endif
|
|
|
|
#pragma noroot
|
|
|
|
|
|
/* ****************************************************************** *
|
|
* ks_file_write - Perform an write to an open file (possibly using *
|
|
* an internal buffer). *
|
|
* *
|
|
* History: Feb 27, 1991 Dave Created this routine *
|
|
* ****************************************************************** */
|
|
|
|
#undef ROUTINE_NAME
|
|
#define ROUTINE_NAME "ks_file_write"
|
|
|
|
KS_E_ERROR ks_file_write(KS_FILE_PTR file_ptr,
|
|
LongWord position,
|
|
LongWord data_size,
|
|
Pointer data_buffer)
|
|
{
|
|
/* ************************************************************** *
|
|
* Local declarations: *
|
|
* ************************************************************** */
|
|
|
|
KS_E_ERROR error; /* Holds error codes for subroutine*/
|
|
/* calls */
|
|
LongWord data_offset; /* Offset into the buffer to return*/
|
|
LongWord remaining_space; /* Space remaining in file buffer */
|
|
LongWord buffer_request; /* Size of each copy from the */
|
|
/* file buffer */
|
|
|
|
|
|
ROUTINE_ENTER();
|
|
|
|
|
|
/* ************************************************************** *
|
|
* Verify the structure ID passed in is the correct one. *
|
|
* ************************************************************** */
|
|
|
|
if (file_ptr->struct_id != KS_FILE_ID)
|
|
{
|
|
KS_ERROR(KS_E_INVALID_STRUCT_ID, KS_FILE_ID);
|
|
};
|
|
|
|
|
|
/* ************************************************************** *
|
|
* Zero the number of bytes transfered in the KS_FILE structure. *
|
|
* ************************************************************** */
|
|
|
|
file_ptr->data_size = 0;
|
|
|
|
|
|
/* ************************************************************** *
|
|
* If there is a buffer, then lets put data into the file buffer.*
|
|
* ************************************************************** */
|
|
|
|
if (file_ptr->buffer_size != NULL)
|
|
{
|
|
|
|
/* ********************************************************** *
|
|
* Loop till we satisfy the request (or take an error) *
|
|
* ********************************************************** */
|
|
|
|
data_offset = 0;
|
|
|
|
while (data_size > 0)
|
|
{
|
|
|
|
/* ****************************************************** *
|
|
* Calculate the remaining space in the buffer. If *
|
|
* there is any space left in the buffer then lets copy *
|
|
* as much as we need to into the file buffer. *
|
|
* ****************************************************** */
|
|
|
|
remaining_space = (file_ptr->buffer_available) -
|
|
(file_ptr->buffer_offset);
|
|
|
|
if (remaining_space > 0)
|
|
{
|
|
buffer_request = MIN(data_size,
|
|
remaining_space);
|
|
|
|
COPY_BYTES(data_buffer,
|
|
data_offset,
|
|
file_ptr->buffer,
|
|
file_ptr->buffer_offset,
|
|
buffer_request);
|
|
|
|
/* ************************************************** *
|
|
* Now modify the parameters of the buffers by: *
|
|
* *
|
|
* 1) Adding the size of the request to the file *
|
|
* buffer ofset and the data offset (IE: Indices to *
|
|
* the file buffer and the read request buffer). *
|
|
* *
|
|
* 2) Subtracting the request size from the read *
|
|
* request size and the remaining number of *
|
|
* characters in the file buffer. *
|
|
* ************************************************** */
|
|
|
|
file_ptr->buffer_offset = file_ptr->buffer_offset +
|
|
buffer_request;
|
|
|
|
data_offset = data_offset + buffer_request;
|
|
|
|
file_ptr->data_size = data_offset;
|
|
|
|
data_size = data_size - buffer_request;
|
|
|
|
remaining_space = remaining_space - buffer_request;
|
|
};
|
|
|
|
|
|
/* ****************************************************** *
|
|
* If the file buffer is full, then we have to write it *
|
|
* to disk. The problem is that the buffer size may *
|
|
* have changed due to what our user wants (users are *
|
|
* bound to be the end of all computing...). This means *
|
|
* that we'll junp through a few hoops if we must change *
|
|
* buffer sizes - so expect some weirdness here. *
|
|
* ****************************************************** */
|
|
|
|
if (remaining_space == 0)
|
|
{
|
|
|
|
/* ************************************************** *
|
|
* Issue a Read to the file into our buffer. *
|
|
* ************************************************** */
|
|
|
|
KSf_pkts.IO.pCount = 4;
|
|
KSf_pkts.IO.refNum = file_ptr->refNum;
|
|
KSf_pkts.IO.dataBuffer = TO_POINTER(file_ptr->buffer);
|
|
KSf_pkts.IO.requestCount = file_ptr->buffer_size;
|
|
|
|
WriteGS(&KSf_pkts.IO);
|
|
|
|
if ((error = GET_ERROR()) != KS_E_SUCCESS)
|
|
{
|
|
goto EXIT_NOW;
|
|
};
|
|
|
|
file_ptr->buffer_available = file_ptr->buffer_size;
|
|
file_ptr->buffer_offset = 0;
|
|
|
|
|
|
/* ************************************************** *
|
|
* This is the above mentioned weirdness - if the *
|
|
* user specified a different size buffer we will *
|
|
* no comply with their wishes. *
|
|
* ************************************************** */
|
|
|
|
if (file_ptr->buffer_size != KSf_FileBufferSize)
|
|
{
|
|
KS_MEMORY_DEALLOCATE(file_ptr->buffer_handle,
|
|
error);
|
|
|
|
if (error != KS_E_SUCCESS)
|
|
{
|
|
goto EXIT_NOW;
|
|
};
|
|
|
|
KS_MEMORY_ALLOCATE(attrFixed + attrLocked,
|
|
KSf_FileBufferSize,
|
|
BUFFER_USERID,
|
|
file_ptr->buffer_handle,
|
|
error);
|
|
|
|
if (error != KS_E_SUCCESS)
|
|
{
|
|
goto EXIT_NOW;
|
|
};
|
|
|
|
file_ptr->buffer = (Byte *)
|
|
*(file_ptr->buffer_handle);
|
|
|
|
file_ptr->buffer_size = KSf_FileBufferSize;
|
|
|
|
file_ptr->buffer_available = KSf_FileBufferSize;
|
|
};
|
|
|
|
}; /* End if there is no remaining buffer space */
|
|
|
|
}; /* End while there are characters to be read... */
|
|
|
|
KS_SUCCESS();
|
|
|
|
}; /* End if we are doing buffer I/O from the file */
|
|
|
|
|
|
|
|
|
|
/* ************************************************************** *
|
|
* Ok, we've done enough buffering... lets do some real output...*
|
|
* *
|
|
* Position the 'mark' (where we will write to) in the file. *
|
|
* Note: We'll move the mark only if our user asks us to. *
|
|
* ************************************************************** */
|
|
|
|
if (position != KS_NEXT_FILE_POSITION)
|
|
{
|
|
KSf_pkts.position.pCount = 3;
|
|
KSf_pkts.position.refNum = file_ptr->refNum;
|
|
KSf_pkts.position.base = startPlus;
|
|
KSf_pkts.position.displacement = position;
|
|
|
|
SetMarkGS(&KSf_pkts.position);
|
|
|
|
if ((error = GET_ERROR()) != KS_E_SUCCESS)
|
|
{
|
|
goto EXIT_NOW;
|
|
};
|
|
|
|
}; /* End if we must change the file position */
|
|
|
|
|
|
/* ************************************************************** *
|
|
* Setup the I/O packet and write what our user is asking for. *
|
|
* ************************************************************** */
|
|
|
|
KSf_pkts.IO.pCount = 4;
|
|
KSf_pkts.IO.refNum = file_ptr->refNum;
|
|
KSf_pkts.IO.dataBuffer = data_buffer;
|
|
KSf_pkts.IO.requestCount = data_size;
|
|
|
|
WriteGS(&KSf_pkts.IO);
|
|
|
|
if ((error = GET_ERROR()) != KS_E_SUCCESS)
|
|
{
|
|
goto EXIT_NOW;
|
|
};
|
|
|
|
|
|
/* ************************************************************** *
|
|
* Save the number of bytes transfered in the KS_FILE structure. *
|
|
* ************************************************************** */
|
|
|
|
file_ptr->data_size = KSf_pkts.IO.transferCount;
|
|
|
|
|
|
/* ************************************************************** *
|
|
* Return the status back to our caller. *
|
|
* ************************************************************** */
|
|
|
|
EXIT_NOW:
|
|
|
|
if (error != KS_E_SUCCESS)
|
|
{
|
|
KS_ERROR(error, KS_FILE_ID);
|
|
};
|
|
|
|
KS_SUCCESS();
|
|
|
|
} /* End of ks_file_write() */
|