📄 nu_file.c
字号:
/* Restore pointers and return */
pfile->fptr = saved_ptr;
pfile->fptr_block = saved_ptr_block;
pfile->fptr_cluster = saved_ptr_cluster;
}
else
{
ret_val = count;
}
PC_INODE_EXIT(pfile->pobj->finode)
PC_DRIVE_EXIT(pdrive->driveno)
}
/* Restore the kernel state */
PC_FS_EXIT()
return(ret_val);
}
/************************************************************************
* FUNCTION
*
* NU_Write
*
* DESCRIPTION
*
* Attempt to write count bytes from buf to the current file
* pointer of file at fd. The file pointer is updated.
*
* AUTHOR
*
* Takahiro Takahashi
*
* INPUTS
*
* fd File descriptor.
* *buf Pointer of buffer to write.
* count Write byte count.
*
* OUTPUTS
*
* Returns the number of bytes written or negative value on error.
* If the return value is negative, the meaning is follows:
*
* INT32 A non-negative integer to be
* used as a number of bytes
* written.
* NUF_BAD_USER Not a file user.
* NUF_BADPARM Invalid parameter specified.
* NUF_BADFILE File descriptor invalid.
* NUF_ACCES Not a PO_WRONLY or PO_RDWR
* open flag or file
* attributes is ARDONLY.
* NUF_NOSPC Write failed. Presumably
* because of no space.
* NUF_IO_ERROR IO error occured.
* NUF_INTERNAL Nucleus FILE internal error.
*
* fs_user->p_errno is set to one of these values
*
* PEBADF Invalid file descriptor.
* PEACCES Attempt to open a read only
* file or a special
* (directory) file.
* PENOSPC Create failed.
*
*************************************************************************/
INT32 NU_Write(INT fd, CHAR *buf, INT32 count)
{
PC_FILE *pfile;
DDRIVE *pdrive;
UINT32 block_in_cluster;
UINT16 byte_offset_in_block;
UINT32 next_cluster;
UINT32 saved_ptr;
UINT32 saved_ptr_block;
UINT32 saved_ptr_cluster;
UINT32 ltemp;
UINT32 n_bytes;
UINT32 n_to_write;
UINT32 n_left;
UINT32 n_blocks_left;
UINT16 nblocks;
UINT32 n_clusters;
UINT32 alloced_size;
UINT32 block_to_write;
UINT8 local_buf[512];
INT32 ret_val;
STATUS status;
PC_FS_ENTER() /* Must be last line in declarations */
CHECK_USER(INT32, NUF_BAD_USER) /* Check if a valid user if multitasking */
fs_user->p_errno = 0;
/* Get the FILE. Second argument is ignored */
if ( (pfile = pc_fd2file(fd)) == NULL )
{
fs_user->p_errno = PEBADF;
ret_val = NUF_BADFILE;
}
/* Check the file attributes */
else if (pfile->pobj->finode->fattribute & ARDONLY)
{
fs_user->p_errno = PEACCES;
ret_val = NUF_ACCES;
}
/* Opened for write ? */
else if ( !((pfile->flag & PO_WRONLY) || (pfile->flag & PO_RDWR)) )
{
fs_user->p_errno = PEACCES;
ret_val = NUF_ACCES;
}
/* Return 0 (none written) on bad args */
else if (!count)
{
ret_val = 0;
}
/* Return -1 bad parameter */
else if ( count < 0 || !buf )
{
ret_val = NUF_BADPARM;
}
else
{
pdrive = pfile->pobj->pdrive;
PC_DRIVE_ENTER(pdrive->driveno, NO) /* Register drive in use (non excl) */
/* Only one process may write at a time */
PC_INODE_ENTER(pfile->pobj->finode, YES)
/* if the file is zero sized make sure the current cluster pointer
is invalid */
if (!pfile->pobj->finode->fsize)
pfile->fptr_cluster = 0L;
/* 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;
/* calculate initial values */
n_left = count;
/* 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);
while (n_left)
{
block_in_cluster = (UINT32) (pfile->fptr & pdrive->byte_into_cl_mask);
block_in_cluster >>= 9;
if (pfile->fptr >= alloced_size)
{
/* Extending the file */
n_blocks_left = (UINT32) ((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 = ( UINT32) (1 +
((n_blocks_left + block_in_cluster - 1) >> pdrive->log2_secpalloc));
if (pdrive->fasize == 8) /* FAT32 */
{
/* Calculate file total size */
ltemp = alloced_size >> pdrive->log2_secpalloc;
ltemp >>= 9; /* Divide by 512 */
ltemp += n_clusters;
/* Chech the maximum file size(4GB) */
if (pdrive->maxfsize_cluster < ltemp)
{
ret_val = NUF_MAXFILE_SIZE;
break; /* Exit from write loop */
}
}
/* 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 */
PC_FAT_ENTER(pdrive->driveno)
status = pc_alloc_chain(&n_clusters, pdrive, &(pfile->fptr_cluster), n_clusters);
PC_FAT_EXIT(pdrive->driveno)
if (status != NU_SUCCESS)
{
ret_val = (INT32)status;
break; /* Exit from write loop */
}
/* Calculate the last cluster in this chain. */
next_cluster = (UINT32) (pfile->fptr_cluster + n_clusters - 1);
/* link the chain to the directory object if just starting */
if (!pfile->pobj->finode->fcluster)
pfile->pobj->finode->fcluster = pfile->fptr_cluster;
/* calculate the new block pointer */
pfile->fptr_block = pc_cl2sector(pdrive, pfile->fptr_cluster);
/* calculate amount of space used by the file */
ltemp = n_clusters << pdrive->log2_secpalloc; ltemp <<= 9;
alloced_size += ltemp;
}
else /* Not extending the file. (writing inside the file) */
{
n_blocks_left = (UINT32) ((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 = (UINT32) (1 +
((n_blocks_left + block_in_cluster - 1) >> pdrive->log2_secpalloc));
/* how many contiguous clusters can we get ? <= n_clusters */
PC_FAT_ENTER(pdrive->driveno)
ret_val = pc_get_chain(pdrive, pfile->fptr_cluster,
&next_cluster, n_clusters);
PC_FAT_EXIT(pdrive->driveno)
/* IO error occuered */
if (ret_val <= 0)
{
break; /* Exit from write loop */
}
n_clusters = ret_val;
}
/* Are we inside a block */
if ( (pfile->fptr & 0x1ffL) || (n_left < 512) )
{
block_in_cluster = (UINT32) (pfile->fptr & pdrive->byte_into_cl_mask);
block_in_cluster >>= 9;
block_to_write = pfile->fptr_block + block_in_cluster;
byte_offset_in_block = (UINT16) (pfile->fptr & 0x1ffL);
/* Copy source data to the local buffer */
n_bytes = (UINT32) (512 - byte_offset_in_block);
if (n_bytes > n_left)
n_bytes = n_left;
PC_DRIVE_IO_ENTER(pdrive->driveno)
/* File pointer is not at block boundary, then we need to read the block. */
/* Read */
if ( !pc_bdevsw[pdrive->driveno].io_proc(pdrive->driveno,
block_to_write, local_buf, (UINT16) 1, YES) )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -