📄 drobj.c
字号:
{
pi = (DOSINODE *) &rbuf->data[0];
OS_CLAIM_FSCRITICAL()
pc_dos2inode(pmom->finode , pi );
OS_RELEASE_FSCRITICAL()
pc_free_buf(rbuf,FALSE);
/* 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 didn't 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))
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);
}
#if (RTFS_WRITE)
/**************************************************************************
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 ,char *filename, char *fileext, byte attributes) /*__fn__*/
{
DROBJ *pobj;
BOOLEAN ret_val;
DOSINODE *pdinodes;
FINODE lfinode;
CLUSTERTYPE cluster;
CLUSTERTYPE cltemp;
DATESTR crdate;
BLKBUFF *pbuff;
DDRIVE *pdrive;
byte attr;
#if (VFAT)
char vffilename[9],vffileext[4];
#endif
ret_val = TRUE;
if (!pmom)
return (0);
pdrive = pmom->pdrive;
cluster = 0;
if (!pdrive)
ret_val = FALSE;
#if (RTFS_SUBDIRS)
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 */
CLUSTERTYPE clbase = 0;
if (!pmom->isroot)
clbase = pc_finode_cluster(pmom->pdrive,pmom->finode); /* FAT32 */
/*Grab a cluster for a new dir and cleaer it */
cluster = pc_clalloc(pdrive, clbase);
if (!cluster)
ret_val = FALSE;
else if (!pc_clzero( pdrive , cluster ) )
{
pc_clrelease(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);
}
/* Load the inode copy name,ext,attr,cluster, size,datetime */
#if (VFAT)
pc_malias(vffilename,vffileext, (byte *)filename,pmom);
pc_init_inode( pobj->finode, vffilename, vffileext,
attr, cluster, /*size*/ 0L ,pc_getsysdate(&crdate) );
#else
pc_init_inode( pobj->finode, filename, fileext,
attr, cluster, /*size*/ 0L ,pc_getsysdate(&crdate) );
#endif
/* Convert pobj to native and stitch it in to mom */
#if (VFAT)
ARGSUSED_PVOID((PFVOID) fileext);
if (!pc_insert_inode(pobj , pmom, filename))
#else
if (!pc_insert_inode(pobj , pmom))
#endif
{
pc_clrelease(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)
{
/* Set up a buffer to do surgery */
pbuff = pc_init_blk( pdrive , pc_cl2sector(pdrive , cluster));
if (!pbuff)
{
pc_freeobj(pobj);
pc_clrelease(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 */
pc_init_inode( &lfinode, string_dot,string_null, ADIRENT|ARCHIVE,
cluster, /*size*/ 0L ,&crdate);
/* And to the buffer in intel form */
pc_ino2dos (pdinodes, &lfinode);
/* Now DOTDOT points to mom's cluster */
#if (FAT32)
if ((pdrive->fasize == 8) &&
(pobj->blkinfo.my_frstblock == pdrive->rootblock))
cltemp = 0;
else
#endif
cltemp = pc_sec2cluster(pdrive,pobj->blkinfo.my_frstblock);
pc_init_inode( &lfinode, string_dot_dot, string_null, 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_free_buf(pbuff,TRUE); /* Error. Chuck the buffer */
pc_freeobj(pobj);
pc_clrelease(pdrive , cluster);
return (0);
}
else
pc_free_buf(pbuff,FALSE);
/* 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);
pc_clrelease(pdrive , cluster);
return (0);
}
}
#endif
ret_val = pc_flushfat(pdrive->driveno);
if (ret_val)
{
return (pobj);
}
else
{
pc_freeobj(pobj);
return (0);
}
}
#endif
#if (RTFS_WRITE)
/***************************************************************************
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 TRUE if all went well, FALSE on a write error, disk full error or
root directory full.
**************************************************************************/
/* Note: the parent directory is locked before this routine is called */
#if (VFAT)
BOOLEAN pc_insert_inode( DROBJ *pobj, DROBJ *pmom, char *lfn) /*__fn__*/
#else
BOOLEAN pc_insert_inode( DROBJ *pobj, DROBJ *pmom) /*__fn__*/
#endif
{
BLKBUFF *pbuff;
DIRBLK *pd;
DOSINODE *pi;
int i;
BOOLEAN retval;
CLUSTERTYPE cluster;
#if (VFAT)
byte cksum;
BOOLEAN end_of_dir;
int n_segs;
/* How many segments do we need */
//DM: 3/14/99: This has been changed back and forth several times.
// The correct statement does NOT have the +1. The correct formula
// is (length+12)/13. The +1 was in anticipation of the NUL character
// terminator, but that is only used when the filename is not an
// even multiple of 13. Examples:
// 1-char name: (1+12)/13 == 1
// 13-char name: (13+12)/13 == 1 not 2
//
// If there are still problems with LFN's, the problem is elsewhere --
// do not change this again!
//
n_segs = (tc_strlen(lfn) + 12 )/13;
// n_segs = ((tc_strlen(lfn) + 1) + 12 )/13; WRONG -- delete +1
#endif
/* Set up pobj */
pobj->pdrive = pmom->pdrive;
pobj->isroot = FALSE;
pd = &pobj->blkinfo;
/* Now get the start of the dir */
pd->my_block = pd->my_frstblock = pc_firstblock(pmom);
if (!pd->my_block)
{
return (FALSE);
}
else
pd->my_index = 0;
/* Read the data */
pobj->pblkbuff = pbuff = pc_read_blk(pobj->pdrive, pobj->blkinfo.my_block);
if (!pbuff)
return(FALSE);
#if (VFAT)
cksum = pc_cksum((byte*)pobj->finode);
end_of_dir = FALSE;
pc_zeroseglist(&pobj->finode->s);
pobj->finode->s.ncksum = cksum;
#endif /* VFAT */
while (pbuff)
{
i = pd->my_index = 0;
pi = (DOSINODE *) &pbuff->data[0];
/* look for a slot */
while ( i < INOPBLOCK )
{
#if (VFAT)
if (pi->fname[0] == '\0')
end_of_dir = TRUE;
if (pi->fname[0] == PCDELETE || end_of_dir)
{
/* Note that we fake an allocation of n_segs + 1 segments.
this scheme makes sure that there is room for the DOSINODE
immediately after the segment list. We reduce the segment
count before we write the segments */
if (pobj->finode->s.nsegs != (n_segs +1))
{
pc_addtoseglist(&pobj->finode->s, pd->my_block, i);
}
/* Write the lfn and dos inode if we have the space */
if (pobj->finode->s.nsegs == (n_segs +1))
{
/* Write the long file name entries to their respective
locations */
/* Drop the segment count by one before we write.
with this scheme we fall out of the loop and
put the DOSINODE in the correct location */
pc_reduceseglist(&pobj->finode->s);
if (!pc_seglist2disk(pobj->pdrive, &pobj->finode->s, lfn))
{
pc_free_buf(pbuff, TRUE);
goto clean_and_fail;
}
pd->my_index = i;
/* Update the DOS disk */
pc_ino2dos( pi, pobj->finode );
/* Write the data */
retval = pc_write_blk(pobj->pblkbuff);
/* 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, (BOOLEAN)!retval);
return (retval);
}
}
else
{
pc_zeroseglist(&pobj->finode->s);
}
#else /* IF NOT VFAT */
/* End of dir if name is 0 */
if ( (pi->fname[0] == '\0') || (pi->fname[0] == PCDELETE) )
{
pd->my_index = (word)i;
/* Update the DOS disk */
pc_ino2dos( pi, pobj->finode );
/* Write the data */
retval = pc_write_blk(pobj->pblkbuff);
/* 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, (BOOLEAN)(!retval));
return (retval);
}
#endif /* VFAT */
i++;
pi++;
}
/* Not in that block. Try again */
pc_free_buf(pbuff,FALSE);
/* Update the objects block pointer */
if (!pc_next_block(pobj))
#if (VFAT)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -