📄 drobj.c
字号:
/****************************************************************************
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__*/
{
if (!pc_isadir(pobj))
return (BLOCKEQ0);
/* Root dir ? */
if (pobj->isroot)
return (pobj->blkinfo.my_frstblock);
else
return (pc_cl2sector(pobj->pdrive , pobj->finode->fcluster) );
}
/***************************************************************************
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 YES or NO on end of chain.
*****************************************************************************/
/* Calculate the next block in an object */
BOOL 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 (YES);
}
else
return (NO);
}
/**************************************************************************
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__*/
{
UCOUNT cluster;
/* If the block is in the root area */
if (curblock < pdrive->firstclblock)
{
if (curblock < pdrive->rootblock)
return (BLOCKEQ0);
else if (++curblock < pdrive->firstclblock)
return (curblock);
else
return (BLOCKEQ0);
}
/* In cluster space */
else
{
if (curblock >= pdrive->numsecs)
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 - No error test needed */
cluster = pc_sec2cluster(pdrive,curblock);
/* Consult the fat for the next cluster */
PC_FAT_ENTER(pdrive->driveno) /* claim the fat for alloc */
cluster = pc_clnext(pdrive, cluster);
PC_FAT_EXIT(pdrive->driveno)
if (!cluster)
return (BLOCKEQ0); /* End of chain */
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, COUNT index)/*__fn__*/
{
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 (inoroot)
inoroot->pprev = pfi;
pfi->pprev = NULL;
pfi->pnext = inoroot;
inoroot = pfi;
}
/**************************************************************************
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, COUNT index) /*__fn__*/
{
FINODE *pfi;
pfi = inoroot;
while (pfi)
{
if ( (pfi->my_drive == pdrive) &&
(pfi->my_block == sectorno) &&
(pfi->my_index == index) )
{
pfi->opencount += 1;
return (pfi);
}
pfi = pfi->pnext;
}
return (NULL);
}
/**************************************************************************
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() /*__fn__*/
{
DROBJ *pobj;
/* Alloc a DROBJ */
pobj = pc_memory_drobj(NULL);
if (!pobj)
return (NULL);
else
{
pobj->finode = pc_alloci();
if (!pobj->finode)
{
/* Free the DROBJ */
pc_memory_drobj(pobj);
return(NULL);
}
else
{
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() /*__fn__*/
{
return(pc_memory_finode(NULL));
}
/**************************************************************************
PC_FREE_ALL_I - Release all inode buffers associated with a drive.
Description
Called by pc_dskclose().
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;
pfi = inoroot;
while (pfi)
{
if (pfi->my_drive == pdrive)
{
/* Set the opencount to 1 so freei releases the inode */
pfi->opencount = 1;
pc_report_error(PCERR_FREEINODE);
pc_freei(pfi);
/* Since we changed the list go back to the top */
pfi = inoroot;
}
else
pfi = pfi->pnext;
}
}
/*****************************************************************************
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)
{
pc_report_error(PCERR_FREEINODE);
return;
}
if (pfi->opencount)
{
if (--pfi->opencount)/* Decrement opencount and return if non zero */
return;
else
{
if (pfi->pprev) /* Pont the guy behind us at the guy in front*/
{
pfi->pprev->pnext = pfi->pnext;
}
else
{
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;
}
}
}
/* 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);
}
else
pc_report_error(PCERR_FREEDROBJ);
}
/***************************************************************************
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);
copybuff(&pdir->fext[0],&pbuff->fext[0],3);
pdir->fattribute = pbuff->fattribute;
copybuff(&pdir->resarea[0],&pbuff->resarea[0], 10);
pdir->ftime = to_WORD((UTINY *) &pbuff->ftime);
pdir->fdate = to_WORD((UTINY *) &pbuff->fdate);
pdir->fcluster = to_WORD((UTINY *) &pbuff->fcluster);
pdir->fsize = to_DWORD((UTINY *) &pbuff->fsize);
}
/**************************************************************************
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
****************************************************************************/
/* Load an in memory inode up with user supplied values*/
VOID pc_init_inode(FINODE *pdir, TEXT *filename, TEXT *fileext, UTINY attr, UCOUNT cluster, ULONG size, DATESTR *crdate) /*__fn__*/
{
/* Copy the file names and pad with ' ''s */
pc_cppad(pdir->fname,(UTEXT*)filename,8);
pc_cppad(pdir->fext,(UTEXT*)fileext,3);
pdir->fattribute = attr;
pc_memfill(&pdir->resarea[0],10, '\0');
pdir->ftime = crdate->time;
pdir->fdate = crdate->date;
pdir->fcluster = cluster;
pdir->fsize = size;
}
/***************************************************************************
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__*/
{
copybuff(&pbuff->fname[0],&pdir->fname[0],8);
if (pbuff->fname[0] == (UTINY) 0xE5)
pbuff->fname[0] = PCDELETE;
copybuff(&pbuff->fext[0],&pdir->fext[0],3);
pbuff->fattribute = pdir->fattribute;
copybuff(&pbuff->resarea[0],&pdir->resarea[0], 10);
fr_WORD((UTINY *) &pbuff->ftime,pdir->ftime);
fr_WORD((UTINY *) &pbuff->fdate,pdir->fdate);
fr_WORD((UTINY *) &pbuff->fcluster,pdir->fcluster);
fr_DWORD((UTINY *) &pbuff->fsize,pdir->fsize);
}
/**************************************************************************
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 NO if the obj does not point to a directory.
****************************************************************************/
BOOL pc_isavol( DROBJ *pobj) /*__fn__*/
{
return(pobj->finode->fattribute & AVOLUME);
}
/**************************************************************************
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 NO if the obj does not point to a directory.
****************************************************************************/
BOOL pc_isadir( DROBJ *pobj) /*__fn__*/
{
return ( (pobj->isroot) || (pobj->finode->fattribute & ADIRENT) );
}
/**************************************************************************
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 */
BOOL pc_isroot( DROBJ *pobj) /*__fn__*/
{
return(pobj->isroot);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -