📄 api.c
字号:
po_lseek and po_truncate.
Returns
Returns the new offset or -1 on error.
If the return value is -1 xn_getlasterror() will be set with one of the following:
PENBADF - File descriptor invalid
PEINVAL - Seek to negative file pointer attempted.
*****************************************************************************/
/*
* Note: when this routine is caled the file's finode is LOCKED so the code
* needn't be reentrant relative to the finode.
*/
long _po_lseek(PC_FILE *pfile, long offset, int origin) /*__fn__*/
{
long file_pointer;
DDRIVE *pdrive;
BOOLEAN past_file;
int log2_bytespcluster;
dword ltemp;
dword ltemp2;
CLUSTERTYPE n_clusters_to_seek; /* FAT32 */
CLUSTERTYPE n_clusters;/* FAT32 */
CLUSTERTYPE first_cluster; /* FAT32 */
long ret_val;
dword alloced_size;
int p_errno;
p_errno = 0;
pdrive = pfile->pobj->pdrive;
/* If file is zero size'd. were there */
if (!(pfile->pobj->finode->fsize))
{
ret_val = 0L;
goto errex;
}
if (origin == PSEEK_SET) /* offset from begining of file */
file_pointer = offset;
else if (origin == PSEEK_CUR) /* offset from current file pointer */
{
file_pointer = (long) pfile->fptr;
file_pointer += offset;
}
else if (origin == PSEEK_END) /* offset from end of file */
{
file_pointer = (long) pfile->pobj->finode->fsize;
file_pointer += offset;
}
else /* Illegal origin */
{
p_errno = PEINVAL;
ret_val = -1L;
goto errex;
}
if (file_pointer < 0L)
{
p_errno = PEINVAL;
ret_val = -1L;
goto errex;
}
if (file_pointer >= (long) pfile->pobj->finode->fsize)
{
file_pointer = (long) pfile->pobj->finode->fsize;
past_file = TRUE;
}
else
past_file = FALSE;
log2_bytespcluster = (int) (pdrive->log2_secpalloc + 9);
/* How many clusters do we need to seek */
/* use the current cluster as the starting point if we can */
if (file_pointer >= (long)pfile->fptr)
{
first_cluster = pfile->fptr_cluster;
ltemp = file_pointer;
if (past_file)
{
/* If seeking past eof reduce the seek count by one since we can't
really seek past EOF */
ltemp -= 1;
}
ltemp >>= log2_bytespcluster;
ltemp2 = pfile->fptr >> log2_bytespcluster;
/* If this algorithm was run twice n_clusters_to_seek would
end up -1. Which would still work but spin 64K times.
Thanks top Morgan Woodson of EMU systems for the patch */
if (ltemp >= ltemp2)
n_clusters_to_seek = (CLUSTERTYPE) (ltemp - ltemp2); /* FAT32 */
else
n_clusters_to_seek = (word) 0;
}
else
{
/* seek from the beginning */
/* seek from the beginning */
first_cluster = pc_finode_cluster(pdrive,pfile->pobj->finode);/* FAT32 */
ltemp = file_pointer >> log2_bytespcluster;
n_clusters_to_seek = (CLUSTERTYPE) ltemp; /* FAT32 */
}
while (n_clusters_to_seek)
{
n_clusters = pc_get_chain(pdrive, first_cluster,
&first_cluster, n_clusters_to_seek);
if (!n_clusters)
{
p_errno = PEINVAL;
ret_val = -1L;
goto errex;
}
n_clusters_to_seek = (CLUSTERTYPE) (n_clusters_to_seek - n_clusters);
}
pfile->fptr_cluster = first_cluster;
pfile->fptr_block = pc_cl2sector(pdrive, first_cluster);
pfile->fptr= file_pointer;
/* If seeking to the end of file see if we are beyond the allocated size of
the file. If we are we set the at_eof flag so we know to try to move the
cluster pointer in case another file instance extends the file */
if (past_file)
{
/* 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 the file pointer is beyond the space allocated to the file note it
since we may need to adjust this file's 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;
}
else
pfile->at_eof = FALSE;
ret_val = pfile->fptr;
errex:
/* No only errors return through here. Everything does. */
set_errno(p_errno);
return(ret_val);
}
#if (RTFS_WRITE)
/*
* Note: when this routine is caled the file's finode is LOCKED so the code
* needn't 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__*/
{
BOOLEAN ret_val;
ret_val = TRUE;
/* Convert to native. Overwrite the existing inode.Set archive/date */
if (pfile->needs_flush)
{
if (pc_update_inode(pfile->pobj, TRUE, TRUE))
{
pfile->needs_flush = FALSE;
/* Flush the file allocation table */
if (!pc_flushfat(pfile->pobj->pdrive->driveno))
ret_val = FALSE;
}
}
return(ret_val);
}
#endif
#if (RTFS_WRITE)
/****************************************************************************
PO_FLUSH - Flush a file.
Description
Flush the file updating the disk.
Returns
Returns TRUE if all went well otherwise it returns FALSE and xn_getlasterror() is set to
one of these values
PENBADF - Invalid file descriptor
PENOSPC - IO error occured
****************************************************************************/
BOOLEAN po_flush(PCFD fd) /*__fn__*/
{
PC_FILE *pfile;
BOOLEAN ret_val;
int p_errno;
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
OS_FS_ENTER()
/* Start by assuming failure */
ret_val = FALSE;
p_errno = PEBADF;
/* Get the FILE. must be open for write */
pfile = pc_fd2file(fd, PO_WRONLY|PO_RDWR);
if (pfile)
{
OS_CLAIM_LOGDRIVE(pfile->pobj->pdrive->driveno) /* Register drive in use */
/* Claim exclusive access on flush */
ret_val = _po_flush(pfile);
if (!ret_val)
p_errno = PENOSPC;
OS_RELEASE_LOGDRIVE(pfile->pobj->pdrive->driveno)
}
/* Restore the kernel state */
set_errno(p_errno);
OS_FS_EXIT()
return(ret_val);
}
#endif
/****************************************************************************
PO_CLOSE - Close a file.
Description
Close the file updating the disk and freeing all core associated with FD.
Returns
Returns 0 if all went well otherwise it returns -1 and xn_getlasterror() is set to
one of these values
PENBADF - Invalid file descriptor
PENOSPC - IO error occured
****************************************************************************/
int po_close(PCFD fd) /*__fn__*/
{
PC_FILE *pfile;
int ret_val;
int driveno;
int p_errno;
CHECK_MEM(int, -1) /* Make sure memory is initted */
OS_FS_ENTER()
if ( (pfile = pc_fd2file(fd, 0)) == 0)
{
p_errno = PEBADF;
ret_val = -1;
}
else
{
driveno = pfile->pobj->pdrive->driveno;
OS_CLAIM_LOGDRIVE(driveno) /* Register drive in use */
ret_val = 0;
p_errno = 0;
#if (RTFS_WRITE)
if (pfile->flag & ( PO_RDWR | PO_WRONLY ) )
{
if (!_po_flush(pfile))
{
p_errno = PENOSPC;
ret_val = -1;
}
}
#endif
/* Release the FD and its core */
pc_freefile(fd);
OS_RELEASE_LOGDRIVE(driveno)
}
set_errno(p_errno);
/* Restore the kernel state */
OS_FS_EXIT()
return(ret_val);
}
/***************************************************************************
PC_MV - Rename a file.
Description
Renames the file in path (name) to newname. Fails if name is invalid,
newname already exists or path not found.
01-07-99 - Rewrote to support moving files between subdirectories
no longer supports renaming subdirectories or volumes
Returns
Returns TRUE if the file was renamed. Or no if the name not found.
***************************************************************************/
#if (RTFS_WRITE)
/* Rename a file */
BOOLEAN pc_mv(char *old_name, char *new_name) /*__fn__*/
{
int old_driveno;
DROBJ *old_obj;
DROBJ *old_parent_obj;
char path[EMAXPATH];
char filename[FILENAMESIZE];
char fileext[4];
int new_driveno;
DROBJ *new_obj;
DROBJ *new_parent_obj;
BOOLEAN ret_val;
CLUSTERTYPE cluster; /* FAT32 */
int p_errno;
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
OS_FS_ENTER() /* Must be last line in declarations */
/* Get the drive and make sure it is mounted */
old_driveno = check_drive(old_name);
if (old_driveno < 0)
{
OS_FS_EXIT()
return(FALSE);
}
old_obj = 0;
old_parent_obj = 0;
new_obj = 0;
new_parent_obj = 0;
ret_val = FALSE;
p_errno = PENOENT;
if (!pc_parsedrive( &old_driveno, old_name ))
goto return_error;
if (!pc_parsedrive( &new_driveno, new_name ))
goto return_error;
/* Drives must be the same */
if (old_driveno != new_driveno)
goto return_error;
OS_CLAIM_LOGDRIVE(old_driveno) /* Grab exclusive access to the drive */
/* Get out the filename and d:parent */
if (!pc_parsepath(path,filename,fileext,old_name))
goto errex;
/* Find the parent and make sure it is a directory */
old_parent_obj = pc_fndnode(path);
if (!old_parent_obj || !pc_isadir(old_parent_obj) || pc_isavol(old_parent_obj))
goto errex;
/* Find the file */
old_obj = pc_get_inode(0, old_parent_obj, (byte*)filename, (byte*)fileext, FALSE);
/* Be sure it exists and is a normal file and is not open */
if (!old_obj || pc_isroot(old_obj) || (old_obj->finode->opencount > 1) ||
(old_obj->finode->fattribute&(ARDONLY|AVOLUME|ADIRENT)))
goto errex;
/* At this point old_obj contains the file we are renaming */
/* See if the new directory entry already exists */
new_obj = pc_fndnode(new_name);
if (new_obj)
{
p_errno = PEEXIST;
goto errex;
}
/* Get out the filename and d:parent */
if (!pc_parsepath(path,filename,fileext,new_name))
goto errex;
/* Find the parent and make sure it is a directory */
new_parent_obj = pc_fndnode(path);
if (!new_parent_obj || !pc_isadir(new_parent_obj) || pc_isavol(new_parent_obj))
goto errex;
/* Set errno to EINVAL if we fail file validation */
p_errno = PEINVAL;
#if (VFAT)
if (!validate_filename(filename, tc_strlen(filename)))
goto errex;
#else
if (!validate_filename(filename, 8))
goto errex;
if (!validate_filename(fileext, 3))
goto errex;
#endif
p_errno = PENOSPC;
/* Create
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -