📄 drobj.c
字号:
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright Peter Van Oudenaren , 1993
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* DROBJ.C - Directory object manipulation routines
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.
static 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.
static pc_firstblock - Return the absolute block number of a directory
static pc_next_block - Calculate the next block owned by an object.
static 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.
static pc_marki - Set dr:sec:index, + stitch FINODE into the inode list
static 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 -
pc_isroot -
*/
#include "pcdisk.h"
IMPORT FINODE *inoroot;
/**************************************************************************
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 NULL.
***************************************************************************/
/* Find "path" and create a DROBJ structure if found */
DROBJ *pc_fndnode(TEXT *path) /*__fn__*/
{
DROBJ *pobj;
DROBJ *pmom;
DROBJ *pchild;
COUNT driveno;
DDRIVE *pdrive;
UTEXT filename[9];
UTEXT fileext[4];
/* Get past D: plust get drive number if there */
path = pc_parsedrive( &driveno, path );
if (!path)
return (NULL);
/* Find the drive */
pdrive = pc_drno2dr(driveno);
if (!pdrive)
return (NULL);
/* Get the top of the current path */
if ( *path == BACKSLASH )
{
pobj = pc_get_root(pdrive);
if (!pobj)
return (NULL);
path++;
}
else
{
pobj = pc_get_cwd(pdrive);
if (!pobj)
return (NULL);
}
/* Search through the path til exausted */
while (*path)
{
path = pc_nibbleparse((TEXT*) filename,(TEXT*) fileext, path );
if (!path)
{
pc_freeobj(pobj);
return (NULL);
}
if (pc_isdot( filename, fileext ))
;
else
{
/* Find Filename in pobj. and initialize lpobj with result */
PC_INODE_ENTER(pobj->finode, NO)
pchild = pc_get_inode(NULL, pobj, filename, fileext);
if (!pchild)
{
PC_INODE_EXIT(pobj->finode)
pc_freeobj(pobj);
return (NULL);
}
/* We found it. We have one special case. if "..". we need
to shift up a level so we are not the child of mom
but of grand mom. */
if (pc_isdotdot( filename, fileext ))
{
/* Find pobj's parent. By looking back from ".." */
pmom = pc_get_mom(pchild);
PC_INODE_EXIT(pobj->finode)
/* We're done with pobj for now */
pc_freeobj(pobj);
if (!pmom)
{
pc_freeobj(pchild);
return (NULL);
}
else
{
/* We found the parent now free the child */
pobj = pmom;
pc_freeobj(pchild);
}
}
else
{
PC_INODE_EXIT(pobj->finode)
/* We're done with pobj for now */
pc_freeobj(pobj);
/* Make sure pobj points at the next inode */
pobj = pchild;
}
}
}
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.
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, UTEXT *filename, UTEXT *fileext) /*__fn__*/
{
BOOL starting = NO;
/* Create the child if just starting */
if (!pobj)
{
starting = YES;
pobj = pc_mkchild(pmom);
if (!pobj)
return(NULL);
}
else /* If doing a gnext don't get stuck in and endless loop */
{
if ( ++(pobj->blkinfo.my_index) >= INOPBLOCK )
{
if (!pc_next_block(pobj))
{
return (NULL);
}
else
pobj->blkinfo.my_index = 0;
}
}
if (pc_findin(pobj, filename, fileext))
{
return (pobj);
}
else
{
if (starting)
pc_freeobj(pobj);
return (NULL);
}
}
/***************************************************************************
PC_FINDIN - Find a filename in the same directory as the argument.
Description
Look for the next match of filename or pattern filename:ext in the
subdirectory containing pobj. If found update pobj to contain the
new information (essentially getnext.) Called by pc_get_inode().
Note: Filename and ext must be right filled with spaces to 8 and 3 bytes
respectively. Null termination does not matter.
Returns
Returns YES if found or NO.
****************************************************************************/
/* Find filename in the directory containing pobj. If found, load the inode
section of pobj. If the inode is already in the inode buffers we free the current inode
and stitch the existing one in, bumping its open count */
BOOL pc_findin( DROBJ *pobj, UTEXT *filename, UTEXT *fileext) /*__fn__*/
{
BLKBUFF *rbuf;
DIRBLK *pd;
DOSINODE *pi;
FINODE *pfi;
/* For convenience. We want to get at block info here */
pd = &pobj->blkinfo;
/* Read the data */
rbuf = pc_read_obj(pobj);
while (rbuf)
{
pi = (DOSINODE *) &rbuf->data[0];
/* Look at the current inode */
pi += pd->my_index;
/* And look for a match */
while ( pd->my_index < INOPBLOCK )
{
/* End of dir if name is 0 */
if (!pi->fname[0])
{
pc_free_buf(rbuf,NO);
return(NO);
}
/* Note: Patcmp won't match on deleted */
if (pc_patcmp(pi->fname, (UTEXT*) filename, 8) && (pc_patcmp(pi->fext, (UTEXT*) fileext, 3) ))
{
/* We found it */
/* See if it already exists in the inode list.
If so.. we use the copy from the inode list */
pfi = pc_scani(pobj->pdrive, rbuf->blockno, pd->my_index);
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 */
{
pfi = pc_alloci();
if (pfi)
{
pc_freei(pobj->finode); /* Release the current */
pobj->finode = pfi;
pc_dos2inode(pobj->finode , pi );
pc_marki(pobj->finode , pobj->pdrive , pd->my_block,
pd->my_index );
}
else
{
pc_free_buf(rbuf,NO);
return (NO);
}
}
/* Free, no error */
pc_free_buf(rbuf,NO);
return (YES);
} /* if (match) */
pd->my_index++;
pi++;
}
/* Not in that block. Try again */
pc_free_buf(rbuf,NO);
/* Update the objects block pointer */
if (!pc_next_block(pobj))
break;
pd->my_index = 0;
rbuf = pc_read_obj(pobj);
}
return (NO);
}
/**************************************************************************
PC_GET_MOM - Find the parent inode of a subdirectory.
Description
Given a DROBJ initialized with the contents of a subdirectory's ".."
entry, initialize a DROBJ which is the parent of the current directory.
Returns
Returns a DROBJ pointer or NULL if could something went wrong.
****************************************************************************/
/*
* 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;
/* We have to be a subdir */
if (!pc_isadir(pdotdot))
return(NULL);
/* If ..->cluster is zero then parent is root */
if (!pdotdot->finode->fcluster)
return(pc_get_root(pdrive));
/* Otherwise : cluster points to the beginning of our parent.
we also need the position of our parent in it's parent */
pmom = pc_allocobj();
if (!pmom)
return (NULL);
pmom->pdrive = pdrive;
/* Find .. in our parent's directory */
sectorno = pc_cl2sector(pdrive,pdotdot->finode->fcluster);
/* 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 = NO;
pd = &pmom->blkinfo;
rbuf = pc_read_obj(pmom);
if (rbuf)
{
pi = (DOSINODE *) &rbuf->data[0];
pc_dos2inode(pmom->finode , pi );
pc_free_buf(rbuf,NO);
/* See if the inode is in the buffers */
pfi = pc_scani(pdrive, sectorno, 0);
if (pfi)
{
pc_freei(pmom->finode);
pmom->finode = pfi;
return (pmom);
}
else
{
pc_marki(pmom->finode , pmom->pdrive , pd->my_block,
pd->my_index);
return (pmom);
}
}
else /* Error, something didn't work */
{
pc_freeobj(pmom);
return (NULL);
}
}
/**************************************************************************
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))
return(NULL);
/* init the object - */
pobj = pc_allocobj();
if (!pobj)
return (NULL);
pd = &pobj->blkinfo;
pobj->isroot = NO; /* 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 (NULL);
}
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 */
DROBJ *pc_mknode(DROBJ *pmom ,TEXT *filename, TEXT *fileext, UTINY attributes) /*__fn__*/
{
DROBJ *pobj;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -