mirror of
https://github.com/rvtr/twl_wrapsdk.git
synced 2025-10-31 06:11:10 -04:00
git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/twl_wrapsdk/trunk@96 4ee2a332-4b2b-5046-8439-1ba90f034370
829 lines
31 KiB
C
829 lines
31 KiB
C
/*
|
||
* EBS - RTFS (Real Time File Manager)
|
||
*
|
||
* Copyright EBS Inc. 1987-2003
|
||
* All rights reserved.
|
||
* This code may not be redistributed in source or linkable object form
|
||
* without the consent of its author.
|
||
*/
|
||
/* APIWRITE.C - Contains user api level file IO source code.
|
||
|
||
The following routines are included:
|
||
po_write - Write Bytes to a file.
|
||
po_flush - Flush an open file
|
||
po_trunc - Truncate an open file
|
||
pc_set_attributes - Set File Attributes
|
||
pc_diskflush - Flush the FAT and all files on a disk
|
||
*/
|
||
|
||
#include <rtfs.h>
|
||
|
||
/***************************************************************************
|
||
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.
|
||
|
||
errno is set to one of the following
|
||
0 - No error
|
||
PEBADF - Invalid file descriptor
|
||
PEACCES - File is read only
|
||
PEIOERRORWRITE - Error performing write
|
||
PEIOERRORREAD - Error reading block for merge and write
|
||
PENOSPC - Disk full
|
||
An ERTFS system error
|
||
****************************************************************************/
|
||
|
||
int po_write(PCFD fd, byte *in_buff, int count) /*__apifn__*/
|
||
{
|
||
PC_FILE *pfile;
|
||
DDRIVE *pdrive;
|
||
dword block_in_cluster;
|
||
dword byte_offset_in_block;
|
||
dword n_blocks_left;
|
||
dword n_to_write, n_w_to_write;
|
||
CLUSTERTYPE next_cluster;
|
||
CLUSTERTYPE n_clusters;
|
||
dword ltemp;
|
||
int n_bytes;
|
||
int n_written;
|
||
int n_left;
|
||
dword alloced_size;
|
||
dword block_to_write;
|
||
int end_of_chain;
|
||
BOOLEAN extending_file;
|
||
int ret_val;
|
||
int p_errno;
|
||
|
||
CHECK_MEM(int, -1) /* Make sure memory is initted */
|
||
|
||
/* Return 0 (none written) on bad args */
|
||
if (!count)
|
||
return(0);
|
||
|
||
p_errno = 0;
|
||
rtfs_set_errno(0); /* po_write: clear error status */
|
||
/* Get the FILE. must be open for write */
|
||
/* Get the file structure and semaphore lock the drive */
|
||
pfile = pc_fd2file(fd, PO_WRONLY|PO_RDWR);
|
||
if (!pfile)
|
||
{ /* fd2file set errno */
|
||
ret_val = -1;
|
||
goto return_unlocked;
|
||
}
|
||
pdrive = pfile->pobj->pdrive;
|
||
/* Only one process may write at a time */
|
||
/* if the file is zero sized make sure the current cluster pointer
|
||
is invalid */
|
||
if (!pfile->pobj->finode->fsize)
|
||
pfile->fptr_cluster = 0;
|
||
|
||
/* 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);
|
||
if (alloced_size < pfile->pobj->finode->fsize)
|
||
alloced_size = 0xffffffff;
|
||
|
||
/* Set the cluster and block file pointers if not already set */
|
||
if (!_synch_file_ptrs(pfile))
|
||
{ /* _synch_file_ptrs set errno */
|
||
ret_val = -1;
|
||
goto return_locked;
|
||
}
|
||
/* Seek to the end if append mode */
|
||
if (pfile->flag & PO_APPEND)
|
||
{
|
||
if (pfile->pobj->finode->fsize)
|
||
{
|
||
if (!_po_ulseek(pfile, 0L, <emp, PSEEK_END))
|
||
{ /* po_ulseek will set error status */
|
||
ret_val = -1;
|
||
goto return_locked;
|
||
}
|
||
if (!_synch_file_ptrs(pfile))
|
||
{ /* _synch_file_ptrs set errno */
|
||
ret_val = -1;
|
||
goto return_locked;
|
||
}
|
||
}
|
||
}
|
||
/* Check if this write will wrap past 4 Gigabytes
|
||
if so truncate the count to 4 Gig minus 1*/
|
||
ltemp = pfile->fptr + count;
|
||
if (ltemp < pfile->fptr)
|
||
{
|
||
#if (RTFS_TRUNCATE_WRITE_TO_MAX)
|
||
ltemp = 0xffffffff;
|
||
count = ltemp - pfile->fptr;
|
||
#else
|
||
p_errno = PETOOLARGE;
|
||
ret_val = -1;
|
||
goto return_locked;
|
||
#endif
|
||
}
|
||
if (ltemp > RTFS_MAX_FILE_SIZE)
|
||
{
|
||
#if (RTFS_TRUNCATE_WRITE_TO_MAX)
|
||
ltemp = RTFS_MAX_FILE_SIZE;
|
||
count = ltemp - pfile->fptr;
|
||
#else
|
||
p_errno = PETOOLARGE;
|
||
ret_val = -1;
|
||
goto return_locked;
|
||
#endif
|
||
}
|
||
|
||
/* calculate initial values */
|
||
n_left = count;
|
||
n_written = 0;
|
||
|
||
while (n_left)
|
||
{
|
||
end_of_chain = 0;
|
||
block_in_cluster = (dword) (pfile->fptr & pdrive->byte_into_cl_mask);
|
||
block_in_cluster >>= 9;
|
||
|
||
if (pfile->fptr >= alloced_size)
|
||
{
|
||
/* Extending the file */
|
||
extending_file = TRUE;
|
||
ltemp = (dword) n_left;
|
||
n_blocks_left = (dword) ((ltemp + 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 +
|
||
((n_blocks_left + block_in_cluster -1) >> pdrive->log2_secpalloc));
|
||
|
||
/* 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 = FATOP(pdrive)->fatop_alloc_chain(pdrive, &(pfile->fptr_cluster), n_clusters, TRUE);
|
||
if (!n_clusters)
|
||
{ /* Allocchain will set errno to PENOSPC or an IO or internal error */
|
||
break;
|
||
}
|
||
|
||
/* Calculate the last cluster in this chain. */
|
||
next_cluster = (CLUSTERTYPE) (pfile->fptr_cluster + n_clusters -1);
|
||
/* link the chain to the directory object if just starting */
|
||
if (!pc_finode_cluster(pfile->pobj->pdrive,pfile->pobj->finode))
|
||
pc_pfinode_cluster(pfile->pobj->pdrive,pfile->pobj->finode,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;
|
||
if (alloced_size < ltemp)
|
||
alloced_size = 0xffffffff;
|
||
|
||
}
|
||
else /* Not extending the file. (writing inside the file) */
|
||
{
|
||
extending_file = FALSE;
|
||
ltemp = (dword) n_left;
|
||
n_blocks_left = (dword) ((ltemp + 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 +
|
||
((n_blocks_left + block_in_cluster -1) >> pdrive->log2_secpalloc));
|
||
|
||
/* how many contiguous clusters can we get ? <= n_clusters */
|
||
end_of_chain = 0;
|
||
n_clusters = FATOP(pdrive)->fatop_get_chain(pdrive, pfile->fptr_cluster,
|
||
&next_cluster, n_clusters, &end_of_chain);
|
||
if (!n_clusters)
|
||
{
|
||
/* get_chain already set errno */
|
||
ret_val = (int) -1;
|
||
goto return_locked;
|
||
}
|
||
}
|
||
|
||
/* Are we inside a block */
|
||
if ( (pfile->fptr & 0x1ffL) || (n_left < 512) )
|
||
{
|
||
block_in_cluster = (dword) (pfile->fptr & pdrive->byte_into_cl_mask);
|
||
block_in_cluster >>= 9;
|
||
block_to_write = pfile->fptr_block + block_in_cluster;
|
||
|
||
byte_offset_in_block = (dword) (pfile->fptr & 0x1ffL);
|
||
|
||
/* Copy source data to the local buffer */
|
||
n_bytes = (int) (512 - byte_offset_in_block);
|
||
if (n_bytes > n_left)
|
||
n_bytes = n_left;
|
||
/* READ - Use the block buffer pool to read for us */
|
||
if (!pc_load_file_buffer(pfile, block_to_write))
|
||
break; /* load_file_block set errno */
|
||
/* Merge the data and mark it dirty */
|
||
if (in_buff)
|
||
copybuff(&(pfile->pobj->finode->pfile_buffer->data[byte_offset_in_block]), in_buff, n_bytes);
|
||
pfile->pobj->finode->file_buffer_dirty = 1;
|
||
if (!(pfile->pobj->finode->openflags & OF_BUFFERED))
|
||
{
|
||
/* Write the buffer. and discard it */
|
||
if (!pc_load_file_buffer(pfile, 0))
|
||
break; /* load_file_block set errno */
|
||
}
|
||
if (in_buff)
|
||
in_buff += n_bytes;
|
||
|
||
n_left = (int) (n_left - n_bytes);
|
||
pfile->fptr += n_bytes;
|
||
n_written += 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
|
||
{
|
||
/* Check for corrupted file
|
||
We are about to advance fptr_cluster by
|
||
making next_cluster the current cluster.
|
||
If the file pointer is less than the current file
|
||
size, but we are at the end of chain we know
|
||
that there is no next_cluster and the chain is
|
||
corrupted. It shorter than the file size indicates.
|
||
Reset the byte pointer to match the current
|
||
block and cluster pointers, set errno to
|
||
PEINVALIDCLUSTER, return -1
|
||
We check against alloced_size here because next
|
||
time through the write routine will check and if
|
||
fptr >= alloced_size then it will link a new cluster
|
||
to the file.
|
||
*/
|
||
if (!extending_file &&
|
||
pfile->fptr < alloced_size &&
|
||
end_of_chain)
|
||
{
|
||
pfile->fptr -= n_bytes;
|
||
p_errno = PEINVALIDCLUSTER;
|
||
ret_val = -1;
|
||
goto return_locked;
|
||
}
|
||
else
|
||
{
|
||
/* NOTE: Put the next cluster into the pointer. If we had
|
||
alloced a chain this value is the last cluster in
|
||
the chain and does not concur with the byte file pointer.
|
||
This is not a problem since the cluster pointer is known
|
||
to be off at this point any (fptr>=alloced_size) */
|
||
pfile->fptr_cluster = next_cluster;
|
||
pfile->fptr_block = pc_cl2sector(pdrive, next_cluster);
|
||
}
|
||
} /* if (--nclusters) {} else {}; */
|
||
} /* if (!(pfile->fptr & byte_into_cl_mask)) */
|
||
} /* if ( (pfile->fptr & 0x1ff) || (n_left < 512) ) */
|
||
|
||
if (n_clusters && (n_left>511))
|
||
{
|
||
/* If we get here we need to write contiguous blocks */
|
||
block_in_cluster = (dword) (pfile->fptr & pdrive->byte_into_cl_mask);
|
||
block_in_cluster >>= 9;
|
||
block_to_write = pfile->fptr_block + block_in_cluster;
|
||
/* how many do we write ? */
|
||
ltemp = (dword) n_left;
|
||
n_blocks_left = (dword) (ltemp >> 9);
|
||
n_to_write = (dword) ((n_clusters << pdrive->log2_secpalloc) - block_in_cluster);
|
||
|
||
if (n_to_write > n_blocks_left)
|
||
{
|
||
n_to_write = n_blocks_left;
|
||
|
||
/* If we are not writing to the end of the chain we may not
|
||
advance the cluster pointer to the beginning of the next
|
||
chain. We add in block_in_cluster so we account for the
|
||
partial cluster we have already seen */
|
||
next_cluster = (CLUSTERTYPE) (pfile->fptr_cluster +
|
||
((n_to_write+block_in_cluster) >> pdrive->log2_secpalloc));
|
||
}
|
||
/* Devio takes words for blocks so split it up */
|
||
ltemp = n_to_write;
|
||
while (ltemp)
|
||
{
|
||
if (ltemp > 0xffff)
|
||
n_w_to_write = 0xffff;
|
||
else
|
||
n_w_to_write = ltemp & 0xffff;
|
||
/* Set pdrive->drive_flags to tell the device driver we are perfroming
|
||
file data transfer */
|
||
pdrive->drive_flags |= DRIVE_FLAGS_FILEIO;
|
||
if (in_buff && !devio_write(pdrive->driveno, block_to_write, in_buff, (word) n_w_to_write, FALSE))
|
||
{
|
||
pdrive->drive_flags &= ~DRIVE_FLAGS_FILEIO;
|
||
/* set errno to IO error unless devio set PEDEVICE */
|
||
if (!get_errno())
|
||
p_errno = PEIOERRORWRITE;
|
||
ret_val = n_written;
|
||
goto return_locked;
|
||
}
|
||
pdrive->drive_flags &= ~DRIVE_FLAGS_FILEIO;
|
||
/* Purge the file block buffer if it was in our range, since we will overwrite */
|
||
pc_sync_file_buffer(pfile, block_to_write, n_w_to_write, FALSE);
|
||
n_bytes = (int) n_w_to_write * 512;
|
||
if (in_buff)
|
||
in_buff = in_buff + n_bytes;
|
||
block_to_write += n_w_to_write;
|
||
ltemp = ltemp - n_w_to_write;
|
||
}
|
||
/* See note above */
|
||
n_bytes = (int) n_to_write * 512;
|
||
n_left = n_left - n_bytes;
|
||
pfile->fptr += n_bytes;
|
||
n_written += n_bytes;
|
||
pfile->fptr_cluster = next_cluster;
|
||
pfile->fptr_block = pc_cl2sector(pdrive, next_cluster);
|
||
}
|
||
} /* while n_left */
|
||
ret_val = n_written;
|
||
/* If we wrote anything change the last modified time and date */
|
||
if (pfile->pobj && ret_val > 0)
|
||
{
|
||
DATESTR crdate;
|
||
pc_getsysdate(&crdate);
|
||
pfile->pobj->finode->fattribute |= ARCHIVE;
|
||
pfile->pobj->finode->ftime = crdate.time;
|
||
pfile->pobj->finode->fdate = crdate.date;
|
||
pfile->needs_flush = TRUE;
|
||
}
|
||
|
||
return_locked:
|
||
if (pfile->pobj && (pfile->fptr > pfile->pobj->finode->fsize))
|
||
{
|
||
pfile->needs_flush = TRUE;
|
||
pfile->pobj->finode->fsize = pfile->fptr;
|
||
pfile->pobj->finode->fattribute |= ARCHIVE;
|
||
}
|
||
/* If the file pointer is beyond the space allocated to the file note it.
|
||
since we may need to adjust this files cluster and block pointers
|
||
later if someone else extends the file behind our back */
|
||
if (pfile->fptr >= alloced_size)
|
||
pfile->at_eof = TRUE;
|
||
else
|
||
pfile->at_eof = FALSE;
|
||
/* If the file is open in auto flush mode flush directory entry changes to disk */
|
||
if (pfile->flag & PO_AFLUSH)
|
||
if (!_po_flush(pfile))
|
||
ret_val = -1;
|
||
if (!release_drive_mount_write(pdrive->driveno))/* Release lock, unmount if aborted */
|
||
return(-1);
|
||
return_unlocked:
|
||
if (p_errno)
|
||
rtfs_set_errno(p_errno);
|
||
return(ret_val);
|
||
}
|
||
|
||
/**************************************************************************
|
||
PO_TRUNCATE - Truncate an open file.
|
||
|
||
Description
|
||
Move the file pointer offset bytes from the beginning of the file
|
||
and truncate the file beyond that point by adjusting the file size
|
||
and freeing the cluster chain past the file pointer.
|
||
|
||
Returns
|
||
Returns TRUE if successful otherwise FALSE
|
||
|
||
errno is set to one of the following
|
||
0 - No error
|
||
PEBADF - Invalid file descriptor
|
||
PEACCES - File is read only or opened more than once
|
||
PEINVALIDPARMS - Invalid or inconsistent arguments
|
||
An ERTFS system error
|
||
*****************************************************************************/
|
||
|
||
|
||
BOOLEAN po_truncate(PCFD fd, dword offset) /*__apifn__*/
|
||
{
|
||
PC_FILE *pfile;
|
||
DDRIVE *pdrive;
|
||
BOOLEAN ret_val;
|
||
CLUSTERTYPE first_cluster_to_release;
|
||
CLUSTERTYPE last_cluster_in_chain;
|
||
CLUSTERTYPE clno;
|
||
int p_errno;
|
||
dword clusters_to_release;
|
||
dword old_chain_len;
|
||
dword new_chain_len;
|
||
dword range_check;
|
||
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
|
||
|
||
p_errno = 0;
|
||
rtfs_set_errno(0); /* po_truncate: clear error status */
|
||
|
||
/* Assume failure */
|
||
ret_val = FALSE;
|
||
|
||
/* Get the FILE. must be open for write */
|
||
/* Get the file structure and semaphore lock the drive */
|
||
pfile = pc_fd2file(fd, PO_WRONLY|PO_RDWR);
|
||
/* Make sure we have write privilages */
|
||
if (!pfile)
|
||
goto return_error;
|
||
|
||
pdrive = pfile->pobj->pdrive;
|
||
|
||
/* Can only truncate a file that you hold exclusively */
|
||
if (pfile->pobj->finode->opencount > 1)
|
||
{
|
||
p_errno = PEACCES;
|
||
goto errex;
|
||
}
|
||
|
||
/* Set the cluster and block file pointers if not already set */
|
||
if (!_synch_file_ptrs(pfile))
|
||
{ /* _synch_file_ptrs set errno */
|
||
goto errex;
|
||
}
|
||
|
||
/* Make sure the file buffer is clear */
|
||
pc_load_file_buffer(pfile, 0);
|
||
|
||
if (offset > pfile->pobj->finode->fsize)
|
||
{
|
||
p_errno = PEINVALIDPARMS;
|
||
goto errex;
|
||
}
|
||
|
||
/* Call the internal seek routine that we share with po_lseek. Seek to
|
||
offset from the origin of zero. */
|
||
if (!_po_ulseek(pfile, offset, &offset, PSEEK_SET))
|
||
goto errex; /* _po_lseek() set errno */
|
||
else if (offset == pfile->pobj->finode->fsize)
|
||
{
|
||
ret_val = TRUE;
|
||
}
|
||
else
|
||
{
|
||
pfile->needs_flush = TRUE;
|
||
|
||
/* calculate maximum number of clusters we will need to release */
|
||
/* Round the file size up to its cluster size by adding in clustersize-1
|
||
and masking off the low bits */
|
||
old_chain_len = pc_chain_length(pdrive, pfile->pobj->finode->fsize);
|
||
new_chain_len = pc_chain_length(pdrive, offset);
|
||
|
||
clusters_to_release = old_chain_len - new_chain_len;
|
||
|
||
/* Are we on a cluster boundary ? */
|
||
if (!(offset & pdrive->byte_into_cl_mask))
|
||
{
|
||
|
||
/* Free the current cluster and beyond since we are on a cluster boundary. */
|
||
first_cluster_to_release = pfile->fptr_cluster;
|
||
/* Find the previous cluster so we can terminate the chain */
|
||
clno = pc_finode_cluster(pdrive,pfile->pobj->finode);
|
||
last_cluster_in_chain = clno;
|
||
range_check = 0;
|
||
while (clno != first_cluster_to_release)
|
||
{
|
||
if ((clno < 2) || (clno > pdrive->maxfindex) || (++range_check > old_chain_len) )
|
||
{
|
||
rtfs_set_errno(PEINVALIDCLUSTER);
|
||
goto errex;
|
||
}
|
||
last_cluster_in_chain = clno;
|
||
clno = FATOP(pdrive)->fatop_clnext(pdrive , clno); /* File */
|
||
if (!clno)
|
||
{ /* FATOP will set errno */
|
||
goto errex;
|
||
}
|
||
}
|
||
/* Set ptr_cluster to last in chain so read&write will work right */
|
||
pfile->fptr_cluster = last_cluster_in_chain;
|
||
if (last_cluster_in_chain)
|
||
{
|
||
if ((clno < 2) || (clno > pdrive->maxfindex))
|
||
{
|
||
rtfs_set_errno(PEINVALIDCLUSTER);
|
||
goto errex;
|
||
}
|
||
|
||
pfile->fptr_block = pc_cl2sector(pdrive, last_cluster_in_chain);
|
||
}
|
||
else
|
||
pfile->fptr_block = 0;
|
||
pfile->at_eof = TRUE;
|
||
}
|
||
else /* Simple case. we are not on a cluster boundary. Just free*/
|
||
{ /* The chain beyond us and terminate the list */
|
||
last_cluster_in_chain = pfile->fptr_cluster;
|
||
first_cluster_to_release = FATOP(pdrive)->fatop_clnext(pdrive, pfile->fptr_cluster); /* File */
|
||
if (!first_cluster_to_release) /* if 0 and not end of chain it's an error */
|
||
{ /* clnext set errno */
|
||
goto errex;
|
||
}
|
||
/* Clear cluster number if clnext returned eof */
|
||
if (first_cluster_to_release == 0xffffffff)
|
||
first_cluster_to_release = 0;
|
||
pfile->at_eof = TRUE;
|
||
}
|
||
|
||
/* Now update the directory entry. */
|
||
pfile->pobj->finode->fsize = offset;
|
||
if (!offset) /* If the file goes to zero size unlink the chain */
|
||
{
|
||
pc_pfinode_cluster(pdrive,pfile->pobj->finode,0);
|
||
pfile->fptr_cluster = 0;
|
||
pfile->fptr_block = 0;
|
||
pfile->fptr = 0;
|
||
pfile->at_eof = FALSE;
|
||
/* We are freeing the whole chain so we do not mark last_cluster in chain */
|
||
last_cluster_in_chain = 0;
|
||
}
|
||
ret_val = TRUE; /* If it doesn't get changed to false, it worked */
|
||
/* Convert to native. Overwrite the existing inode.Set archive/date */
|
||
if (!pc_update_inode(pfile->pobj, TRUE, TRUE))
|
||
ret_val = FALSE;
|
||
/* Terminate the chain and free the lost chain part */
|
||
/* Free the rest of the chain */
|
||
if (ret_val && clusters_to_release && first_cluster_to_release)
|
||
{
|
||
/* Release the chain FATOP will set erno if needed - set min and max
|
||
the same so it must delete exactly this many clusters */
|
||
if (!FATOP(pdrive)->fatop_freechain(pdrive, first_cluster_to_release, clusters_to_release, clusters_to_release))
|
||
ret_val = FALSE;
|
||
}
|
||
/* Null terminate the chain */
|
||
if (ret_val && last_cluster_in_chain)
|
||
{
|
||
if (!FATOP(pdrive)->fatop_pfaxxterm(pdrive, last_cluster_in_chain)) /* File */
|
||
ret_val = FALSE;
|
||
}
|
||
if (ret_val && !FATOP(pdrive)->fatop_flushfat(pdrive->driveno))
|
||
ret_val = FALSE;
|
||
}
|
||
|
||
errex:
|
||
if (!release_drive_mount_write(pdrive->driveno))/* Release lock, unmount if aborted */
|
||
return(FALSE);
|
||
return_error: /* No only errors return through here. Everything does. */
|
||
if (p_errno)
|
||
rtfs_set_errno(p_errno);
|
||
return(ret_val);
|
||
}
|
||
|
||
/*
|
||
* Note: when this routine is caled the files finode is LOCKED so the code
|
||
* need not be reentrant relative to the finode.
|
||
*/
|
||
/* Internal version of po_flush() called by po_flush and po_close */
|
||
BOOLEAN _po_flush(PC_FILE *pfile) /*__fn__*/
|
||
{
|
||
/*---------- ctr modified ----------*/
|
||
int driveno;
|
||
DDRIVE *pdr;
|
||
/*----------------------------------*/
|
||
BOOLEAN ret_val;
|
||
|
||
/* Flush the file buffer if it is in use */
|
||
if (!pc_flush_file_buffer(pfile))
|
||
return(FALSE);
|
||
ret_val = TRUE;
|
||
/* Convert to native. Overwrite the existing inode.Set archive
|
||
set date. */
|
||
if (pfile->needs_flush)
|
||
{
|
||
if (pc_update_inode(pfile->pobj, TRUE, TRUE))
|
||
{ /* pc_update_inode and FATOP both set errno */
|
||
pfile->needs_flush = FALSE;
|
||
/* Flush the file allocation table */
|
||
if (!FATOP(pfile->pobj->pdrive)->fatop_flushfat(pfile->pobj->pdrive->driveno))
|
||
ret_val = FALSE;
|
||
}
|
||
else
|
||
ret_val = FALSE;
|
||
}
|
||
|
||
/*---------- ctr modified ----------*/
|
||
driveno = pfile->pobj->pdrive->driveno;
|
||
pdr = pc_drno_to_drive_struct( driveno);
|
||
if( pdr) {
|
||
if( pdr->dev_table_perform_device_ioctl) {
|
||
if( pdr->dev_table_perform_device_ioctl( driveno,
|
||
DEVCTL_FLUSH,
|
||
NULL) != 0) {
|
||
ret_val = FALSE;
|
||
}
|
||
}
|
||
}
|
||
/*----------------------------------*/
|
||
return(ret_val);
|
||
}
|
||
|
||
/****************************************************************************
|
||
PO_FLUSH - Flush a file.
|
||
|
||
Description
|
||
Flush the file updating the disk.
|
||
|
||
Returns
|
||
Returns TRUE if all went well otherwise it returns FALSE.
|
||
|
||
errno is set to one of the following
|
||
0 - No error
|
||
PEBADF - Invalid file descriptor
|
||
PEACCES - File is read only
|
||
An ERTFS system error
|
||
****************************************************************************/
|
||
|
||
BOOLEAN po_flush(PCFD fd) /*__apifn__*/
|
||
{
|
||
PC_FILE *pfile;
|
||
BOOLEAN ret_val;
|
||
int driveno;
|
||
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
|
||
|
||
rtfs_set_errno(0); /* po_flush: clear error status */
|
||
|
||
/* Get the FILE. must be open for write */
|
||
/* Get the file structure and semaphore lock the drive */
|
||
pfile = pc_fd2file(fd, PO_WRONLY|PO_RDWR);
|
||
if (pfile)
|
||
{
|
||
driveno = pfile->pobj->pdrive->driveno;
|
||
ret_val = _po_flush(pfile); /* _po_flush() will set errno */
|
||
if (!release_drive_mount_write(driveno))/* Release lock, unmount if aborted */
|
||
ret_val = -1;
|
||
return(ret_val);
|
||
}
|
||
else
|
||
{ /* fd2file set errno */
|
||
return(FALSE);
|
||
}
|
||
}
|
||
/*****************************************************************************
|
||
pc_set_attributes - Set File Attributes
|
||
|
||
Description
|
||
Given a file or directory name return set directory entry attributes
|
||
associated with the entry.
|
||
|
||
The following values may be set:
|
||
|
||
BIT Nemonic
|
||
0 ARDONLY
|
||
1 AHIDDEN
|
||
2 ASYSTEM
|
||
5 ARCHIVE
|
||
|
||
Note: bits 3 & 4 (AVOLUME,ADIRENT) may not be changed.
|
||
|
||
|
||
Returns
|
||
Returns TRUE if successful otherwise it returns FALSE.
|
||
|
||
errno is set to one of the following
|
||
0 - No error
|
||
PEINVALIDDRIVEID- Drive component is invalid
|
||
PEINVALIDPATH - Path specified badly formed.
|
||
PENOENT - Path not found
|
||
PEACCESS - Object is read only
|
||
PEINVALIDPARMS - attribute argument is invalid
|
||
An ERTFS system error
|
||
****************************************************************************/
|
||
|
||
BOOLEAN pc_set_attributes(byte *path, byte attributes) /*__apifn__*/
|
||
{
|
||
DROBJ *pobj;
|
||
BOOLEAN ret_val;
|
||
int driveno;
|
||
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
|
||
|
||
rtfs_set_errno(0); /* pc_set_attributes: clear error status */
|
||
if ((attributes&(0x40|0x80)) !=0 ) /* Illegal */
|
||
{
|
||
rtfs_set_errno(PEINVALIDPARMS);
|
||
return(FALSE);
|
||
}
|
||
driveno = check_drive_name_mount(path);
|
||
if (driveno < 0)
|
||
{ /* errno was set by check_drive */
|
||
return (FALSE);
|
||
}
|
||
ret_val = FALSE;
|
||
/* pc_fndnode will set errno */
|
||
pobj = pc_fndnode(path);
|
||
if (pobj)
|
||
{
|
||
/* Change the attributes if legal */
|
||
if (
|
||
(attributes & (AVOLUME|ADIRENT)) == /* Still same type */
|
||
(pobj->finode->fattribute & (AVOLUME|ADIRENT)))
|
||
{
|
||
pobj->finode->fattribute = attributes;
|
||
/* Overwrite the existing inode. Do not set archive/date */
|
||
/* pc_update_inode() will set errno */
|
||
ret_val = pc_update_inode(pobj, FALSE, FALSE);
|
||
}
|
||
else
|
||
rtfs_set_errno(PEACCES);
|
||
|
||
pc_freeobj(pobj);
|
||
}
|
||
if (!release_drive_mount_write(driveno))/* Release lock, unmount if aborted */
|
||
ret_val = FALSE;
|
||
return (ret_val);
|
||
}
|
||
|
||
/****************************************************************************
|
||
PC_DISKFLUSH - Flush the FAT and all files on a disk
|
||
|
||
Description
|
||
|
||
If an application may call this functions to force all files
|
||
to be flushed and the fat to be flushed. After this call returns
|
||
the disk image is synchronized with RTFSs internal view of the
|
||
voulme.
|
||
|
||
Returns
|
||
TRUE if the disk flushed else no
|
||
|
||
errno is set to one of the following
|
||
0 - No error
|
||
PEINVALIDDRIVEID- Drive component is invalid
|
||
An ERTFS system error
|
||
****************************************************************************/
|
||
|
||
BOOLEAN pc_diskflush(byte *path) /*__apifn__*/
|
||
{
|
||
int driveno;
|
||
DDRIVE *pdrive;
|
||
BOOLEAN ret_val;
|
||
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
|
||
|
||
rtfs_set_errno(0); /* pc_diskflush: clear error status */
|
||
ret_val = FALSE;
|
||
driveno = check_drive_name_mount(path);
|
||
/* if error, errno was set by check_drive */
|
||
if (driveno >= 0)
|
||
{
|
||
/* Find the drive */
|
||
pdrive = pc_drno2dr(driveno);
|
||
if (pdrive)
|
||
{
|
||
/*---------- ctr modified ----------*/
|
||
if (pc_flush_all_fil(pdrive)) {
|
||
if (FATOP(pdrive)->fatop_flushfat(driveno)) {
|
||
ret_val = TRUE;
|
||
}
|
||
}
|
||
if( pdrive->dev_table_perform_device_ioctl) {
|
||
if( pdrive->dev_table_perform_device_ioctl( driveno,
|
||
DEVCTL_FLUSH,
|
||
NULL) == 0) {
|
||
ret_val = TRUE;
|
||
}
|
||
}/*----------------------------------*/
|
||
}
|
||
|
||
if (!release_drive_mount_write(driveno))/* Release lock, unmount if aborted */
|
||
ret_val = FALSE;
|
||
}
|
||
return(ret_val);
|
||
}
|
||
|
||
/*ctr modified
|
||
<20>{<7B><><EFBFBD>Apc_diskflush<73><68>RTFS<46>̃o<CC83>b<EFBFBD>t<EFBFBD>@<40><><EFBFBD>f<EFBFBD><66><EFBFBD>o<EFBFBD><6F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>s<EFBFBD><73><EFBFBD><EFBFBD><EFBFBD>A
|
||
nand<6E>̓h<CD83><68><EFBFBD>C<EFBFBD>o<EFBFBD><6F><EFBFBD>ł<EFBFBD><C582>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<40><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>邽<EFBFBD>߃f<DF83>o<EFBFBD>C<EFBFBD>X<EFBFBD>ɔ<EFBFBD><C994>f<EFBFBD><66><EFBFBD><EFBFBD><EFBFBD>Ȃ<EFBFBD><C882>B
|
||
<20>h<EFBFBD><68><EFBFBD>C<EFBFBD>o<EFBFBD><6F><EFBFBD>̃o<CC83>b<EFBFBD>t<EFBFBD>@<40><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ăf<C483>o<EFBFBD>C<EFBFBD>X<EFBFBD>ɓf<C993><66><EFBFBD>o<EFBFBD><6F><EFBFBD>悤<EFBFBD>ɂ<EFBFBD><C982>邽<EFBFBD>߂̕ύX<CF8D>B
|
||
<20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>ł<EFBFBD><C582><EFBFBD><EFBFBD><EFBFBD>_po_flush<73><68>DEVCTL_FLUSH<53><48><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>|<7C><><EFBFBD>Ă<EFBFBD><C482>邱<EFBFBD>Ƃɂ<C682><C982><EFBFBD><EFBFBD><EFBFBD><CE8D>B
|
||
mkdir, rmdir<69>Ȃǂ́A<CD81>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>łȂ<C582><C882><EFBFBD><EFBFBD><EFBFBD>_po_flush<73><68><EFBFBD>f<EFBFBD>ʂ肵<CA82>Ă<EFBFBD><C482>܂<EFBFBD><DC82>̂ŁA
|
||
pc_diskflush<73>ɂ<EFBFBD>DEVCTL_FLUSH<53><48><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>|<7C><><EFBFBD>邱<EFBFBD>Ƃɂ<C682><C982><EFBFBD><EFBFBD><EFBFBD><CE8D>B
|
||
<20><><EFBFBD>ꂾ<EFBFBD>Ə<EFBFBD><C68F>ʑw<CA91><77>pc_diskflush<73><68><EFBFBD>ĂȂ<CE82><C882>Ƃ<EFBFBD><C682><EFBFBD><EFBFBD>Ȃ<EFBFBD><C882>̂<EFBFBD>mkdir,rmdir<69>Ȃǂ<C882>
|
||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>|<7C><><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD>B<EFBFBD>ipc_diskflush<73><68>DEVCTL_FLUSH<53>͍폜<CD8D><ED8F9C><EFBFBD>Ă悢<C482><E682A2><EFBFBD><EFBFBD><EFBFBD>j
|
||
*/
|