📄 drobj.c
字号:
BOOL ret_val;
DOSINODE *pdinodes;
FINODE lfinode;
UCOUNT cluster;
DATESTR crdate;
BLKBUFF *pbuff;
DDRIVE *pdrive;
UTINY attr;
pobj = NULL;
ret_val = YES;
if (!pmom)
return (NULL);
pdrive = pmom->pdrive;
if (!pdrive)
ret_val = NO;
else if (attributes & ADIRENT)
{
/* Grab a new cluster and clear it. We optimize here (10/27/90).
To minimize fragmentation we give clalloc a hint where to
start looking for new clusters */
UCOUNT clbase = 0;
if (!pc_isroot(pmom))
clbase = pmom->finode->fcluster;
/*Grab a cluster for a new dir and cleaer it */
PC_FAT_ENTER(pdrive->driveno)
cluster = pc_clalloc(pdrive, clbase);
PC_FAT_EXIT(pdrive->driveno)
if (!cluster)
ret_val = NO;
else if (!pc_clzero( pdrive , cluster ) )
{
PC_FAT_ENTER(pdrive->driveno)
pc_clrelease(pdrive , cluster);
PC_FAT_EXIT(pdrive->driveno)
ret_val = NO;
}
}
else
cluster = 0;
if (!ret_val)
{
return (NULL);
}
/* For a subdirectory. First make it a simple file. We will change the
attribute after all is clean */
attr = attributes;
if (attr & ADIRENT)
attr = ANORMAL;
/* Allocate an empty DROBJ and FINODE to hold the new file */
pobj = pc_allocobj();
if (!pobj)
{
return (NULL);
}
/* Load the inode copy name,ext,attr,cluster, size,datetime*/
pc_init_inode( pobj->finode, filename, fileext,
attr, cluster, /*size*/ 0L ,pc_getsysdate(&crdate) );
/* Convert pobj to native and stitch it in to mom */
if (!pc_insert_inode(pobj , pmom))
{
PC_FAT_ENTER(pdrive->driveno)
pc_clrelease(pdrive , cluster);
PC_FAT_EXIT(pdrive->driveno)
pc_freeobj(pobj);
return (NULL);
}
/* 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)
{
/* Set up a buffer to do surgery */
pbuff = pc_init_blk( pdrive , pc_cl2sector(pdrive , cluster));
if (!pbuff)
{
pc_freeobj(pobj);
PC_FAT_ENTER(pdrive->driveno) /* claim the fat for alloc */
pc_clrelease(pdrive , cluster);
PC_FAT_EXIT(pdrive->driveno)
return (NULL);
}
pdinodes = (DOSINODE *) &pbuff->data[0];
/* Load DOT and DOTDOT in native form */
/* DOT first. It points to the begining of this sector */
pc_init_inode( &lfinode, ".", "", ADIRENT|ARCHIVE,
cluster, /*size*/ 0L ,&crdate);
/* And to the buffer in intel form */
pc_ino2dos (pdinodes, &lfinode);
/* Now DOTDOT points to mom's cluster */
pc_init_inode( &lfinode, "..", "", ADIRENT|ARCHIVE,
pc_sec2cluster( pdrive , pobj->blkinfo.my_frstblock),
/*size*/ 0L ,&crdate);
/* And to the buffer in intel form */
pc_ino2dos ( ++pdinodes, &lfinode );
/* Write the cluster out */
if ( !pc_write_blk ( pbuff ) )
{
pc_free_buf(pbuff,YES); /* Error. Chuck the buffer */
pc_freeobj(pobj);
PC_FAT_ENTER(pdrive->driveno) /* claim the fat for alloc */
pc_clrelease(pdrive , cluster);
PC_FAT_EXIT(pdrive->driveno)
return (NULL);
}
else
pc_free_buf(pbuff,NO);
/* And write the node out with the original attributes */
pobj->finode->fattribute = attributes;
pobj->finode->fattribute |= ARCHIVE;
/* Convert to native and overwrite the existing inode*/
if (!pc_update_inode(pobj))
{
pc_freeobj(pobj);
PC_FAT_ENTER(pdrive->driveno) /* claim the fat for alloc */
pc_clrelease(pdrive , cluster);
PC_FAT_EXIT(pdrive->driveno)
return (NULL);
}
}
PC_FAT_ENTER(pdrive->driveno)
ret_val = pc_flushfat(pdrive->driveno);
PC_FAT_EXIT(pdrive->driveno)
if (ret_val)
{
return (pobj);
}
else
{
pc_freeobj(pobj);
return (NULL);
}
}
/***************************************************************************
PC_INSERT_INODE - Insert a new inode into an existing directory inode.
Description
Take mom , a fully defined DROBJ, and pobj, a DROBJ with a finode
containing name, ext, etc, but not yet stitched into the inode buffer
pool, and fill in pobj and its inode, write it to disk and make the inode
visible in the inode buffer pool. (see also pc_mknode() )
Returns
Returns YES if all went well, NO on a write error, disk full error or
root directory full.
**************************************************************************/
BOOL pc_insert_inode( DROBJ *pobj, DROBJ *pmom) /*__fn__*/
{
BLKBUFF *pbuff;
DIRBLK *pd;
DOSINODE *pi;
COUNT i;
BOOL retval;
UCOUNT cluster;
/* Set up pobj */
pobj->pdrive = pmom->pdrive;
pobj->isroot = NO;
pd = &pobj->blkinfo;
/* Now get the start of the dir */
pd->my_block = pd->my_frstblock = pc_firstblock(pmom);
if (!pd->my_block)
{
return (NO);
}
else
pd->my_index = 0;
/* Read the data */
pbuff = pc_read_obj(pobj);
while (pbuff)
{
i = pd->my_index = 0;
pi = (DOSINODE *) &pbuff->data[0];
/* look for a slot */
while ( i < INOPBLOCK )
{
/* End of dir if name is 0 */
if ( (pi->fname[0] == '\0') || (pi->fname[0] == PCDELETE) )
{
pd->my_index = i;
/* Update the DOS disk */
pc_ino2dos( pi, pobj->finode );
/* Write the data */
retval = pc_write_obj( pobj );
/* Mark the inode in the inode buffer */
if (retval)
pc_marki(pobj->finode , pobj->pdrive , pd->my_block,
pd->my_index );
pc_free_buf(pbuff, !retval);
return (retval);
}
i++;
pi++;
}
/* Not in that block. Try again */
pc_free_buf(pbuff,NO);
/* Update the objects block pointer */
if (!pc_next_block(pobj))
break;
pbuff = pc_read_obj(pobj);
}
/* Hmmm - root full ??. This is a problem */
if (pc_isroot(pmom))
return (NO);
/* Ok:There ar no slots in mom. We have to make one. And copy our stuf in*/
PC_FAT_ENTER(pobj->pdrive->driveno) /* claim the fat for alloc */
cluster = pc_clgrow(pobj->pdrive , pmom->finode->fcluster);
PC_FAT_EXIT(pobj->pdrive->driveno)
if (!cluster)
return (NO);
/* Zero out the cluster */
if (!pc_clzero( pobj->pdrive , cluster ) )
{
PC_FAT_ENTER(pobj->pdrive->driveno) /* claim the fat for alloc */
pc_clrelease(pobj->pdrive , cluster);
PC_FAT_EXIT(pobj->pdrive->driveno)
return (NO);
}
/* Don't forget where the new item is */
pd->my_block = pc_cl2sector(pobj->pdrive , cluster);
pd->my_index = 0;
/* Copy the item into the first block */
pbuff = pc_init_blk( pobj->pdrive , pd->my_block);
if (!pbuff)
{
PC_FAT_ENTER(pobj->pdrive->driveno) /* claim the fat for alloc */
pc_clrelease(pobj->pdrive , cluster);
PC_FAT_EXIT(pobj->pdrive->driveno)
return (NO);
}
pc_ino2dos ( (DOSINODE *) &pbuff->data[0] , pobj->finode ) ;
/* Write it out */
if ( !pc_write_blk ( pbuff ) )
{
pc_free_buf(pbuff,YES);
PC_FAT_ENTER(pobj->pdrive->driveno) /* claim the fat for alloc */
pc_clrelease(pobj->pdrive , cluster);
PC_FAT_EXIT(pobj->pdrive->driveno)
return (NO);
}
/* 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,NO);
return (YES);
}
/***************************************************************************
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 YES if it successfully deleted the inode an flushed the fat.
*****************************************************************************/
/* Delete a file / dir or volume. Don't check for write access et al */
BOOL pc_rmnode( DROBJ *pobj) /*__fn__*/
{
UCOUNT cluster;
BOOL ret_val;
/* Don't delete anything that has multiple links */
if (pobj->finode->opencount > 1)
{
pc_report_error(PCERR_REMINODE);
return (NO);
}
/* Mark it deleted and unlink the cluster chain */
pobj->finode->fname[0] = PCDELETE;
cluster = pobj->finode->fcluster;
/* We free up store right away. Don't leave cluster pointer
hanging around to cause problems. */
pobj->finode->fcluster = 0;
if (pc_update_inode(pobj))
{
/* And clear up the space */
PC_FAT_ENTER(pobj->pdrive->driveno)
pc_freechain(pobj->pdrive, cluster);
ret_val = pc_flushfat(pobj->pdrive->driveno);
PC_FAT_EXIT(pobj->pdrive->driveno)
return (ret_val);
}
/* If it gets here we had a probblem */
return(NO);
}
/**************************************************************************
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 YES 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 */
BOOL pc_update_inode( DROBJ *pobj) /*__fn__*/
{
BLKBUFF *pbuff;
DOSINODE *pi;
COUNT i;
BOOL retval;
DIRBLK *pd;
DATESTR crdate;
pd = &pobj->blkinfo;
i = pd->my_index;
if ( i >= INOPBLOCK || i < 0 ) /* Index into block */
return (NO);
/* Set the archive bit and the date */
pobj->finode->fattribute |= ARCHIVE;
pc_getsysdate(&crdate);
pobj->finode->ftime = crdate.time;
pobj->finode->fdate = crdate.date;
/* Read the data */
pbuff = pc_read_obj(pobj);
if (pbuff)
{
pi = (DOSINODE *) &pbuff->data[0];
/* Copy it off and write it */
pc_ino2dos( (pi+i), pobj->finode );
retval = pc_write_obj( pobj );
/* Free the buff. If retval == NO(fail), pass a yes to
freebuf so it will discard the buffer. */
pc_free_buf(pbuff, !retval);
return (retval);
}
return (NO);
}
/***************************************************************************
PC_READ_OBJ - Assign an initialized BLKBUFF to a DROBJ
Description
Use the pdrive and myblock fields of pobj to determine what block to
read. Add block to the buffer pool, if needed, point pobj at the
buffer and return the buffer.
Note: After reading, you "own" the buffer. You must release it by
calling pc_free_buff() before others can use it.
Returns
Returns a valid pointer or NULL if block not found and not readable.
****************************************************************************/
BLKBUFF *pc_read_obj(DROBJ *pobj) /*__fn__*/
{
if (!pobj)
return (NULL);
pobj->pblkbuff = pc_read_blk(pobj->pdrive, pobj->blkinfo.my_block);
return(pobj->pblkbuff);
}
/***************************************************************************
PC_WRITE_OBJ - Write a DROBJ's BLKBUFF to disk
Description
Write the data in the BLKBUFF for pobj to disk.
Returns
Returns YES if the write succeeded.
*****************************************************************************/
BOOL pc_write_obj(DROBJ *pobj) /*__fn__*/
{
if (!pobj)
return (NO);
return (pc_write_blk(pobj->pblkbuff));
}
/*************************************************************************
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 (NULL);
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 = YES;
return (pobj);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -