mirror of
https://github.com/peteratebs/rtfsprorelease.git
synced 2025-06-19 01:05:39 -04:00
901 lines
30 KiB
C
901 lines
30 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.
|
|
*/
|
|
/* RTCOMMONGLUE.C - ProPlus Pro miscelaneous common functions */
|
|
|
|
#include "rtfs.h"
|
|
|
|
|
|
|
|
dword pc_finode_cluster(DDRIVE *pdr, FINODE *finode) /* __fatfn__ */
|
|
{
|
|
if (pdr->drive_info.fasize == 8)
|
|
return ( (dword)finode->fcluster | ((dword)finode->fclusterhi << 16) );
|
|
else
|
|
return ( (dword)finode->fcluster );
|
|
}
|
|
void pc_pfinode_cluster(DDRIVE *pdr, FINODE *finode, dword value) /*__fatfn__ */
|
|
{
|
|
finode->fcluster = (word)value;
|
|
if (pdr->drive_info.fasize == 8)
|
|
finode->fclusterhi = (word)(value >> 16);
|
|
}
|
|
|
|
dword pc_get_parent_cluster(DDRIVE *pdrive, DROBJ *pobj) /* __fatfn__ */
|
|
{
|
|
if ((pdrive->drive_info.fasize == 8) &&
|
|
(pobj->blkinfo.my_frstblock == pdrive->drive_info.rootblock))
|
|
return(0);
|
|
else
|
|
return(pc_sec2cluster(pdrive,pobj->blkinfo.my_frstblock));
|
|
}
|
|
|
|
/****************************************************************************
|
|
int _pc_file_open(DDRIVE *pdrive, byte *name, word flag, word mode, dword extended, BOOLEAN *created, int use_charset)
|
|
- Open a file.
|
|
|
|
This routine is the original po_open() API call with minor changes to accomodate
|
|
RtfsProPlus
|
|
|
|
Description
|
|
Open the file for access as specified in flag. If creating use mode to
|
|
set the access permissions on the file.
|
|
|
|
Flag values are
|
|
|
|
PO_BINARY - Ignored. All file access is binary
|
|
PO_TEXT - Ignored
|
|
PO_RDONLY - Open for read only
|
|
PO_RDWR - Read/write access allowed.
|
|
PO_WRONLY - Open for write only
|
|
PO_CREAT - Create the file if it does not exist. Use mode to
|
|
specify the permission on the file.
|
|
PO_EXCL - If flag contains (PO_CREAT | PO_EXCL) and the file already
|
|
exists fail and set xn_getlasterror() to EEXIST
|
|
PO_TRUNC - Truncate the file if it already exists
|
|
PO_NOSHAREANY - Fail if the file is already open. If the open succeeds
|
|
no other opens will succeed until it is closed.
|
|
PO_NOSHAREWRITE- Fail if the file is already open for write. If the open
|
|
succeeds no other opens for write will succeed until it
|
|
is closed.
|
|
|
|
Mode values are
|
|
|
|
PS_IWRITE - Write permitted
|
|
PS_IREAD - Read permitted. (Always true anyway)
|
|
|
|
Returns
|
|
Returns a non-negative integer to be used as a file descriptor for
|
|
calling read/write/seek/close otherwise it returns -1.
|
|
|
|
errno is set to one of the following
|
|
0 - No error
|
|
PENOENT - Not creating a file and file not found
|
|
PEINVALIDPATH - Invalid pathname
|
|
PENOSPC - No space left on disk to create the file
|
|
PEACCES - Is a directory or opening a read only file for write
|
|
PESHARE - Sharing violation on file opened in exclusive mode
|
|
PEEXIST - Opening for exclusive create but file already exists
|
|
PEEXIST - Opening for exclusive create but file already exists
|
|
An ERTFS system error
|
|
****************************************************************************/
|
|
|
|
BOOLEAN _synch_file_ptrs(PC_FILE *pfile);
|
|
|
|
/* Workhorse filio opne/create routine used by RtfsPro and ProPlus */
|
|
int _pc_file_open(DDRIVE *pdrive, byte *name, word flag, word mode, dword extended, BOOLEAN *created, int use_charset)
|
|
{
|
|
int fd;
|
|
PC_FILE *pfile;
|
|
DROBJ *parent_obj;
|
|
DROBJ *pobj;
|
|
byte *path;
|
|
byte *filename;
|
|
byte fileext[4];
|
|
BOOLEAN open_for_write;
|
|
BOOLEAN sharing_error;
|
|
int p_set_errno;
|
|
|
|
sharing_error = FALSE;
|
|
parent_obj = 0;
|
|
|
|
open_for_write = FALSE;
|
|
p_set_errno = 0;
|
|
|
|
#if (!INCLUDE_RTFS_PROPLUS)
|
|
RTFS_ARGSUSED_DWORD(extended);
|
|
#endif
|
|
#if (!RTFS_CFG_READONLY) /* Read only file system, don't open files for writing */
|
|
/* We will need to know this in a few places. */
|
|
if(flag & (PO_WRONLY|PO_RDWR))
|
|
open_for_write = TRUE;
|
|
#endif
|
|
fd = -1;
|
|
pfile = pc_allocfile();
|
|
if (pfile)
|
|
fd = pfile->my_fd;
|
|
else
|
|
{
|
|
rtfs_set_errno(PERESOURCEFILES, __FILE__, __LINE__);
|
|
return(fd);
|
|
}
|
|
|
|
/* Allocate scratch buffers in the DRIVE structure. */
|
|
if (!pc_alloc_path_buffers(pdrive))
|
|
goto errex;
|
|
path = pdrive->pathname_buffer;
|
|
filename = pdrive->filename_buffer;
|
|
|
|
/* Get out the filename and d:parent */
|
|
if (!pc_parsepath(path,filename,fileext,name, use_charset))
|
|
{
|
|
p_set_errno = PEINVALIDPATH;
|
|
/* rtfs_set_errno(PEINVALIDPATH, __FILE__, __LINE__); */
|
|
goto errex;
|
|
}
|
|
|
|
/* Find the parent */
|
|
/* pc_fndnode will set errno */
|
|
parent_obj = pc_fndnode(path, use_charset);
|
|
if (!parent_obj)
|
|
goto errex;
|
|
|
|
if (!pc_isadir(parent_obj) || pc_isavol(parent_obj))
|
|
{
|
|
p_set_errno = PENOENT; /* Path is not a directory */
|
|
goto errex;
|
|
}
|
|
|
|
pobj = pc_get_inode(0, parent_obj,filename,(byte*)fileext, GET_INODE_MATCH, use_charset);
|
|
if(pobj && (pc_isadir(pobj) || pc_isavol(pobj)) )
|
|
{
|
|
pc_freeobj(pobj);
|
|
p_set_errno = PEACCES; /* is a directory */
|
|
goto errex;
|
|
}
|
|
if (pobj)
|
|
{
|
|
/* If we goto exit: we want them linked so we can clean up */
|
|
pfile->pobj = pobj; /* Link the file to the object */
|
|
#if (INCLUDE_RTFS_PROPLUS) /* Use ProPlus ffinode field */
|
|
pfile->fc.plus.ffinode = pobj->finode;
|
|
#endif
|
|
/* check the sharing conditions */
|
|
sharing_error = FALSE;
|
|
if (pobj->finode->opencount != 1)
|
|
{
|
|
/* The file is already open by someone. Lets see if we are
|
|
compatible */
|
|
/* 1. We do not want to share with anyone */
|
|
if (flag & PO_NOSHAREANY)
|
|
sharing_error = TRUE;
|
|
/* 2. Someone else does not want to share */
|
|
if (pobj->finode->openflags & OF_EXCLUSIVE)
|
|
sharing_error = TRUE;
|
|
/* 3. We want exclusive write but already open for write */
|
|
if ( open_for_write && (flag & PO_NOSHAREWRITE) &&
|
|
(pobj->finode->openflags & OF_WRITE))
|
|
sharing_error = TRUE;
|
|
/* 4. We want open for write but it is already open for
|
|
exclusive */
|
|
if ( (open_for_write) &&
|
|
(pobj->finode->openflags & OF_WRITEEXCLUSIVE))
|
|
sharing_error = TRUE;
|
|
/* 5. Open for trunc when already open */
|
|
if (flag & PO_TRUNC)
|
|
sharing_error = TRUE;
|
|
#if (INCLUDE_RTFS_PROPLUS) /* Test for ProPlus sharing errors */
|
|
/* 4. We want open for write but it is already open for
|
|
transaction */
|
|
if ( (open_for_write) &&
|
|
(pobj->finode->openflags & OF_TRANSACTION))
|
|
sharing_error = TRUE;
|
|
/* Opened in write already and now opening for transaction */
|
|
if ((extended & PCE_TRANSACTION_FILE) &&
|
|
(pobj->finode->openflags & OF_WRITE))
|
|
sharing_error = TRUE;
|
|
#endif
|
|
}
|
|
if (sharing_error)
|
|
{
|
|
p_set_errno = PESHARE;
|
|
goto errex;
|
|
}
|
|
if ( (flag & (PO_EXCL|PO_CREAT)) == (PO_EXCL|PO_CREAT) )
|
|
{
|
|
p_set_errno = PEEXIST; /* Exclusive fail */
|
|
goto errex;
|
|
}
|
|
if(open_for_write && (pobj->finode->fattribute & ARDONLY) )
|
|
{
|
|
p_set_errno = PEACCES; /* read only file */
|
|
goto errex;
|
|
}
|
|
/* Removed file truncation code. basic file io and extended file IO have their own methods of thruncating.
|
|
The common routine does not need to support it */
|
|
if (created)
|
|
*created = FALSE;
|
|
}
|
|
#if (RTFS_CFG_READONLY) /* Read only file system, don't create files */
|
|
else /* File not found */
|
|
{
|
|
if (get_errno() != PENOENT)
|
|
goto errex;
|
|
rtfs_clear_errno(); /* Clear PENOENT */
|
|
p_set_errno = PEACCES; /* read only file */
|
|
RTFS_ARGSUSED_INT((int) mode);
|
|
goto errex;
|
|
}
|
|
#else
|
|
else /* File not found */
|
|
{
|
|
if (get_errno() != PENOENT)
|
|
goto errex;
|
|
if (!(flag & PO_CREAT))
|
|
{
|
|
p_set_errno = PENOENT; /* Set PENOENT again, this time in debug mode to print the error */
|
|
goto errex; /* File does not exist */
|
|
}
|
|
rtfs_clear_errno(); /* Clear PENOENT */
|
|
/* Do not allow create if write bits not set */
|
|
if(!open_for_write)
|
|
{
|
|
p_set_errno = PEACCES; /* read only file */
|
|
goto errex;
|
|
}
|
|
/* Create for read only if write perm not allowed */
|
|
pobj = pc_mknode( parent_obj, filename, fileext, (byte) ((mode == PS_IREAD) ? ARDONLY : 0), 0, use_charset);
|
|
if (!pobj)
|
|
{
|
|
/* pc_mknode has set errno */
|
|
goto errex;
|
|
}
|
|
|
|
pfile->pobj = pobj; /* Link the file to the object */
|
|
#if (INCLUDE_RTFS_PROPLUS) /* Use ProPlus ffinode field */
|
|
pfile->fc.plus.ffinode = pobj->finode;
|
|
#endif
|
|
if (created)
|
|
*created = TRUE;
|
|
}
|
|
#endif /* !RTFS_CFG_READONLY (end do not create because read-only) */
|
|
/* Set the file sharing flags in the shared finode structure */
|
|
/* clear flags if we just opened it . */
|
|
if (pobj->finode->opencount == 1)
|
|
pobj->finode->openflags = 0;
|
|
|
|
if (flag & PO_BUFFERED)
|
|
{
|
|
/* use pc_load_file_buffer(pfinode, 1, FALSE) to allocate a file buffer to use with this file until it is closed
|
|
use sector 1 which is never a valid file location */
|
|
if (!pc_load_file_buffer(pobj->finode, 1, FALSE))
|
|
goto errex;
|
|
pobj->finode->openflags |= OF_BUFFERED;
|
|
}
|
|
|
|
if (open_for_write)
|
|
{
|
|
pobj->finode->openflags |= OF_WRITE;
|
|
if (flag & PO_NOSHAREWRITE)
|
|
pobj->finode->openflags |= OF_WRITEEXCLUSIVE;
|
|
}
|
|
if (flag & PO_NOSHAREANY)
|
|
pobj->finode->openflags |= OF_EXCLUSIVE;
|
|
pfile->flag = flag; /* Access flags */
|
|
#if (INCLUDE_RTFS_PROPLUS) /* ProPlus transaction files */
|
|
if (extended & PCE_TRANSACTION_FILE)
|
|
pobj->finode->openflags |= OF_TRANSACTION;
|
|
#endif
|
|
|
|
p_set_errno = 0;
|
|
if (parent_obj)
|
|
pc_freeobj(parent_obj);
|
|
pc_release_path_buffers(pdrive);
|
|
return(fd);
|
|
errex:
|
|
pc_release_path_buffers(pdrive);
|
|
pc_freefile(pfile);
|
|
if (parent_obj)
|
|
pc_freeobj(parent_obj);
|
|
if (p_set_errno)
|
|
rtfs_set_errno(p_set_errno, __FILE__, __LINE__);
|
|
return(-1);
|
|
}
|
|
|
|
BOOLEAN pc_alloc_path_buffers(DDRIVE *pdrive)
|
|
{
|
|
pdrive->pathname_blkbuff = pc_scratch_blk();
|
|
pdrive->filename_blkbuff = pc_scratch_blk();
|
|
if (!pdrive->pathname_blkbuff || !pdrive->filename_blkbuff)
|
|
{
|
|
pc_release_path_buffers(pdrive);
|
|
return(FALSE);
|
|
}
|
|
pdrive->pathname_buffer = pdrive->pathname_blkbuff->data;
|
|
pdrive->filename_buffer = pdrive->filename_blkbuff->data;
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
void pc_release_path_buffers(DDRIVE *pdrive)
|
|
{
|
|
if (pdrive->pathname_blkbuff)
|
|
pc_free_scratch_blk(pdrive->pathname_blkbuff);
|
|
if (pdrive->filename_blkbuff)
|
|
pc_free_scratch_blk(pdrive->filename_blkbuff);
|
|
pdrive->pathname_blkbuff = pdrive->filename_blkbuff = 0;
|
|
}
|
|
/****************************************************************************
|
|
Miscelaneous File and file descriptor management functions
|
|
|
|
These functions are private functions used by the po_ file io routines.
|
|
|
|
pc_fd2file -
|
|
Map a file descriptor to a file structure. Return null if the file is
|
|
not open. If an error has occured on the file return NULL unless
|
|
allow_err is true.
|
|
|
|
pc_allocfile -
|
|
Allocate a file structure an return its handle. Return -1 if no more
|
|
handles are available.
|
|
|
|
pc_freefile -
|
|
Free all core associated with a file descriptor and make the descriptor
|
|
available for future calls to allocfile.
|
|
|
|
pc_free_all_fil -
|
|
*****************************************************************************/
|
|
|
|
/* Map a file descriptor to a file structure. Return null if the file is
|
|
not open or the flags do not match (test for write access if needed).
|
|
Get the file structure and semaphore lock the drive
|
|
*/
|
|
|
|
|
|
PC_FILE *pc_fd2file(int fd,int flags) /*__fn__*/
|
|
{
|
|
PC_FILE *pfile;
|
|
|
|
/* Get the file and associated drive structure with the crit sem locked */
|
|
if (0 <= fd && fd < pc_nuserfiles())
|
|
{
|
|
pfile = prtfs_cfg->mem_file_pool+fd;
|
|
OS_CLAIM_FSCRITICAL()
|
|
if (!pfile->is_free)
|
|
{
|
|
if (!pfile->pobj)
|
|
{
|
|
/* An event (probably card removal or failure)
|
|
closed the file. Set errno and return. The
|
|
user must call po_close to clear this condition */
|
|
rtfs_set_errno(PECLOSED, __FILE__, __LINE__);
|
|
}
|
|
/* If flags == 0. Any access allowed. Otherwise at least one
|
|
bit in the file open flags must match the flags sent in */
|
|
else if (!flags || (pfile->flag&flags))
|
|
{
|
|
DDRIVE *pdrive;
|
|
int driveno;
|
|
/* dereference pobj while critical semaphore is still locked */
|
|
driveno = pfile->pobj->pdrive->driveno;
|
|
OS_RELEASE_FSCRITICAL()
|
|
/* Claim the drive, double check that the file is still
|
|
good (was not closed out by a pc_dskfree() call) */
|
|
pdrive = rtfs_claim_media_and_buffers(driveno);
|
|
if (!pdrive)
|
|
{
|
|
rtfs_clear_errno(); /* Clear errno set by claim, we want PECLOSED */
|
|
rtfs_set_errno(PECLOSED, __FILE__, __LINE__);
|
|
return(0);
|
|
}
|
|
|
|
if (pfile->pobj)
|
|
{
|
|
return(pfile);
|
|
}
|
|
else
|
|
{
|
|
/* An event (probably card removal or failure)
|
|
closed the file. Set errno and return. The
|
|
user must call po_close to clear this condition */
|
|
rtfs_release_media_and_buffers(driveno); /* pc_fd2file - clear Drive on error */
|
|
rtfs_clear_errno(); /* Make sure we set errno to PECLOSED */
|
|
rtfs_set_errno(PECLOSED, __FILE__, __LINE__);
|
|
return(0);
|
|
}
|
|
}
|
|
else
|
|
rtfs_set_errno(PEACCES, __FILE__, __LINE__);
|
|
}
|
|
else
|
|
rtfs_set_errno(PEBADF, __FILE__, __LINE__);
|
|
OS_RELEASE_FSCRITICAL()
|
|
}
|
|
else
|
|
rtfs_set_errno(PEBADF, __FILE__, __LINE__);
|
|
return(0);
|
|
}
|
|
|
|
/* Assign zeroed out file structure to an FD and return the structure. Return
|
|
0 on error. pfile->my_fd contains the file descriptor */
|
|
PC_FILE *pc_allocfile(void) /*__fn__*/
|
|
{
|
|
PC_FILE *pfile;
|
|
int i;
|
|
|
|
OS_CLAIM_FSCRITICAL()
|
|
pfile = prtfs_cfg->mem_file_pool;
|
|
for (i=0;i<pc_nuserfiles();i++, pfile++)
|
|
{
|
|
if (pfile->is_free)
|
|
{
|
|
rtfs_memset(pfile, 0, sizeof(PC_FILE));
|
|
OS_RELEASE_FSCRITICAL()
|
|
pfile->my_fd = i;
|
|
return(pfile);
|
|
}
|
|
}
|
|
OS_RELEASE_FSCRITICAL()
|
|
return (0);
|
|
}
|
|
|
|
/* Free core associated with a file descriptor. Release the FD for later use */
|
|
void pc_freefile(PC_FILE *pfile)
|
|
{
|
|
DROBJ *pobj;
|
|
OS_CLAIM_FSCRITICAL()
|
|
pobj = pfile->pobj;
|
|
pfile->is_free = TRUE;
|
|
OS_RELEASE_FSCRITICAL()
|
|
if (pobj)
|
|
pc_freeobj(pobj);
|
|
}
|
|
|
|
/* Note: all file buffering code was moved to rtfilebuffer.c */
|
|
|
|
|
|
#define ENUM_FLUSH 1
|
|
#define ENUM_TEST 2
|
|
#define ENUM_FREE 3
|
|
#define ENUM_RELEASE_PREALLOC 4
|
|
|
|
/* Release all file descriptors associated with a drive and free up all core
|
|
associated with the files called by pc_free_all_fil, pc_flush_all_fil,
|
|
pc_test_all_fil. The drive semaphore must be locked before this call is
|
|
entered.
|
|
*/
|
|
/* basic file flush if PROPLUS is not enabled */
|
|
BOOLEAN _pc_bfilio_flush(PC_FILE *pefile);
|
|
|
|
int pc_enum_file(DDRIVE *pdrive, int chore) /*__fn__*/
|
|
{
|
|
PC_FILE *pfile;
|
|
DROBJ *pobj;
|
|
int i;
|
|
int dirty_count;
|
|
|
|
dirty_count = 0;
|
|
for (i=0; i < pc_nuserfiles(); i++)
|
|
{
|
|
OS_CLAIM_FSCRITICAL()
|
|
pfile = prtfs_cfg->mem_file_pool+i;
|
|
if (pfile && !pfile->is_free && pfile->pobj && pfile->pobj->pdrive == pdrive)
|
|
{
|
|
OS_RELEASE_FSCRITICAL()
|
|
if (chore == ENUM_FLUSH)
|
|
{
|
|
#if (INCLUDE_RTFS_PROPLUS) /* ProPlus file flush */
|
|
if (!_pc_efilio_flush(pfile))
|
|
return(-1);
|
|
#else
|
|
if (!_pc_bfilio_flush(pfile))
|
|
return(-1);
|
|
#endif
|
|
}
|
|
#if (INCLUDE_RTFS_PROPLUS) /* ProPlus file purge preallocated clusters */
|
|
else if (chore == ENUM_RELEASE_PREALLOC)
|
|
{
|
|
_pc_efilio_free_excess_clusters(pfile);
|
|
}
|
|
#endif
|
|
else if (chore == ENUM_TEST)
|
|
{
|
|
if (pc_check_file_dirty(pfile))
|
|
dirty_count += 1;
|
|
}
|
|
if (chore == ENUM_FREE)
|
|
{
|
|
/* Mark the file closed here. po_close must release it */
|
|
OS_CLAIM_FSCRITICAL()
|
|
pobj = pfile->pobj;
|
|
pfile->pobj = 0;
|
|
OS_RELEASE_FSCRITICAL()
|
|
if (pobj)
|
|
pc_freeobj(pobj);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OS_RELEASE_FSCRITICAL()
|
|
}
|
|
}
|
|
return(dirty_count);
|
|
}
|
|
|
|
/* Return the user buffer and it calculates how many sectors can fit in it.
|
|
Sectors are usually 512 bytes but could be larger.
|
|
If no user buffers are assigned use a scratch block
|
|
If the user buffer can't hold mimimum sector blocks then
|
|
*/
|
|
|
|
byte *pc_claim_user_buffer(DDRIVE *pdr, dword *pbuffer_size_sectors, dword minimimum_size_sectors)
|
|
{
|
|
byte *ret_val;
|
|
dword ret_size;
|
|
|
|
ret_size = 0;
|
|
/* If we return NULL it may be an error but it may also mean that the
|
|
user buffer or scratch buffers are not large enough for the request. */
|
|
/* use the device-wide shared user buffer (all volumes on the device) if one was provided */
|
|
if (prtfs_cfg->rtfs_exclusive_semaphore) /* In single threaded mode use the system-wide shared user buffer */
|
|
{
|
|
ret_val = prtfs_cfg->shared_user_buffer;
|
|
ret_size = prtfs_cfg->shared_user_buffer_size/pdr->pmedia_info->sector_size_bytes;
|
|
}
|
|
else
|
|
{
|
|
ret_val = (byte *) pdr->pmedia_info->device_sector_buffer;
|
|
ret_size = pdr->pmedia_info->device_sector_buffer_size/pdr->pmedia_info->sector_size_bytes;
|
|
}
|
|
if (!ret_val || ret_size < minimimum_size_sectors)
|
|
{
|
|
ret_val = 0;
|
|
ret_size = 0;
|
|
}
|
|
|
|
*pbuffer_size_sectors = ret_size;
|
|
return(ret_val);
|
|
}
|
|
/* Release the user buffer, releases scratch buffer if that's what we are using for user buffers */
|
|
void pc_release_user_buffer(DDRIVE *pdr, byte *pbuffer)
|
|
{
|
|
RTFS_ARGSUSED_PVOID((void *) pdr);
|
|
RTFS_ARGSUSED_PVOID((void *) pbuffer);
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Release all file descriptors associated with a drive and free up all core
|
|
associated with the files called by dsk_close */
|
|
void pc_free_all_fil(DDRIVE *pdrive) /*__fn__*/
|
|
{
|
|
pc_enum_file(pdrive, ENUM_FREE);
|
|
}
|
|
|
|
/* Release all preallocated clusters from all files */
|
|
void pc_release_all_prealloc(DDRIVE *pdrive) /*__fn__*/
|
|
{
|
|
pc_enum_file(pdrive, ENUM_RELEASE_PREALLOC);
|
|
}
|
|
|
|
/* Flush all files on a drive */
|
|
BOOLEAN pc_flush_all_fil(DDRIVE *pdrive) /*__fn__*/
|
|
{
|
|
if (pc_enum_file(pdrive, ENUM_FLUSH) == 0)
|
|
return(TRUE);
|
|
else
|
|
return(FALSE);
|
|
}
|
|
|
|
/* Test the dirty flag for all files */
|
|
int pc_test_all_fil(DDRIVE *pdrive) /*__fn__*/
|
|
{
|
|
return(pc_enum_file(pdrive, ENUM_TEST));
|
|
}
|
|
|
|
dword pc_get_media_sector_size(DDRIVE *pdr)
|
|
{
|
|
dword sector_size_bytes;
|
|
/* If the device may have non default sector size we must scale by it */
|
|
sector_size_bytes = pdr->pmedia_info->sector_size_bytes;
|
|
ERTFS_ASSERT(sector_size_bytes)
|
|
if (!sector_size_bytes) /* defensive */
|
|
sector_size_bytes = RTFS_CFG_DEFAULT_SECTOR_SIZE_BYTES;
|
|
return(sector_size_bytes);
|
|
}
|
|
|
|
#if (INCLUDE_FAT16)
|
|
|
|
BOOLEAN pc_init_drv_fat_info16(DDRIVE *pdr, struct pcblk0 *pbl0)
|
|
{
|
|
pdr->drive_info.secpfat = (dword) pbl0->secpfat; /* sectors / fat */
|
|
pdr->drive_info.numfats = pbl0->numfats; /* Number of fat copies */
|
|
pdr->drive_info.fatblock = (dword) pbl0->secreserved;
|
|
|
|
pdr->drive_info.rootblock = pdr->drive_info.fatblock + pdr->drive_info.secpfat * pdr->drive_info.numfats;
|
|
pdr->drive_info.secproot = (int)((pdr->drive_info.numroot + pdr->drive_info.inopblock-1)/pdr->drive_info.inopblock);
|
|
/* The first block of the cluster area is just past the root */
|
|
/* Round up if we have to */
|
|
pdr->drive_info.firstclblock = pdr->drive_info.rootblock + pdr->drive_info.secproot;
|
|
/* Calculate the largest index in the file allocation table.
|
|
Total # block in the cluster area)/Blockpercluster == s total
|
|
Number of clusters. Entries 0 & 1 are reserved so the highest
|
|
valid fat index is 1 + total # clusters.
|
|
*/
|
|
pdr->drive_info.maxfindex = (dword)(1 + ((pdr->drive_info.numsecs - pdr->drive_info.firstclblock)/pdr->drive_info.secpalloc));
|
|
/* If the file system type was specified by format in the bpb, use that. Otherwise calculate nibbles/fat entry */
|
|
if (pbl0->fasize)
|
|
pdr->drive_info.fasize = pbl0->fasize;
|
|
else /* if < 4087 clusters then 12 bit else 16 */
|
|
pdr->drive_info.fasize = (int) ((pdr->drive_info.maxfindex < 4087) ? 3 : 4);
|
|
{
|
|
/* Make sure the calculated index doesn't overflow the fat sectors */
|
|
dword max_index;
|
|
/* For FAT16 Each block of the fat holds 256 entries so the maximum index is
|
|
(pdr->secpfat * 256)-1; */
|
|
max_index = (dword) pdr->drive_info.secpfat;
|
|
if (pdr->drive_info.fasize == 3)
|
|
{/* Max clusters in FAT12.. 1024 per 3 blocks plus 341 per residual block */
|
|
/* Modified 8-16-06 to distinguish between FAT12 and FAT16 */
|
|
dword max_index3,div3,ltemp,residual;
|
|
max_index3 = max_index;
|
|
div3 = max_index3/3;
|
|
max_index = div3 * 1024;
|
|
ltemp = div3 * 3;
|
|
residual = max_index3-ltemp;
|
|
max_index += (residual * 341);
|
|
}
|
|
else
|
|
{
|
|
max_index *= 256; /* Multiplied by blocks per sector later */
|
|
}
|
|
max_index *= pdr->drive_info.blockspsec;
|
|
max_index -= 1;
|
|
if (pdr->drive_info.maxfindex > max_index)
|
|
pdr->drive_info.maxfindex = max_index;
|
|
}
|
|
/* if calculated size > fff0 set it to one less. fff0 to ffff are
|
|
reserved values. */
|
|
if (pdr->drive_info.fasize == 4)
|
|
{
|
|
if (pdr->drive_info.maxfindex >= 0xfff0 && pdr->drive_info.maxfindex <= 0xffff)
|
|
pdr->drive_info.maxfindex = 0xffef;
|
|
}
|
|
else
|
|
{
|
|
if (pdr->drive_info.maxfindex >= 0xff0 && pdr->drive_info.maxfindex <= 0xfff)
|
|
pdr->drive_info.maxfindex = 0xfef;
|
|
}
|
|
|
|
/* Create a hint for where we should write file data. */
|
|
/* Previous versions put the file cluster allocation base 1/32 nd into the cluster space. This is no longer the default baehavior. Now
|
|
we allocate file clusters from the beginning of the cluster space */
|
|
pdr->drive_info.free_contig_base = 2;
|
|
/* set the pointer to where to look for free clusters to the contiguous
|
|
area. On the first call to write this will hunt for the real free
|
|
blocks. */
|
|
pdr->drive_info.free_contig_pointer = pdr->drive_info.free_contig_base;
|
|
|
|
pdr->drive_info.infosec = 0;
|
|
return(TRUE);
|
|
}
|
|
#endif
|
|
/* Helper functions used by ProPlus and Pro */
|
|
dword pc_alloced_bytes_from_clusters(DDRIVE *pdr, dword total_alloced_clusters)
|
|
{
|
|
dword ltemp,alloced_size_bytes;
|
|
/* Check if we get an overflow by shifting */
|
|
ltemp = total_alloced_clusters >> (32-pdr->drive_info.log2_bytespalloc);
|
|
if (ltemp)
|
|
alloced_size_bytes = LARGEST_DWORD;
|
|
else
|
|
alloced_size_bytes = total_alloced_clusters << pdr->drive_info.log2_bytespalloc;
|
|
return(alloced_size_bytes);
|
|
}
|
|
|
|
dword pc_byte2clmod(DDRIVE *pdr, dword nbytes)
|
|
{
|
|
dword nclusters;
|
|
/* Round nbytes up to its cluster size by adding in clustersize-1
|
|
and masking off the low bits */
|
|
nclusters = nbytes >> pdr->drive_info.log2_bytespalloc;
|
|
if (nbytes & pdr->drive_info.byte_into_cl_mask)
|
|
nclusters += 1;
|
|
return(nclusters);
|
|
}
|
|
/* Routines to test, clear and set file and drive status conditions
|
|
The methods differ between RtfsPro and RtfsProPlus so an abstraction layer is provided */
|
|
void pc_set_file_dirty(PC_FILE * pfile, BOOLEAN isdirty)
|
|
{
|
|
if (pfile->pobj && pfile->pobj->finode)
|
|
{
|
|
if (isdirty)
|
|
{ /* Update the modified field with the current time and date */
|
|
pc_update_finode_datestamp(pfile->pobj->finode, TRUE, DATESETUPDATE);
|
|
pfile->pobj->finode->operating_flags |= FIOP_NEEDS_FLUSH;
|
|
}
|
|
else
|
|
pfile->pobj->finode->operating_flags &= ~FIOP_NEEDS_FLUSH;
|
|
}
|
|
}
|
|
BOOLEAN pc_check_file_dirty(PC_FILE * pfile)
|
|
{
|
|
if (pfile->pobj && pfile->pobj->finode && pfile->pobj->finode->operating_flags & FIOP_NEEDS_FLUSH)
|
|
return(TRUE);
|
|
else
|
|
return(FALSE);
|
|
}
|
|
void pc_set_file_buffer_dirty(FINODE *pfinode, BOOLEAN isdirty)
|
|
{
|
|
if (isdirty)
|
|
pfinode->operating_flags |= FIOP_BUFFER_DIRTY;
|
|
else
|
|
pfinode->operating_flags &= ~FIOP_BUFFER_DIRTY;
|
|
}
|
|
BOOLEAN pc_check_file_buffer_dirty(FINODE *pfinode)
|
|
{
|
|
if (pfinode->operating_flags & FIOP_BUFFER_DIRTY)
|
|
return(TRUE);
|
|
else
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
void set_fat_dirty(DDRIVE *pdr)
|
|
{
|
|
pdr->drive_info.drive_operating_flags |= DRVOP_FAT_IS_DIRTY;
|
|
}
|
|
void clear_fat_dirty(DDRIVE *pdr)
|
|
{
|
|
pdr->drive_info.drive_operating_flags &= ~DRVOP_FAT_IS_DIRTY;
|
|
}
|
|
BOOLEAN chk_fat_dirty(DDRIVE *pdr)
|
|
{
|
|
if (pdr->drive_info.drive_operating_flags & DRVOP_FAT_IS_DIRTY)
|
|
return(TRUE);
|
|
else
|
|
return(FALSE);
|
|
}
|
|
void set_mount_abort_status(DDRIVE *pdr)
|
|
{
|
|
pdr->drive_info.drive_operating_flags |= DRVOP_MOUNT_ABORT;
|
|
}
|
|
void clear_mount_valid(DDRIVE *pdr)
|
|
{
|
|
pdr->drive_info.drive_operating_flags &= ~DRVOP_MOUNT_VALID;
|
|
}
|
|
void clear_mount_abort(DDRIVE *pdr)
|
|
{
|
|
pdr->drive_info.drive_operating_flags &= ~DRVOP_MOUNT_ABORT;
|
|
}
|
|
|
|
void set_mount_valid(DDRIVE *pdr)
|
|
{
|
|
pdr->drive_info.drive_operating_flags |= DRVOP_MOUNT_VALID;
|
|
}
|
|
BOOLEAN chk_mount_abort(DDRIVE *pdr)
|
|
{
|
|
if (pdr && (pdr->drive_info.drive_operating_flags & DRVOP_MOUNT_ABORT))
|
|
return(TRUE);
|
|
return(FALSE);
|
|
}
|
|
BOOLEAN chk_mount_valid(DDRIVE *pdr)
|
|
{
|
|
if (pdr->drive_info.drive_operating_flags & DRVOP_MOUNT_VALID)
|
|
return(TRUE);
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
#if (!INCLUDE_FAT32)
|
|
|
|
BOOLEAN pc_init_drv_fat_info32(DDRIVE *pdr, struct pcblk0 *pbl0)
|
|
{
|
|
RTFS_ARGSUSED_PVOID((void *) pdr);
|
|
RTFS_ARGSUSED_PVOID((void *) pbl0);
|
|
return(FALSE);
|
|
}
|
|
BOOLEAN pc_gblk0_32(DDRIVE *pdr, struct pcblk0 *pbl0, byte *b) /*__fn__*/
|
|
{
|
|
RTFS_ARGSUSED_PVOID((void *) pdr);
|
|
RTFS_ARGSUSED_PVOID((void *) pbl0);
|
|
RTFS_ARGSUSED_PVOID((void *) b);
|
|
return(FALSE);
|
|
}
|
|
|
|
BOOLEAN pc_validate_partition_type(byte p_type)
|
|
{
|
|
if ( (p_type == 0x01) || (p_type == 0x04) || (p_type == 0x06) || (p_type == 0x0E))
|
|
return(TRUE);
|
|
else
|
|
return(FALSE);
|
|
}
|
|
#endif /* !(INCLUDE_FAT32) */
|
|
|
|
|
|
|
|
#if (!INCLUDE_RTFS_FREEMANAGER)
|
|
int free_manager_disabled(int i) /* Quiets down compilers */
|
|
{
|
|
return(i);
|
|
}
|
|
void free_manager_revert(DDRIVE *pdr)
|
|
{
|
|
RTFS_ARGSUSED_PVOID((void *) pdr);
|
|
}
|
|
#endif
|
|
#if (RTFS_CFG_READONLY) /* Stubs and overrides of certain functions for read only file system.*/
|
|
/* These stubs reduce the number of places where conditional compilation is required without adding significant bloat, */
|
|
/* Make release_drive_mount_write() same as release_drive_mount for a read only file system */
|
|
BOOLEAN release_drive_mount_write(int driveno)
|
|
{
|
|
release_drive_mount(driveno);
|
|
return(TRUE);
|
|
}
|
|
void pc_set_mbuff_dirty(PCMBUFF *pcmb, dword block_offset, int block_count)
|
|
{
|
|
RTFS_ARGSUSED_PVOID((void *) pcmb);
|
|
RTFS_ARGSUSED_DWORD(block_offset);
|
|
RTFS_ARGSUSED_DWORD(block_count);
|
|
}
|
|
void pc_zero_mbuff_dirty(PCMBUFF *pcmb)
|
|
{
|
|
RTFS_ARGSUSED_PVOID((void *) pcmb);
|
|
}
|
|
int pc_get_clear_mbuff_dirty(PCMBUFF *pcmb, int *pfirst_dirty)
|
|
{
|
|
RTFS_ARGSUSED_PVOID((void *) pcmb);
|
|
RTFS_ARGSUSED_PVOID((void *) pfirst_dirty);
|
|
return(0);
|
|
}
|
|
|
|
BOOLEAN pc_flush_file_buffer(FINODE *pfinode)
|
|
{
|
|
RTFS_ARGSUSED_PVOID((void *) pfinode);
|
|
return(TRUE);
|
|
}
|
|
BOOLEAN pc_write_fat_block_buffer_page(DDRIVE *pdrive, FATBUFF *pblk)
|
|
{
|
|
RTFS_ARGSUSED_PVOID((void *) pdrive);
|
|
RTFS_ARGSUSED_PVOID((void *) pblk);
|
|
return(TRUE);
|
|
}
|
|
BOOLEAN _pc_bfilio_flush(PC_FILE *pfile)
|
|
{
|
|
RTFS_ARGSUSED_PVOID((void *) pfile);
|
|
return(TRUE);
|
|
}
|
|
BOOLEAN _pc_efilio_flush(PC_FILE *pfile)
|
|
{
|
|
RTFS_ARGSUSED_PVOID((void *) pfile);
|
|
return(TRUE);
|
|
}
|
|
BOOLEAN _pc_efilio_flush_file_buffer(PC_FILE *pfile)
|
|
{
|
|
RTFS_ARGSUSED_PVOID((void *) pfile);
|
|
return(TRUE);
|
|
}
|
|
void _pc_efilio_free_excess_clusters(PC_FILE *pefile)
|
|
{
|
|
RTFS_ARGSUSED_PVOID((void *) pefile);
|
|
};
|
|
|
|
dword _pc_efinode_count_to_link(FINODE *pefinode,dword allocation_policy)
|
|
{
|
|
RTFS_ARGSUSED_PVOID((void *) pefinode);
|
|
RTFS_ARGSUSED_DWORD(allocation_policy);
|
|
return(0);
|
|
}
|
|
void pc_free_excess_clusters(FINODE *pefinode)
|
|
{
|
|
RTFS_ARGSUSED_PVOID((void *) pefinode);
|
|
};
|
|
|
|
#endif
|