📄 drobj.c
字号:
#if (FAT32)
if (pmom->pdrive->fasize != 8)
#endif
if (pc_isroot(pmom))
return (FALSE);
#if RTFS_SUBDIRS
/* Ok:There ar no slots in mom. We have to make one. And copy our stuf in */
#if (FAT32)
if (pobj->pdrive->fasize == 8)
{
dword tmpcl = pc_finode_cluster(pobj->pdrive,pmom->finode);
if (tmpcl == 0)
tmpcl = pc_sec2cluster(pobj->pdrive, pmom->pdrive->rootblock);
cluster = pc_clgrow(pobj->pdrive , tmpcl);
}
else
#endif
cluster = pc_clgrow(pobj->pdrive, pc_finode_cluster(pobj->pdrive,pmom->finode)); /* FAT32 */
if (!cluster)
return (FALSE);
/* Don't forget where the new item is */
pd->my_block = pc_cl2sector(pobj->pdrive , cluster);
pd->my_index = 0;
/* Zero out the cluster */
if (!pc_clzero( pobj->pdrive , cluster ) )
goto clean_and_fail;
/* Copy the item into the first block */
pobj->pblkbuff = pbuff = pc_init_blk( pobj->pdrive , pd->my_block);
if (!pbuff)
goto clean_and_fail;
#endif /* Subdir */
}
else
#else /* IF NOT VFAT */
break;
#endif /* VFAT */
pobj->pblkbuff = pbuff = pc_read_blk(pobj->pdrive, pobj->blkinfo.my_block);
}
#if (!VFAT)
/* Hmmm - root full ??. This is a problem */
#if (FAT32)
if (pmom->pdrive->fasize != 8)
#endif
if (pc_isroot(pmom))
return (FALSE);
#if RTFS_SUBDIRS
/* Ok:There ar no slots in mom. We have to make one. And copy our stuf in */
#if (FAT32)
if (pobj->pdrive->fasize == 8)
{
dword tmpcl = pc_finode_cluster(pobj->pdrive,pmom->finode);
if (tmpcl == 0)
tmpcl = pc_sec2cluster(pobj->pdrive, pmom->pdrive->rootblock);
cluster = pc_clgrow(pobj->pdrive , tmpcl);
}
else
#endif
cluster = pc_clgrow(pobj->pdrive, pc_finode_cluster(pobj->pdrive,pmom->finode)); /*FAT32 */
if (!cluster)
return (FALSE);
/* Don't forget where the new item is */
pd->my_block = pc_cl2sector(pobj->pdrive , cluster);
pd->my_index = 0;
/* Zero out the cluster */
if (!pc_clzero( pobj->pdrive , cluster ) )
goto clean_and_fail;
/* Copy the item into the first block */
pbuff = pc_init_blk( pobj->pdrive , pd->my_block);
if (!pbuff)
goto clean_and_fail;
pc_ino2dos ( (DOSINODE *) &pbuff->data[0] , pobj->finode ) ;
/* Write it out */
if ( !pc_write_blk ( pbuff ) )
{
pc_free_buf(pbuff,TRUE);
goto clean_and_fail;
}
/* We made a new slot. Mark the inode as belonging there */
pc_marki(pobj->finode , pobj->pdrive , pd->my_block, pd->my_index );
pc_free_buf(pbuff,FALSE);
return (TRUE);
#endif /* Subdir */
#endif /* VFAT */
clean_and_fail:
#if RTFS_SUBDIRS
#if (FAT32)
if (pobj->pdrive->fasize == 8)
{
dword tmpcl = pc_finode_cluster(pobj->pdrive,pmom->finode);
if (tmpcl == 0)
tmpcl = pc_sec2cluster(pmom->pdrive, pmom->pdrive->rootblock);
pc_cl_truncate(pobj->pdrive, tmpcl, cluster);
}
else
#endif /* FAT32 */
pc_cl_truncate(pobj->pdrive, pc_finode_cluster(pobj->pdrive,pmom->finode), cluster); /* FAT32 */
#endif /* Subdir */
return (FALSE);
}
#endif
#if (RTFS_WRITE)
/***************************************************************************
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 won't work)
Returns
Returns TRUE if it successfully deleted the inode an flushed the fat.
*****************************************************************************/
/* Delete a file / dir or volume. Don't 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;
BOOLEAN ret_val;
/* Don't delete anything that has multiple links */
if (pobj->finode->opencount > 1)
{
#if (VFAT)
err_ex:
#endif
pc_report_error(PCERR_REMINODE);
return (FALSE);
}
/* Mark it deleted and unlink the cluster chain */
pobj->finode->fname[0] = PCDELETE;
#if (VFAT)
if (!pc_deleteseglist(pobj->pdrive, &pobj->finode->s))
goto err_ex;
#endif
cluster = pc_finode_cluster(pobj->pdrive,pobj->finode); /* FAT32 */
/* We free up store right away. Don't leave cluster pointer
hanging around to cause problems. */
pc_pfinode_cluster(pobj->pdrive,pobj->finode,0); /* FAT32 */
/* Convert to native. Overwrite the existing inode.Set archive/date */
if (pc_update_inode(pobj, TRUE, TRUE))
{
/* And clear up the space */
pc_freechain(pobj->pdrive, cluster);
ret_val = pc_flushfat(pobj->pdrive->driveno);
return (ret_val);
}
/* If it gets here we had a probblem */
return(FALSE);
}
#endif
#if (RTFS_WRITE)
/**************************************************************************
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;
BOOLEAN retval;
DIRBLK *pd;
DATESTR crdate;
pd = &pobj->blkinfo;
i = pd->my_index;
if ( i >= INOPBLOCK || i < 0 ) /* Index into block */
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 );
retval = pc_write_blk(pobj->pblkbuff);
/* Free the buff. If retval == FALSE(fail), pass a TRUE to
freebuf so it will discard the buffer. */
pc_free_buf(pbuff, (BOOLEAN)!retval);
return (retval);
}
return (FALSE);
}
#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);
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__*/
{
if (!pc_isadir(pobj))
return (BLOCKEQ0);
/* Root dir ? */
#if (RTFS_SUBDIRS)
if (!pobj->isroot)
return (pc_cl2sector(pobj->pdrive , pc_finode_cluster(pobj->pdrive, pobj->finode)) );
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__*/
{
#if (RTFS_SUBDIRS || FAT32) /* DM: 7-6-99: added conditional */
CLUSTERTYPE cluster;
#endif
/* 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);
}
#if (RTFS_SUBDIRS || FAT32) /* DM: 7-6-99: FIX -- added || FAT32 */
/* 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 */
cluster = pc_clnext(pdrive, cluster);
if (!cluster)
return (BLOCKEQ0); /* End of chain */
else
return (pc_cl2sector(pdrive, cluster));
}
}
#else
return (BLOCKEQ0);
#endif
}
/**************************************************************************
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -