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
1425 lines
45 KiB
C
1425 lines
45 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.
|
|
*/
|
|
/* RTDROBJ.C - Directory object manipulation routines
|
|
pc_get_cwd - Get the current working directory DROBJ for a drive,
|
|
pc_fndnode - Find a file or directory on disk and return a DROBJ.
|
|
pc_get_inode - Find a filename within a subdirectory
|
|
static pc_findin - Find a filename in the same directory as argument.
|
|
|
|
pc_get_mom - Find the parent inode of a subdirectory.
|
|
|
|
pc_mkchild - Allocate a DROBJ and fill in based on parent object.
|
|
pc_mknode - Create an empty subdirectory or file.
|
|
pc_insert_inode - Called only by pc_mknode
|
|
|
|
pc_rmnode - Delete an inode unconditionally.
|
|
pc_update_inode - Flush an inode to disk
|
|
|
|
pc_read_obj - Assign an initialized BLKBUFF to a DROBJ
|
|
pc_write_obj - Write a DROBJ s BLKBUFF to disk
|
|
|
|
pc_get_root - Create the special ROOT object for a drive.
|
|
pc_firstblock - Return the absolute block number of a directory
|
|
pc_next_block - Calculate the next block owned by an object.
|
|
pc_l_next_block - Calculate the next block in a chain.
|
|
|
|
We keep a shared image of directory entries around. These routines
|
|
keep track of them for us.
|
|
pc_marki - Set dr:sec:index, + stitch FINODE into the inode list
|
|
pc_scani - Search for an inode in the internal inode list.
|
|
Heap management routines
|
|
|
|
pc_allocobj -
|
|
pc_alloci -
|
|
pc_free_all_i -
|
|
pc_freei -
|
|
pc_freeobj -
|
|
|
|
Simple helper routines
|
|
pc_dos2inode -
|
|
pc_ino2dos -
|
|
pc_init_inode -
|
|
pc_isadir -
|
|
|
|
*/
|
|
|
|
#include <rtfs.h>
|
|
|
|
|
|
/***************************************************************************
|
|
PC_GET_CWD - Get the current working directory for a drive,
|
|
|
|
Description
|
|
Return the current directory inode for the drive represented by ddrive.
|
|
|
|
***************************************************************************/
|
|
|
|
/* Get the current working directory and copy it into pobj */
|
|
DROBJ *pc_get_cwd(DDRIVE *pdrive) /*__fn__*/
|
|
{
|
|
DROBJ *pcwd;
|
|
DROBJ *pobj;
|
|
|
|
pcwd = (DROBJ *)(rtfs_get_system_user()->lcwd[pdrive->driveno]);
|
|
|
|
/* If no current working dir set it to the root */
|
|
if (!pcwd)
|
|
{
|
|
pcwd = pc_get_root(pdrive);
|
|
rtfs_get_system_user()->lcwd[pdrive->driveno] = pcwd;
|
|
}
|
|
|
|
if (pcwd)
|
|
{
|
|
pobj = pc_allocobj();
|
|
if (!pobj)
|
|
{
|
|
return (0);
|
|
}
|
|
/* Free the inode that comes with allocobj */
|
|
pc_freei(pobj->finode);
|
|
OS_CLAIM_FSCRITICAL()
|
|
copybuff(pobj, pcwd, sizeof(DROBJ));
|
|
pobj->finode->opencount += 1;
|
|
OS_RELEASE_FSCRITICAL()
|
|
return (pobj);
|
|
}
|
|
else /* If no cwd is set error */
|
|
{
|
|
rtfs_set_errno(PEINTERNAL);
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
PC_FNDNODE - Find a file or directory on disk and return a DROBJ.
|
|
|
|
Description
|
|
Take a full path name and traverse the path until we get to the file
|
|
or subdir at the end of the path spec. When found allocate and init-
|
|
ialize (OPEN) a DROBJ.
|
|
|
|
Returns
|
|
Returns a pointer to a DROBJ if the file was found, otherwise 0.
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
/* Find path and create a DROBJ structure if found */
|
|
DROBJ *pc_fndnode(byte *path) /*__fn__*/
|
|
{
|
|
DROBJ *pobj;
|
|
DROBJ *pmom;
|
|
DROBJ *pchild;
|
|
int driveno;
|
|
DDRIVE *pdrive;
|
|
byte *filename;
|
|
byte fileext[4];
|
|
byte *pf0,*pf1;
|
|
BLKBUFF *scratch;
|
|
|
|
|
|
/* Get past D: plust get drive number if there */
|
|
path = pc_parsedrive( &driveno, path );
|
|
if (!path)
|
|
{
|
|
rtfs_set_errno(PEINVALIDDRIVEID); /* pc_fndnode: parsedrive failed */
|
|
return (0);
|
|
}
|
|
/* Find the drive */
|
|
pdrive = pc_drno2dr(driveno);
|
|
if (!pdrive)
|
|
{
|
|
rtfs_set_errno(PEINVALIDDRIVEID); /* pc_fndnode: pc_drno2dr failed */
|
|
return (0);
|
|
}
|
|
/* Get the top of the current path */
|
|
if (CS_OP_CMP_ASCII(path, '\\'))
|
|
{
|
|
CS_OP_INC_PTR(path);
|
|
pobj = pc_get_root(pdrive);
|
|
}
|
|
else
|
|
{
|
|
pobj = pc_get_cwd(pdrive);
|
|
}
|
|
|
|
if (!pobj)
|
|
return (0);
|
|
scratch = pc_scratch_blk();
|
|
if (!scratch)
|
|
return(0);
|
|
filename = (byte *)scratch->data;
|
|
|
|
/* Search through the path til exausted */
|
|
while (CS_OP_IS_NOT_EOS(path))
|
|
{
|
|
path = pc_nibbleparse(filename,fileext, path );
|
|
if (!path)
|
|
{
|
|
pc_free_scratch_blk(scratch);
|
|
rtfs_set_errno(PENOENT); /* pc_fndnode: no match */
|
|
pc_freeobj(pobj);
|
|
return (0);
|
|
}
|
|
#if (RTFS_SUBDIRS)
|
|
pf1 = pf0 = filename;
|
|
CS_OP_INC_PTR(pf1);
|
|
#if (VFAT)
|
|
if (CS_OP_CMP_ASCII(pf0,'.') && CS_OP_IS_EOS(pf1)) /* DOT */
|
|
;
|
|
#else
|
|
/* Tomo */
|
|
if (CS_OP_CMP_ASCII(pf0,'.') && CS_OP_CMP_ASCII(pf1,' ')) /* DOT-in NON-VFAT it is space filled */
|
|
;
|
|
#endif
|
|
#endif
|
|
else
|
|
{
|
|
/* Find Filename in pobj. and initialize lpobj with result */
|
|
pchild = pc_get_inode(0, pobj, filename, fileext, GET_INODE_MATCH);
|
|
if (!pchild)
|
|
{ /* get_inode set errno */
|
|
pc_free_scratch_blk(scratch);
|
|
pc_freeobj(pobj);
|
|
return (0);
|
|
}
|
|
#if (RTFS_SUBDIRS)
|
|
/* We found it. We have one special case. if DOTDOT we need
|
|
to shift up a level so we are not the child of mom
|
|
but of grand mom. */
|
|
pf1 = pf0 = filename;
|
|
CS_OP_INC_PTR(pf1);
|
|
if (CS_OP_CMP_ASCII(pf0,'.') && CS_OP_CMP_ASCII(pf1,'.'))
|
|
{
|
|
/* Find pobj s parent. By looking back from DOTDOT */
|
|
pmom = pc_get_mom(pchild);
|
|
/* We are done with pobj for now */
|
|
pc_freeobj(pobj);
|
|
|
|
if (!pmom)
|
|
{ /* Get mom set errno */
|
|
pc_free_scratch_blk(scratch);
|
|
pc_freeobj(pchild);
|
|
return (0);
|
|
}
|
|
else
|
|
{
|
|
/* We found the parent now free the child */
|
|
pobj = pmom;
|
|
pc_freeobj(pchild);
|
|
}
|
|
}
|
|
else
|
|
#endif /* SUBDIRS */
|
|
{
|
|
/* We are done with pobj for now */
|
|
pc_freeobj(pobj);
|
|
/* Make sure pobj points at the next inode */
|
|
pobj = pchild;
|
|
#if (RTFS_SUBDIRS)
|
|
#else
|
|
/* No subdirectory support. Return the one we found */
|
|
pc_free_scratch_blk(scratch);
|
|
return (pobj);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
pc_free_scratch_blk(scratch);
|
|
return (pobj);
|
|
}
|
|
|
|
/***************************************************************************
|
|
PC_GET_INODE - Find a filename within a subdirectory
|
|
|
|
Description
|
|
Search the directory pmom for the pattern or name in filename:ext and
|
|
return the an initialized object. If pobj is NULL start the search at
|
|
the top of pmom (getfirst) and allocate pobj before returning it.
|
|
Otherwise start the search at pobj (getnext). (see also pc_gfirst,
|
|
pc_gnext)
|
|
|
|
|
|
Note: Filename and ext must be right filled with spaces to 8 and 3 bytes
|
|
respectively. Null termination does not matter.
|
|
|
|
Note the use of the action variable. This is used so we do not have to
|
|
use match patterns in the core code like *.* and ..
|
|
GET_INODE_MATCH Must match the pattern exactly
|
|
GET_INODE_WILD Pattern may contain wild cards
|
|
GET_INODE_STAR Like he passed *.* (pattern will be null)
|
|
GET_INODE_DOTDOT Like he past .. (pattern will be null
|
|
|
|
|
|
Returns
|
|
Returns a drobj pointer or NULL if file not found.
|
|
***************************************************************************/
|
|
|
|
/* Give a directory mom. And a file name and extension.
|
|
Find find the file or dir and initialize pobj.
|
|
If pobj is NULL. We allocate and initialize the object otherwise we get the
|
|
next item in the chain of dirents.
|
|
*/
|
|
DROBJ *pc_get_inode( DROBJ *pobj, DROBJ *pmom, byte *filename, byte *fileext, int action) /*__fn__*/
|
|
{
|
|
BOOLEAN starting = FALSE;
|
|
/* Create the child if just starting */
|
|
if (!pobj)
|
|
{
|
|
starting = TRUE;
|
|
pobj = pc_mkchild(pmom); /* If failure sets errno */
|
|
if (!pobj)
|
|
return(0);
|
|
}
|
|
else /* If doing a gnext do not get stuck in and endless loop */
|
|
{
|
|
if ( ++(pobj->blkinfo.my_index) >= INOPBLOCK )
|
|
{
|
|
rtfs_set_errno(0); /* Clear errno to be safe */
|
|
if (!pc_next_block(pobj)) /* Will set errno illegal block id encountered */
|
|
{
|
|
if (!get_errno())
|
|
rtfs_set_errno(PENOENT); /* pc_get_inode: end of dir */
|
|
if (starting)
|
|
pc_freeobj(pobj);
|
|
return(0);
|
|
}
|
|
else
|
|
pobj->blkinfo.my_index = 0;
|
|
}
|
|
}
|
|
if (pc_findin(pobj, filename, fileext,action))
|
|
{
|
|
return (pobj);
|
|
}
|
|
else
|
|
{
|
|
/* pc_findin set errno */
|
|
if (starting)
|
|
pc_freeobj(pobj);
|
|
return (0);
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
PC_GET_MOM - Find the parent inode of a subdirectory.
|
|
|
|
Description
|
|
Given a DROBJ initialized with the contents of a subdirectory s DOTDOT
|
|
entry, initialize a DROBJ which is the parent of the current directory.
|
|
|
|
Returns
|
|
Returns a DROBJ pointer or NULL if could something went wrong.
|
|
|
|
|
|
****************************************************************************/
|
|
#if (RTFS_SUBDIRS)
|
|
|
|
/*
|
|
* Get mom:
|
|
* if (!dotodot->cluster) Mom is root.
|
|
* getroot()
|
|
* else cluster points to mom.
|
|
* find .. in mom
|
|
* then search through the directory pointed to by moms .. until
|
|
* you find mom. This will be current block startblock etc for mom.
|
|
*/
|
|
|
|
DROBJ *pc_get_mom(DROBJ *pdotdot) /*__fn__*/
|
|
{
|
|
DROBJ *pmom;
|
|
DDRIVE *pdrive = pdotdot->pdrive;
|
|
BLOCKT sectorno;
|
|
BLKBUFF *rbuf;
|
|
DIRBLK *pd;
|
|
DOSINODE *pi;
|
|
FINODE *pfi;
|
|
dword clno;
|
|
/* We have to be a subdir */
|
|
if (!pc_isadir(pdotdot))
|
|
{
|
|
rtfs_set_errno(PEINVALIDDIR);
|
|
return(0);
|
|
}
|
|
|
|
/* If ..->cluster is zero then parent is root */
|
|
if (!pc_finode_cluster(pdrive,pdotdot->finode))
|
|
return(pc_get_root(pdrive));
|
|
|
|
/* Otherwise : cluster points to the beginning of our parent.
|
|
we also need the position of our parent in its parent */
|
|
pmom = pc_allocobj();
|
|
if (!pmom)
|
|
return (0);
|
|
|
|
pmom->pdrive = pdrive;
|
|
/* Find .. in our parent s directory */
|
|
clno = pc_finode_cluster(pdrive,pdotdot->finode);
|
|
if ((clno < 2) || (clno > pdrive->maxfindex) )
|
|
{
|
|
pc_freeobj(pmom);
|
|
rtfs_set_errno(PEINVALIDCLUSTER);
|
|
return (0);
|
|
}
|
|
sectorno = pc_cl2sector(pdrive,clno);
|
|
/* We found .. in our parents dir. */
|
|
pmom->pdrive = pdrive;
|
|
pmom->blkinfo.my_frstblock = sectorno;
|
|
pmom->blkinfo.my_block = sectorno;
|
|
pmom->blkinfo.my_index = 0;
|
|
pmom->isroot = FALSE;
|
|
pd = &pmom->blkinfo;
|
|
|
|
pmom->pblkbuff = rbuf = pc_read_blk(pdrive, pmom->blkinfo.my_block);
|
|
if (rbuf)
|
|
{
|
|
pi = (DOSINODE *) &rbuf->data[0];
|
|
OS_CLAIM_FSCRITICAL()
|
|
pc_dos2inode(pmom->finode , pi );
|
|
OS_RELEASE_FSCRITICAL()
|
|
|
|
pc_release_buf(rbuf);
|
|
|
|
/* See if the inode is in the buffers */
|
|
pfi = pc_scani(pdrive, sectorno, 0);
|
|
if (pfi)
|
|
{
|
|
pc_freei(pmom->finode);
|
|
pmom->finode = pfi;
|
|
}
|
|
else
|
|
{
|
|
pc_marki(pmom->finode , pmom->pdrive , pd->my_block,
|
|
pd->my_index);
|
|
}
|
|
return (pmom);
|
|
|
|
}
|
|
else /* Error, something did not work */
|
|
{
|
|
pc_freeobj(pmom);
|
|
return (0);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/**************************************************************************
|
|
PC_MKCHILD - Allocate a DROBJ and fill in based on parent object.
|
|
|
|
Description
|
|
Allocate an object and fill in as much of the the block pointer section
|
|
as possible based on the parent.
|
|
|
|
Returns
|
|
Returns a partially initialized DROBJ if enough core available and
|
|
pmom was a valid subdirectory.
|
|
|
|
****************************************************************************/
|
|
|
|
DROBJ *pc_mkchild( DROBJ *pmom) /*__fn__*/
|
|
{
|
|
DROBJ *pobj;
|
|
DIRBLK *pd;
|
|
|
|
/* Mom must be a directory */
|
|
if (!pc_isadir(pmom))
|
|
{
|
|
rtfs_set_errno(PEINVALIDDIR); /* pc_mkchild: Internal error, parent dir provided */
|
|
return(0);
|
|
}
|
|
/* init the object - */
|
|
pobj = pc_allocobj();
|
|
if (!pobj)
|
|
return (0);
|
|
|
|
pd = &pobj->blkinfo;
|
|
|
|
pobj->isroot = FALSE; /* Child can not be root */
|
|
pobj->pdrive = pmom->pdrive; /* Child inherets moms drive */
|
|
|
|
/* Now initialize the fields storing where the child inode lives */
|
|
pd->my_index = 0;
|
|
pd->my_block = pd->my_frstblock = pc_firstblock(pmom);
|
|
if (!pd->my_block)
|
|
{
|
|
pc_freeobj(pobj);
|
|
return (0);
|
|
}
|
|
|
|
return (pobj);
|
|
}
|
|
|
|
/**************************************************************************
|
|
PC_MKNODE - Create an empty subdirectory or file.
|
|
|
|
Description
|
|
Creates a file or subdirectory inode depending on the flag values in
|
|
attributes. A pointer to an inode is returned for further processing. See
|
|
po_open(),po_close(), pc_mkdir() et al for examples.
|
|
|
|
Note: After processing, the DROBJ must be released by calling pc_freeobj.
|
|
|
|
Returns
|
|
Returns a pointer to a DROBJ structure for further use, or NULL if the
|
|
inode name already exists or path not found.
|
|
**************************************************************************/
|
|
|
|
/* Make a node from path and attribs create and fill in pobj */
|
|
/* Note: the parent directory is locked before this routine is called */
|
|
DROBJ *pc_mknode(DROBJ *pmom ,byte *filename, byte *fileext, byte attributes, CLUSTERTYPE incluster) /*__fn__*/
|
|
{
|
|
DROBJ *pobj;
|
|
BOOLEAN ret_val;
|
|
DOSINODE *pdinodes;
|
|
FINODE lfinode;
|
|
CLUSTERTYPE cluster;
|
|
CLUSTERTYPE cltemp;
|
|
DATESTR crdate;
|
|
BLKBUFF *pbuff;
|
|
DDRIVE *pdrive;
|
|
byte attr;
|
|
#if (RTFS_SUBDIRS)
|
|
byte dot_str[4]; /* Make DOT and DOTDOT strings */
|
|
byte null_str[4];
|
|
#endif
|
|
|
|
ret_val = TRUE;
|
|
|
|
if (!pmom || !pmom->pdrive)
|
|
{
|
|
rtfs_set_errno(PEINTERNAL); /* pc_mknode: Internal error*/
|
|
return (0);
|
|
}
|
|
/* Make sure the file/directory name is legal */
|
|
if (!validate_filename(filename, fileext))
|
|
{
|
|
rtfs_set_errno(PEINVALIDPATH);
|
|
return (0);
|
|
}
|
|
|
|
|
|
pdrive = pmom->pdrive;
|
|
cluster = incluster;
|
|
#if (RTFS_SUBDIRS)
|
|
if (attributes & ADIRENT)
|
|
{
|
|
/*Unless renaming a directory we grab a cluster for a new dir and */
|
|
/* clear it */
|
|
if (!incluster)
|
|
{
|
|
/* pc_alloc_dir will set errno */
|
|
cluster = pc_alloc_dir(pdrive,pmom);
|
|
if (!cluster)
|
|
ret_val = FALSE;
|
|
else if (!pc_clzero( pdrive , cluster ) )
|
|
{
|
|
/* clzero will set errno */
|
|
FATOP(pdrive)->fatop_clrelease_dir(pdrive , cluster);
|
|
ret_val = FALSE;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (!ret_val)
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
/* For a subdirectory. First make it a simple file. We will change the
|
|
attribute after all is clean */
|
|
attr = attributes;
|
|
#if (RTFS_SUBDIRS)
|
|
if (attr & ADIRENT)
|
|
attr = ANORMAL;
|
|
#endif
|
|
/* Allocate an empty DROBJ and FINODE to hold the new file */
|
|
|
|
pobj = pc_allocobj();
|
|
if (!pobj)
|
|
{
|
|
return (0);
|
|
}
|
|
/* Set up the drive link */
|
|
pobj->pdrive = pmom->pdrive;
|
|
|
|
/* Load the inode copy name,ext,attr,cluster, size,datetime */
|
|
/* Convert pobj to native and stitch it in to mom */
|
|
if (!pc_insert_inode(pobj , pmom, attr, cluster, filename, fileext))
|
|
{
|
|
if (cluster && !incluster)
|
|
FATOP(pdrive)->fatop_clrelease_dir(pdrive , cluster);
|
|
pc_freeobj(pobj);
|
|
return (0);
|
|
}
|
|
|
|
#if (RTFS_SUBDIRS)
|
|
/* Now if we are creating subdirectory we have to make the DOT and DOT DOT
|
|
inodes and then change pobj s attribute to ADIRENT
|
|
The DOT and DOTDOT are not buffered inodes. We are simply putting
|
|
the to disk */
|
|
if ( attributes & ADIRENT)
|
|
{
|
|
if (incluster)
|
|
{
|
|
pbuff = pc_read_blk( pdrive , pc_cl2sector(pdrive , incluster));
|
|
if (!pbuff)
|
|
{
|
|
pc_freeobj(pobj);
|
|
return (0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Set up a buffer to do surgery */
|
|
pbuff = pc_init_blk( pdrive , pc_cl2sector(pdrive , cluster));
|
|
if (!pbuff)
|
|
{
|
|
pc_freeobj(pobj);
|
|
FATOP(pdrive)->fatop_clrelease_dir(pdrive , cluster);
|
|
return (0);
|
|
}
|
|
}
|
|
pdinodes = (DOSINODE *) &pbuff->data[0];
|
|
/* Load DOT and DOTDOT in native form */
|
|
/* DOT first. It points to the begining of this sector */
|
|
dot_str[0] = CS_OP_ASCII('.');dot_str[1]=CS_OP_ASCII('\0');
|
|
null_str[0] = CS_OP_ASCII('\0');
|
|
|
|
/* Load the time and date stamp to be used for "." and ".."
|
|
from the subdirectory that we are creating. In this way
|
|
the three directory entries will all have the same timestamp
|
|
value */
|
|
crdate.time = pobj->finode->ftime;
|
|
crdate.date = pobj->finode->fdate;
|
|
pc_init_inode( &lfinode, dot_str,null_str, ADIRENT|ARCHIVE,
|
|
cluster, /*size*/ 0L , &crdate);
|
|
/* And to the buffer in intel form */
|
|
pc_ino2dos (pdinodes, &lfinode);
|
|
/* Now DOTDOT points to mom s cluster */
|
|
cltemp = pc_get_parent_cluster(pdrive, pobj);
|
|
dot_str[0] = CS_OP_ASCII('.');dot_str[1] = CS_OP_ASCII('.');
|
|
dot_str[2] = CS_OP_ASCII('\0');
|
|
null_str[0] = CS_OP_ASCII('\0');
|
|
pc_init_inode( &lfinode, dot_str, null_str, ADIRENT|ARCHIVE, cltemp,
|
|
/*size*/ 0L , &crdate);
|
|
/* And to the buffer in intel form */
|
|
pc_ino2dos (++pdinodes, &lfinode );
|
|
/* Write the cluster out */
|
|
if ( !pc_write_blk ( pbuff ) )
|
|
{
|
|
pc_discard_buf(pbuff);
|
|
pc_freeobj(pobj);
|
|
if (!incluster)
|
|
FATOP(pdrive)->fatop_clrelease_dir(pdrive , cluster);
|
|
return (0);
|
|
}
|
|
else
|
|
pc_release_buf(pbuff);
|
|
|
|
/* And write the node out with the original attributes */
|
|
pobj->finode->fattribute = (byte)(attributes|ARCHIVE);
|
|
|
|
/* Convert to native. Overwrite the existing inode.Set archive/date */
|
|
if (!pc_update_inode(pobj, TRUE, TRUE))
|
|
{
|
|
pc_freeobj(pobj);
|
|
if (!incluster)
|
|
FATOP(pdrive)->fatop_clrelease_dir(pdrive , cluster);
|
|
return (0);
|
|
}
|
|
}
|
|
#endif
|
|
ret_val = FATOP(pdrive)->fatop_flushfat(pdrive->driveno);
|
|
|
|
if (ret_val)
|
|
{
|
|
return (pobj);
|
|
}
|
|
else
|
|
{
|
|
pc_freeobj(pobj);
|
|
return (0);
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
PC_RMNODE - Delete an inode unconditionally.
|
|
|
|
Description
|
|
Delete the inode at pobj and flush the file allocation table. Does not
|
|
check file permissions or if the file is already open. (see also pc_unlink
|
|
and pc_rmdir). The inode is marked deleted on the disk and the cluster
|
|
chain associated with the inode is freed. (Un-delete wo not work)
|
|
|
|
Returns
|
|
Returns TRUE if it successfully deleted the inode an flushed the fat.
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
/* Delete a file / dir or volume. Do not check for write access et al */
|
|
/* Note: the parent directory is locked before this routine is called */
|
|
BOOLEAN pc_rmnode( DROBJ *pobj) /*__fn__*/
|
|
{
|
|
CLUSTERTYPE cluster;
|
|
DDRIVE *pdrive;
|
|
|
|
/* Do not delete anything that has multiple links */
|
|
if (pobj->finode->opencount > 1)
|
|
{
|
|
rtfs_set_errno(PEACCES); /* pc_rmnode() - directory entry is in use */
|
|
err_ex:
|
|
pc_report_error(PCERR_REMINODE);
|
|
return (FALSE);
|
|
}
|
|
pdrive = pobj->pdrive;
|
|
/* Mark it deleted and unlink the cluster chain */
|
|
pobj->finode->fname[0] = PCDELETEESCAPE;
|
|
|
|
cluster = pc_finode_cluster(pdrive,pobj->finode);
|
|
|
|
if (!pc_delete_lfn_info(pobj)) /* Delete lonf file name info associated with DROBJ */
|
|
goto err_ex;
|
|
|
|
/* We free up store right away. Do not leave cluster pointer
|
|
hanging around to cause problems. */
|
|
pc_pfinode_cluster(pdrive,pobj->finode,0);
|
|
/* Convert to native. Overwrite the existing inode.Set archive/date */
|
|
if (pc_update_inode(pobj, TRUE, TRUE))
|
|
{
|
|
/* If there is no cluster chain to delete don't call freechain */
|
|
if (!cluster)
|
|
return(TRUE);
|
|
/* And clear up the space */
|
|
/* Tomo */
|
|
/* Make sure the blocks contained within the cluster chain
|
|
are flushed from the block buffer pool */
|
|
pc_flush_chain_blk(pdrive, cluster);
|
|
/* Set min to 0 and max to 0xffffffff to eliminate range checking on the
|
|
cluster chain and force removal of all clusters */
|
|
if (!FATOP(pdrive)->fatop_freechain(pdrive, cluster, 0, 0xffffffff))
|
|
{
|
|
/* If freechain failed still flush the fat in INVALID CLUSTER
|
|
was the failure condition */
|
|
if (get_errno() == PEINVALIDCLUSTER)
|
|
FATOP(pdrive)->fatop_flushfat(pobj->pdrive->driveno);
|
|
return(FALSE);
|
|
|
|
}
|
|
else if ( FATOP(pdrive)->fatop_flushfat(pobj->pdrive->driveno) )
|
|
return (TRUE);
|
|
}
|
|
/* If it gets here we had a problem */
|
|
return(FALSE);
|
|
}
|
|
|
|
/**************************************************************************
|
|
PC_UPDATE_INODE - Flush an inode to disk
|
|
|
|
Summary
|
|
|
|
Description
|
|
Read the disk inode information stored in pobj and write it to
|
|
the block and offset on the disk where it belongs. The disk is
|
|
first read to get the block and then the inode info is merged in
|
|
and the block is written. (see also pc_mknode() )
|
|
|
|
Returns
|
|
Returns TRUE if all went well, no on a write error.
|
|
|
|
*****************************************************************************
|
|
*/
|
|
|
|
/* Take a DROBJ that contains correct my_index & my_block. And an inode.
|
|
Load the block. Copy the inode in and write it back out */
|
|
BOOLEAN pc_update_inode(DROBJ *pobj, BOOLEAN set_archive, BOOLEAN set_date) /*__fn__*/
|
|
{
|
|
BLKBUFF *pbuff;
|
|
DOSINODE *pi;
|
|
int i;
|
|
DIRBLK *pd;
|
|
DATESTR crdate;
|
|
|
|
pd = &pobj->blkinfo;
|
|
i = pd->my_index;
|
|
if ( i >= INOPBLOCK || i < 0 ) /* Index into block */
|
|
{
|
|
rtfs_set_errno(PEINTERNAL); /* pc_update_inode: Internal error, illegal inode index */
|
|
return (FALSE);
|
|
}
|
|
OS_CLAIM_FSCRITICAL()
|
|
/* Set the archive bit and the date */
|
|
if (set_archive)
|
|
pobj->finode->fattribute |= ARCHIVE;
|
|
|
|
if (set_date)
|
|
{
|
|
pc_getsysdate(&crdate);
|
|
pobj->finode->ftime = crdate.time;
|
|
pobj->finode->fdate = crdate.date;
|
|
}
|
|
OS_RELEASE_FSCRITICAL()
|
|
/* Read the data */
|
|
pobj->pblkbuff = pbuff = pc_read_blk(pobj->pdrive, pobj->blkinfo.my_block);
|
|
if (pbuff)
|
|
{
|
|
pi = (DOSINODE *) &pbuff->data[0];
|
|
/* Copy it off and write it */
|
|
pc_ino2dos( (pi+i), pobj->finode );
|
|
if (!pc_write_blk(pbuff))
|
|
{
|
|
pc_discard_buf(pbuff);
|
|
return (FALSE);
|
|
}
|
|
else
|
|
{
|
|
pc_release_buf(pbuff);
|
|
return (TRUE);
|
|
}
|
|
}
|
|
return (FALSE);
|
|
}
|
|
|
|
#if (RTFS_WRITE)
|
|
/* Load an in memory inode up with user supplied values */
|
|
void pc_init_inode(FINODE *pdir, KS_CONSTANT byte *filename, /*__fn__*/
|
|
KS_CONSTANT byte *fileext, byte attr,
|
|
CLUSTERTYPE cluster, dword size, DATESTR *crdate) /*__fn__*/
|
|
{
|
|
/* Copy the file names and pad with spaces */
|
|
pc_cppad(pdir->fname,(byte*)filename,8);
|
|
pc_cppad(pdir->fext,(byte*)fileext,3);
|
|
pdir->fattribute = attr;
|
|
rtfs_memset(&pdir->resarea[0],(byte) 0,8);
|
|
|
|
pdir->ftime = crdate->time;
|
|
pdir->fdate = crdate->date;
|
|
/* Note: fclusterhi is of resarea in fat 16 system and cluster>>16 is 0*/
|
|
pdir->fclusterhi = (word)(cluster >> 16);
|
|
pdir->fcluster = (word) cluster;
|
|
pdir->fsize = size;
|
|
pc_zero_lfn_info(pdir);
|
|
|
|
}
|
|
|
|
/***************************************************************************
|
|
PC_INO2DOS - Convert an in memory inode to a dos disk entry.
|
|
|
|
Description
|
|
Take in memory native format inode information and copy it to a
|
|
buffer. Translate the inode to INTEL byte ordering during the transfer.
|
|
|
|
Returns
|
|
Nothing
|
|
|
|
***************************************************************************/
|
|
/* Un-Make a disk directory entry */
|
|
/* Convert an inmem inode to dos form. */
|
|
void pc_ino2dos (DOSINODE *pbuff, FINODE *pdir) /*__fn__*/
|
|
{
|
|
pc_ascii_strn2upper((byte *)&pbuff->fname[0],(byte *)&pdir->fname[0],8); /*X*/
|
|
pc_ascii_strn2upper((byte *)&pbuff->fext[0],(byte *)&pdir->fext[0],3); /*X*/
|
|
pbuff->fattribute = pdir->fattribute; /*X*/
|
|
/* If the first character is 0xE5 (valid kanji) convert it to 0x5 */
|
|
if (pdir->fname[0] == PCDELETE) /* 0XE5 */
|
|
pbuff->fname[0] = 0x5;
|
|
|
|
/* If rmnode wants us to delete the file set it to 0xE5 */
|
|
if (pdir->fname[0] == PCDELETEESCAPE)
|
|
pbuff->fname[0] = PCDELETE;
|
|
|
|
|
|
copybuff(&pbuff->resarea[0],&pdir->resarea[0], 8); /*X*/
|
|
#if (KS_LITTLE_ENDIAN)
|
|
pbuff->ftime = pdir->ftime;
|
|
pbuff->fdate = pdir->fdate;
|
|
pbuff->fcluster = pdir->fcluster;
|
|
/* Note: fclusterhi is of resarea in fat 16 system */
|
|
pbuff->fclusterhi = pdir->fclusterhi;
|
|
pbuff->fsize = pdir->fsize;
|
|
#else
|
|
fr_WORD((byte *) &pbuff->ftime,pdir->ftime); /*X*/
|
|
fr_WORD((byte *) &pbuff->fdate,pdir->fdate); /*X*/
|
|
fr_WORD((byte *) &pbuff->fcluster,pdir->fcluster); /*X*/
|
|
/* Note: fclusterhi is of resarea in fat 16 system */
|
|
fr_WORD((byte *) &pbuff->fclusterhi,pdir->fclusterhi); /*X*/
|
|
fr_DWORD((byte *) &pbuff->fsize,pdir->fsize); /*X*/
|
|
#endif
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/*************************************************************************
|
|
PC_GET_ROOT - Create the special ROOT object for a drive.
|
|
Description
|
|
Use the information in pdrive to create a special object for accessing
|
|
files in the root directory.
|
|
|
|
Returns
|
|
Returns a pointer to a DROBJ, or NULL if no core available.
|
|
****************************************************************************/
|
|
|
|
/* Initialize the special root object
|
|
Note: We do not read any thing in here we just set up
|
|
the block pointers. */
|
|
|
|
DROBJ *pc_get_root( DDRIVE *pdrive) /*__fn__*/
|
|
{
|
|
DIRBLK *pd;
|
|
DROBJ *pobj;
|
|
FINODE *pfi;
|
|
|
|
pobj = pc_allocobj();
|
|
if (!pobj)
|
|
return (0);
|
|
pobj->pdrive = pdrive;
|
|
|
|
pfi = pc_scani(pdrive, 0, 0);
|
|
|
|
if (pfi)
|
|
{
|
|
pc_freei(pobj->finode);
|
|
pobj->finode = pfi;
|
|
}
|
|
else /* No inode in the inode list. Copy the data over
|
|
and mark where it came from */
|
|
{
|
|
pc_marki(pobj->finode , pdrive , 0, 0);
|
|
}
|
|
|
|
|
|
/* Add a TEST FOR DRIVE INIT Here later */
|
|
pobj->pdrive = pdrive;
|
|
/* Set up the tree stuf so we know it is the root */
|
|
pd = &pobj->blkinfo;
|
|
pd->my_frstblock = pdrive->rootblock;
|
|
pd->my_block = pdrive->rootblock;
|
|
pd->my_index = 0;
|
|
pobj->isroot = TRUE;
|
|
return (pobj);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
PC_FIRSTBLOCK - Return the absolute block number of a directory s
|
|
contents.
|
|
Description
|
|
Returns the block number of the first inode in the subdirectory. If
|
|
pobj is the root directory the first block of the root will be returned.
|
|
|
|
Returns
|
|
Returns 0 if the obj does not point to a directory, otherwise the
|
|
first block in the directory is returned.
|
|
|
|
*****************************************************************************/
|
|
|
|
/* Get the first block of a root or subdir */
|
|
BLOCKT pc_firstblock( DROBJ *pobj) /*__fn__*/
|
|
{
|
|
dword clno;
|
|
if (!pc_isadir(pobj))
|
|
{
|
|
rtfs_set_errno(PEINTERNAL); /* pc_firstblock: Internal error */
|
|
return (BLOCKEQ0);
|
|
}
|
|
/* Root dir ? */
|
|
#if (RTFS_SUBDIRS)
|
|
if (!pobj->isroot)
|
|
{
|
|
clno = pc_finode_cluster(pobj->pdrive, pobj->finode);
|
|
if ((clno < 2) || (clno > pobj->pdrive->maxfindex) )
|
|
{
|
|
rtfs_set_errno(PEINVALIDCLUSTER);
|
|
return (0);
|
|
}
|
|
return (pc_cl2sector(pobj->pdrive , clno));
|
|
}
|
|
else
|
|
#endif
|
|
return (pobj->blkinfo.my_frstblock);
|
|
}
|
|
|
|
/***************************************************************************
|
|
PC_NEXT_BLOCK - Calculate the next block owned by an object.
|
|
|
|
Description
|
|
Find the next block owned by an object in either the root or a cluster
|
|
chain and update the blockinfo section of the object.
|
|
|
|
Returns
|
|
Returns TRUE or FALSE on end of chain.
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
/* Calculate the next block in an object */
|
|
BOOLEAN pc_next_block( DROBJ *pobj) /*__fn__*/
|
|
{
|
|
BLOCKT nxt;
|
|
|
|
nxt = pc_l_next_block(pobj->pdrive, pobj->blkinfo.my_block);
|
|
|
|
if (nxt)
|
|
{
|
|
pobj->blkinfo.my_block = nxt;
|
|
return (TRUE);
|
|
}
|
|
else
|
|
return (FALSE);
|
|
}
|
|
|
|
/**************************************************************************
|
|
PC_L_NEXT_BLOCK - Calculate the next block in a chain.
|
|
|
|
Description
|
|
Find the next block in either the root or a cluster chain.
|
|
|
|
Returns
|
|
Returns 0 on end of root dir or chain.
|
|
|
|
****************************************************************************/
|
|
|
|
/* Return the next block in a chain */
|
|
BLOCKT pc_l_next_block(DDRIVE *pdrive, BLOCKT curblock) /*__fn__*/
|
|
{
|
|
CLUSTERTYPE cluster;
|
|
/* If the block is in the root area */
|
|
if (curblock < pdrive->firstclblock)
|
|
{
|
|
if (curblock < pdrive->rootblock)
|
|
{
|
|
rtfs_set_errno(PEINVALIDBLOCKNUMBER); /* pc_l_next_block: Internal error */
|
|
return (BLOCKEQ0);
|
|
}
|
|
else if (++curblock < pdrive->firstclblock)
|
|
return (curblock);
|
|
else
|
|
return (BLOCKEQ0);
|
|
}
|
|
else /* In cluster space */
|
|
{
|
|
if (curblock >= pdrive->numsecs)
|
|
{
|
|
rtfs_set_errno(PEINVALIDBLOCKNUMBER); /* pc_l_next_block: Internal error */
|
|
return (BLOCKEQ0);
|
|
}
|
|
/* Get the next block */
|
|
curblock += 1;
|
|
|
|
/* If the next block is not on a cluster edge then it must be
|
|
in the same cluster as the current. - otherwise we have to
|
|
get the firt block from the next cluster in the chain */
|
|
if (pc_sec2index(pdrive, curblock))
|
|
return (curblock);
|
|
else
|
|
{
|
|
curblock -= 1;
|
|
/* Get the old cluster number */
|
|
cluster = pc_sec2cluster(pdrive,curblock);
|
|
if ((cluster < 2) || (cluster > pdrive->maxfindex) )
|
|
{
|
|
rtfs_set_errno(PEINVALIDBLOCKNUMBER); /* pc_l_next_block: Internal error */
|
|
return (BLOCKEQ0);
|
|
}
|
|
/* Consult the fat for the next cluster */
|
|
cluster = FATOP(pdrive)->fatop_clnext(pdrive, cluster); /* Directory */
|
|
if (cluster == 0xffffffff)
|
|
return (BLOCKEQ0); /* End of chain */
|
|
else if (cluster == 0) /* clnext detected error */
|
|
{
|
|
return (BLOCKEQ0);
|
|
}
|
|
else
|
|
return (pc_cl2sector(pdrive, cluster));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
PC_MARKI - Set dr:sec:index info and stitch a FINODE into the inode list
|
|
|
|
|
|
Description
|
|
Each inode is uniquely determined by DRIVE, BLOCK and Index into that
|
|
block. This routine takes an inode structure assumed to contain the
|
|
equivalent of a DOS directory entry. And stitches it into the current
|
|
active inode list. Drive block and index are stored for later calls
|
|
to pc_scani and the inode s opencount is set to one.
|
|
|
|
Returns
|
|
Nothing
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/* Take an unlinked inode and link it in to the inode chain. Initialize
|
|
the open count and sector locater info. */
|
|
void pc_marki( FINODE *pfi, DDRIVE *pdrive, BLOCKT sectorno, int index)/*__fn__*/
|
|
{
|
|
OS_CLAIM_FSCRITICAL()
|
|
|
|
pfi->my_drive = pdrive;
|
|
pfi->my_block = sectorno;
|
|
pfi->my_index = index;
|
|
pfi->opencount = 1;
|
|
|
|
/* Stitch the inode at the front of the list */
|
|
if (prtfs_cfg->inoroot)
|
|
prtfs_cfg->inoroot->pprev = pfi;
|
|
|
|
pfi->pprev = 0;
|
|
pfi->pnext = prtfs_cfg->inoroot;
|
|
prtfs_cfg->inoroot = pfi;
|
|
|
|
OS_RELEASE_FSCRITICAL()
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
PC_SCANI - Search for an inode in the internal inode list.
|
|
|
|
Description
|
|
Each inode is uniquely determined by DRIVE, BLOCK and Index into that
|
|
block. This routine searches the current active inode list to see
|
|
if the inode is in use. If so the opencount is changed and a pointer is
|
|
returned. This guarantees that two processes will work on the same
|
|
information when manipulating the same file or directory.
|
|
|
|
Returns
|
|
A pointer to the FINODE for pdrive:sector:index or NULL if not found
|
|
|
|
****************************************************************************/
|
|
|
|
/* See if the inode for drive,sector , index is in the list. If so..
|
|
bump its open count and return it. Else return NULL */
|
|
|
|
FINODE *pc_scani( DDRIVE *pdrive, BLOCKT sectorno, int index) /*__fn__*/
|
|
{
|
|
FINODE *pfi;
|
|
OS_CLAIM_FSCRITICAL()
|
|
pfi = prtfs_cfg->inoroot;
|
|
while (pfi)
|
|
{
|
|
if ( (pfi->my_drive == pdrive) &&
|
|
(pfi->my_block == sectorno) &&
|
|
(pfi->my_index == index) )
|
|
{
|
|
pfi->opencount += 1;
|
|
OS_RELEASE_FSCRITICAL()
|
|
return (pfi);
|
|
}
|
|
pfi = pfi->pnext;
|
|
}
|
|
OS_RELEASE_FSCRITICAL()
|
|
return (0);
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
PC_ALLOCOBJ - Allocate a DROBJ structure
|
|
Description
|
|
Allocates and zeroes the space needed to store a DROBJ structure. Also
|
|
allocates and zeroes a FINODE structure and links the two via the
|
|
finode field in the DROBJ structure.
|
|
|
|
Returns
|
|
Returns a valid pointer or NULL if no more core.
|
|
|
|
*****************************************************************************/
|
|
|
|
DROBJ *pc_allocobj(void) /*__fn__*/
|
|
{
|
|
DROBJ *pobj;
|
|
|
|
/* Alloc a DROBJ */
|
|
pobj = pc_memory_drobj(0);
|
|
if (pobj)
|
|
{
|
|
pobj->finode = pc_alloci();
|
|
if (!pobj->finode)
|
|
{
|
|
/* Free the DROBJ */
|
|
pc_memory_drobj(pobj);
|
|
pobj = 0;
|
|
}
|
|
}
|
|
return (pobj);
|
|
}
|
|
|
|
/**************************************************************************
|
|
PC_ALLOCI - Allocate a FINODE structure
|
|
|
|
Description
|
|
Allocates and zeroes a FINODE structure.
|
|
|
|
Returns
|
|
Returns a valid pointer or NULL if no more core.
|
|
|
|
****************************************************************************/
|
|
|
|
FINODE *pc_alloci(void) /*__fn__*/
|
|
{
|
|
FINODE *p;
|
|
p = pc_memory_finode(0);
|
|
return(p);
|
|
}
|
|
|
|
/**************************************************************************
|
|
PC_FREE_ALL_DROBJ - Release all drobj buffers associated with a drive.
|
|
Description
|
|
For each internally buffered drobj structure associated with pdrive
|
|
Returns
|
|
Nothing
|
|
****************************************************************************/
|
|
|
|
void pc_free_all_drobj( DDRIVE *pdrive) /*__fn__*/
|
|
{
|
|
int i;
|
|
DROBJ *pobj;
|
|
pobj = prtfs_cfg->mem_drobj_pool;
|
|
for (i = 0; i < prtfs_cfg->cfg_NDROBJS; i++,pobj++)
|
|
{
|
|
if (pobj->pdrive == pdrive)
|
|
pc_memory_drobj(pobj);
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
PC_FREE_ALL_I - Release all inode buffers associated with a drive.
|
|
Description
|
|
For each internally buffered finode (dirent) check if it exists on
|
|
pdrive. If so delete it. In debug mode print a message since all
|
|
finodes should be freed before pc_dskclose is called.
|
|
Returns
|
|
Nothing
|
|
****************************************************************************/
|
|
|
|
void pc_free_all_i( DDRIVE *pdrive) /*__fn__*/
|
|
{
|
|
FINODE *pfi;
|
|
|
|
OS_CLAIM_FSCRITICAL()
|
|
pfi = prtfs_cfg->inoroot;
|
|
OS_RELEASE_FSCRITICAL()
|
|
while (pfi)
|
|
{
|
|
if (pfi->my_drive == pdrive)
|
|
{
|
|
/* Set the opencount to 1 so freei releases the inode */
|
|
pfi->opencount = 1;
|
|
pc_freei(pfi);
|
|
/* Since we changed the list go back to the top */
|
|
OS_CLAIM_FSCRITICAL()
|
|
pfi = prtfs_cfg->inoroot;
|
|
OS_RELEASE_FSCRITICAL()
|
|
}
|
|
else
|
|
{
|
|
OS_CLAIM_FSCRITICAL()
|
|
pfi = pfi->pnext;
|
|
OS_RELEASE_FSCRITICAL()
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
PC_FREEI - Release an inode from service
|
|
|
|
Description
|
|
If the FINODE structure is only being used by one file or DROBJ, unlink it
|
|
from the internal active inode list and return it to the heap; otherwise
|
|
reduce its open count.
|
|
|
|
Returns
|
|
Nothing
|
|
|
|
****************************************************************************/
|
|
|
|
void pc_freei( FINODE *pfi) /*__fn__*/
|
|
{
|
|
if (!pfi)
|
|
{
|
|
return;
|
|
}
|
|
OS_CLAIM_FSCRITICAL()
|
|
if (pfi->opencount)
|
|
{
|
|
if (--pfi->opencount) /* Decrement opencount and return if non zero */
|
|
{
|
|
OS_RELEASE_FSCRITICAL()
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if (pfi->pprev) /* Pont the guy behind us at the guy in front*/
|
|
{
|
|
pfi->pprev->pnext = pfi->pnext;
|
|
}
|
|
else
|
|
{
|
|
|
|
prtfs_cfg->inoroot = pfi->pnext; /* No prev, we were at the front so
|
|
make the next guy the front */
|
|
}
|
|
|
|
if (pfi->pnext) /* Make the next guy point behind */
|
|
{
|
|
pfi->pnext->pprev = pfi->pprev;
|
|
}
|
|
}
|
|
}
|
|
OS_RELEASE_FSCRITICAL()
|
|
/* release the core */
|
|
pc_memory_finode(pfi);
|
|
}
|
|
|
|
/***************************************************************************
|
|
PC_FREEOBJ - Free a DROBJ structure
|
|
|
|
Description
|
|
Return a drobj structure to the heap. Calls pc_freei to reduce the
|
|
open count of the finode structure it points to and return it to the
|
|
heap if appropriate.
|
|
|
|
Returns
|
|
Nothing
|
|
|
|
|
|
****************************************************************************/
|
|
|
|
void pc_freeobj( DROBJ *pobj) /*__fn__*/
|
|
{
|
|
if (pobj)
|
|
{
|
|
pc_freei(pobj->finode);
|
|
/* Release the core */
|
|
pc_memory_drobj(pobj);
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
PC_DOS2INODE - Convert a dos disk entry to an in memory inode.
|
|
|
|
Description
|
|
Take the data from pbuff which is a raw disk directory entry and copy
|
|
it to the inode at pdir. The data goes from INTEL byte ordering to
|
|
native during the transfer.
|
|
|
|
Returns
|
|
Nothing
|
|
****************************************************************************/
|
|
|
|
/* Convert a dos inode to in mem form. */
|
|
void pc_dos2inode (FINODE *pdir, DOSINODE *pbuff) /*__fn__*/
|
|
{
|
|
copybuff(&pdir->fname[0],&pbuff->fname[0],8); /*X*/
|
|
/* If the on disk representation is 0x5, change it to 0xE5, a valid
|
|
kanji character */
|
|
if (pdir->fname[0] == 0x5)
|
|
pdir->fname[0] = PCDELETE;
|
|
|
|
copybuff(&pdir->fext[0],&pbuff->fext[0],3); /*X*/
|
|
pdir->fattribute = pbuff->fattribute; /*X*/
|
|
copybuff(&pdir->resarea[0],&pbuff->resarea[0], 8); /*X*/
|
|
#if (!KS_LITTLE_ENDIAN)
|
|
pdir->ftime = to_WORD((byte *) &pbuff->ftime); /*X*/
|
|
pdir->fdate = to_WORD((byte *) &pbuff->fdate); /*X*/
|
|
/* Note: fclusterhi is of resarea in fat 16 system */
|
|
pdir->fclusterhi = to_WORD((byte *) &pbuff->fclusterhi);
|
|
pdir->fcluster = to_WORD((byte *) &pbuff->fcluster); /*X*/
|
|
pdir->fsize = to_DWORD((byte *) &pbuff->fsize); /*X*/
|
|
#else
|
|
pdir->ftime = pbuff->ftime; /*X*/
|
|
pdir->fdate = pbuff->fdate; /*X*/
|
|
/* Note: fclusterhi is of resarea in fat 16 system */
|
|
pdir->fclusterhi = pbuff->fclusterhi; /*X*/
|
|
pdir->fcluster = pbuff->fcluster; /*X*/
|
|
pdir->fsize = pbuff->fsize; /*X*/
|
|
#endif
|
|
}
|
|
|
|
/**************************************************************************
|
|
PC_INIT_INODE - Load an in memory inode up with user supplied values.
|
|
|
|
Description
|
|
Take an uninitialized inode (pdir) and fill in some fields. No other
|
|
processing is done. This routine simply copies the arguments into the
|
|
FINODE structure.
|
|
|
|
Note: filename & fileext do not need null termination.
|
|
|
|
Returns
|
|
Nothing
|
|
****************************************************************************/
|
|
/**************************************************************************
|
|
PC_ISAVOL - Test a DROBJ to see if it is a volume
|
|
|
|
Description
|
|
Looks at the appropriate elements in pobj and determines if it is a root
|
|
or subdirectory.
|
|
|
|
Returns
|
|
Returns FALSE if the obj does not point to a directory.
|
|
|
|
****************************************************************************/
|
|
|
|
BOOLEAN pc_isavol( DROBJ *pobj) /*__fn__*/
|
|
{
|
|
if (pobj->finode->fattribute & AVOLUME)
|
|
return(TRUE);
|
|
else
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
PC_ISADIR - Test a DROBJ to see if it is a root or subdirectory
|
|
|
|
Description
|
|
Looks at the appropriate elements in pobj and determines if it is a root
|
|
or subdirectory.
|
|
|
|
Returns
|
|
Returns FALSE if the obj does not point to a directory.
|
|
|
|
****************************************************************************/
|
|
|
|
BOOLEAN pc_isadir( DROBJ *pobj) /*__fn__*/
|
|
{
|
|
if ( (pobj->isroot) || (pobj->finode->fattribute & ADIRENT) )
|
|
return(TRUE);
|
|
else
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
PC_ISROOT - Test a DROBJ to see if it is the root directory
|
|
|
|
Description
|
|
Looks at the appropriate elements in pobj and determines if it is a root
|
|
directory.
|
|
|
|
Returns
|
|
Returns NO if the obj does not point to the root directory.
|
|
|
|
****************************************************************************/
|
|
|
|
/* Get the first block of a root or subdir */
|
|
BOOLEAN pc_isroot( DROBJ *pobj) /*__fn__*/
|
|
{
|
|
return(pobj->isroot);
|
|
}
|