📄 api.c
字号:
/****************************************************************************
PO_READ - Read from a file.
Description
Attempt to read count bytes from the current file pointer of file at fd
and put them in buf. The file pointer is updated.
Returns
Returns the number of bytes read or -1 on error.
If the return value is ((word) ~0) (word) -1 xn_getlasterror() will be set
with one of the following:
PENBADF - File descriptor invalid
PENOSPC - File IO error
*****************************************************************************/
//DM: added: po_read() shell and renamed original to _po_read()
/****************************************************************************
AM: To fix for 32 bit compile, created a shell which returns an int value so
that a comparison to -1 will work under 32 bits. Renamed original to _po_read.
*****************************************************************************/
word _po_read(PCFD fd, byte *buf, word count);
int po_read(PCFD fd, byte *buf, word count) /*__fn__*/
{
word return_value;
return_value = _po_read(fd, buf, count);
if (return_value == 0xFFFF)
return(-1);
else
return(return_value);
}
word _po_read(PCFD fd, byte *buf, word count) /*__fn__*/
{
PC_FILE *pfile;
word block_in_cluster;
word byte_offset_in_block;
word n_bytes;
CLUSTERTYPE next_cluster;/* FAT32 */
CLUSTERTYPE n_clusters; /* FAT32 */
dword block_to_read;
DDRIVE *pdrive;
dword saved_ptr;
dword saved_ptr_block;
CLUSTERTYPE saved_ptr_cluster; /* FAT32 */
word n_left;
word n_to_read;
CLUSTERTYPE utemp;
BLKBUFF *local_buf; /* FAT32 */
int p_errno;
word ret_val;
CHECK_MEM(word, ~0) /* Make sure memory is initted */
OS_FS_ENTER()
p_errno = 0;
/* Get the FILE. */
if ( (pfile = pc_fd2file(fd, 0)) == 0)
{
p_errno = PEBADF;
ret_val = (word) ~0;
goto return_error;
}
/* return 0 bytes read if bad arguments */
if (!count || !buf)
{
ret_val = 0;
goto return_error;
}
OS_CLAIM_FSCRITICAL()
if (pfile->fptr >= pfile->pobj->finode->fsize) /* Dont read if done */
{
ret_val = 0;
OS_RELEASE_FSCRITICAL()
goto return_error;
}
OS_RELEASE_FSCRITICAL()
pdrive = pfile->pobj->pdrive;
OS_CLAIM_LOGDRIVE(pdrive->driveno) /* Register Drive in use */
/* Grab exclusive access to the drobj */
/* Set the cluster and block file pointers if not already set */
_synch_file_ptrs(pfile);
saved_ptr = pfile->fptr;
saved_ptr_block = pfile->fptr_block;
saved_ptr_cluster = pfile->fptr_cluster;
/* Truncate the read count if we need to */
if ( (pfile->fptr + count) >= pfile->pobj->finode->fsize)
count = (word) (pfile->pobj->finode->fsize - pfile->fptr);
n_left = count;
while (n_left)
{
block_in_cluster = (word) (pfile->fptr & pdrive->byte_into_cl_mask);
block_in_cluster >>= 9;
block_to_read = pfile->fptr_block + block_in_cluster;
/* how many clusters are left */
n_to_read = (word) ( (n_left + 511) >> 9 );
n_clusters = (CLUSTERTYPE) ((n_to_read+pdrive->secpalloc-1) >> pdrive->log2_secpalloc); /* FAT32 */
/* how many contiguous clusters can we get ? <= n_clusters */
n_clusters = pc_get_chain(pdrive, pfile->fptr_cluster,
&next_cluster, n_clusters);
if (!n_clusters)
goto ret_bad_f;
/* Are we inside a block */
if ( (pfile->fptr & 0x1ffL) || (n_left < 512) )
{
byte_offset_in_block = (word) (pfile->fptr & 0x1ffL);
/* READ - Use the block buffer pool to read for us */
local_buf = pc_read_blk(pdrive, block_to_read);
if (!local_buf)
goto ret_bad_f;
/* Copy source data to the local buffer */
n_bytes = (word) (512 - byte_offset_in_block);
if (n_bytes > n_left)
n_bytes = n_left;
copybuff(buf, &(local_buf->data[byte_offset_in_block]), n_bytes);
/* Release the buffer. and discard it */
pc_free_buf(local_buf, TRUE);
buf += n_bytes;
n_left = (word) (n_left - n_bytes);
pfile->fptr += n_bytes;
/* Are we on a cluster boundary ? */
if (!(pfile->fptr & pdrive->byte_into_cl_mask))
{
if (--n_clusters) /* If contiguous */
{
pfile->fptr_block += pdrive->secpalloc;
pfile->fptr_cluster += (CLUSTERTYPE)1;
}
else
{
pfile->fptr_cluster = next_cluster;
pfile->fptr_block = pc_cl2sector(pdrive, next_cluster);
} /* if (--nclusters) {} else {}; */
} /* if (!(pfile->fptr & pdrive->byte_into_cl_mask)) */
} /* if ( (pfile->fptr & 0x1ff) || (n_left < 512) ) */
else
{
/* Read as many blocks as possible */
/* How many blocks in the current chain */
n_to_read = (word) (n_clusters << pdrive->log2_secpalloc);
/* subtract out any leading blocks */
n_to_read = (word) (n_to_read - block_in_cluster);
/* How many blocks yet to read */
utemp = (word) (n_left >> 9);
/* take the smallest of the two */
if (n_to_read > (word)utemp)
n_to_read = (word)utemp;
if (n_to_read)
{
/* If we get here we need to read contiguous blocks */
block_to_read = pfile->fptr_block + block_in_cluster;
/* READ */
if (!devio_read(pdrive->driveno, block_to_read, buf, n_to_read, FALSE))
goto ret_bad_f;
n_bytes = (word) (n_to_read << 9);
buf += n_bytes;
n_left= (word)(n_left - n_bytes);
pfile->fptr += n_bytes;
/* if we advanced to a cluster boundary advance the
cluster pointer */
/* utemp ==s how many clusters we read */
utemp =(word) ((n_to_read+block_in_cluster) >> pdrive->log2_secpalloc);
if (utemp == n_clusters)
{
pfile->fptr_cluster = next_cluster;
}
else
{
/* advance the pointer as many as we read */
pfile->fptr_cluster = (CLUSTERTYPE) (pfile->fptr_cluster + utemp); /* FAT32 */
}
pfile->fptr_block = pc_cl2sector(pdrive, pfile->fptr_cluster);
}
}
} /* while n_left */
OS_RELEASE_LOGDRIVE(pdrive->driveno)
/* Restore the kernel state */
set_errno(p_errno);
OS_FS_EXIT()
return(count);
ret_bad_f:
/* Restore pointers and return */
pfile->fptr = saved_ptr;
pfile->fptr_block = saved_ptr_block;
pfile->fptr_cluster = saved_ptr_cluster;
p_errno = PENOSPC;
OS_RELEASE_LOGDRIVE(pdrive->driveno)
ret_val = (word) ~0;
return_error:
/* Restore the kernel state */
set_errno(p_errno);
OS_FS_EXIT()
return(ret_val);
}
RTFS_FILE(write.c, po_write)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
#if (RTFS_WRITE)
/***************************************************************************
PO_WRITE - Write to a file.
Description
Attempt to write count bytes from buf to the current file pointer of file
at fd. The file pointer is updated.
Returns
Returns the number of bytes written or -1 on error.
If the return value is -1 xn_getlasterror() will be set with one of the following:
PENBADF - File descriptor invalid or open read only
PENOSPC - Write failed. Presumably because of no space
****************************************************************************/
//DM: added: po_write() shell and renamed original to _po_write()
/***************************************************************************
AM: Created shell routine with return value of int so will work properly under
32 bit compile for negative number.
****************************************************************************/
word _po_write(PCFD fd, byte *buf, word count);
int po_write(PCFD fd, byte *buf, word count) /*__fn__*/
{
#if (RTFS_WRITE)
word return_value = _po_write(fd, buf, count);
if (return_value == 0xFFFF)
return(-1);
else
return(return_value);
#else
return(-1);
#endif
}
#if (RTFS_WRITE)
word _po_write(PCFD fd, byte *buf, word count) /*__fn__*/
{
PC_FILE *pfile;
DDRIVE *pdrive;
word block_in_cluster;
word byte_offset_in_block;
dword saved_ptr;
dword saved_ptr_block;
CLUSTERTYPE next_cluster; /* FAT32 */
CLUSTERTYPE saved_ptr_cluster; /* FAT32 */
CLUSTERTYPE n_clusters; /* FAT32 */
dword ltemp;
word n_bytes;
word n_to_write;
word n_left;
word n_blocks_left;
dword alloced_size;
dword block_to_write;
BLKBUFF *local_buf;
int p_errno;
word ret_val;
CHECK_MEM(word, ~0) /* Make sure memory is initted */
/* Return 0 (none written) on bad args */
if (!count || !buf)
{
return(0);
}
OS_FS_ENTER()
p_errno = 0;
/* Get the FILE. must be open for write */
pfile = pc_fd2file(fd, PO_WRONLY|PO_RDWR);
if (!pfile)
{
p_errno = PEBADF;
ret_val = (word) ~0;
goto return_error;
}
pdrive = pfile->pobj->pdrive;
OS_CLAIM_LOGDRIVE(pdrive->driveno) /* Register drive in use (non excl) */
/* Only one process may write at a time */
/*
* Note the file's finode is LOCKED below so the code needn't be
* reentrant relative to the finode.
*/
/* if the file is zero sized make sure the current cluster pointer
is invalid */
if (!pfile->pobj->finode->fsize)
pfile->fptr_cluster = 0;
/* 11-20-99 - Bug fix - to register file size and flush if we run out of space */
/* Round the file size up to its cluster size by adding in clustersize-1
and masking off the low bits */
alloced_size = (pfile->pobj->finode->fsize + pdrive->byte_into_cl_mask) &
~(pdrive->byte_into_cl_mask);
/* 11-20-99 - End Bug fix section : more below */
/* Set the cluster and block file pointers if not already set */
_synch_file_ptrs(pfile);
saved_ptr = pfile->fptr;
saved_ptr_block = pfile->fptr_block;
saved_ptr_cluster = pfile->fptr_cluster;
/* Seek to the end if append mode */
if (pfile->flag & PO_APPEND)
{
if (pfile->pobj->finode->fsize)
{
if (_po_lseek(pfile, 0L, PSEEK_END) == -1L)
goto ret_bad_f;
_synch_file_ptrs(pfile);
}
}
/* calculate initial values */
n_left = count;
/* 11-20-99 - Bug fix: moved alloced_size calculation to above append */
/* 11-20-99 - End Bug fix section : more below */
while (n_left)
{
block_in_cluster = (word) (pfile->fptr & pdrive->byte_into_cl_mask);
block_in_cluster >>= 9;
if (pfile->fptr >= alloced_size)
{
/* Extending the file */
n_blocks_left = (word) ((n_left + 511) >> 9);
/* how many clusters are left-
* assume 1 for the current cluster.
* subtract out the blocks in the current
* round up by adding secpalloc-1 and then
* divide by sectors per cluster
| n_clusters = 1 +
| (n_blocks_left-
| (pdrive->secpalloc-block_in_cluster)
| + pdrive->secpalloc-1) >> pdrive->log2_secpalloc;
==>
*/
n_clusters = ( CLUSTERTYPE ) (1 + /* FAT32 */
((n_blocks_left + block_in_cluster -1) >> pdrive->log2_secpalloc));/* FAT32 */
/* Call pc_alloc_chain to build a chain up to n_cluster clusters
long. Return the first cluster in pfile->fptr_cluster and
return the # of clusters in the chain. If pfile->fptr_cluster
is non zero link the current cluster to the new one */
n_clusters = pc_alloc_chain(pdrive, &(pfile->fptr_cluster), n_clusters);
if (!n_clusters)
goto ret_bad_f;
/* Calculate the last cluster in this chain. */
next_cluster = (CLUSTERTYPE) (pfile->fptr_cluster + n_clusters -1);/* FAT32 */
/* link the chain to the directory object if just starting */
if (!pc_finode_cluster(pfile->pobj->pdrive,pfile->pobj->finode))/* FAT32 */
pc_pfinode_cluster(pfile->pobj->pdrive,pfile->pobj->finode,pfile->fptr_cluster);/* FAT32 */
/* calculate the new block pointer */
pfile->fptr_block = pc_cl2sector(pdrive, pfile->fptr_cluster);
/* calculate amount of space used by the file */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -