📄 drobj.c
字号:
/* 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.
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.
pc_firstblock - Return the absolute block number of a directory
pc_next_block - Calculate the next block owned by an object.
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.
pc_marki - Set dr:sec:index, + stitch FINODE into the inode list
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 -
*/
#include <pcdisk.h>
/**************************************************************************
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 0.
***************************************************************************/
/* Find "path" and create a DROBJ structure if found */
DROBJ *pc_fndnode(char *path) /*__fn__*/
{
DROBJ *pobj;
DROBJ *pmom;
DROBJ *pchild;
int driveno;
DDRIVE *pdrive;
byte filename[FILENAMESIZE];
byte fileext[4];
/* Get past D: plust get drive number if there */
path = pc_parsedrive( &driveno, path );
if (!path)
return (0);
/* Find the drive */
pdrive = pc_drno2dr(driveno);
if (!pdrive)
return (0);
/* Get the top of the current path */
if ( *path == char_backslash )
{
pobj = pc_get_root(pdrive);
path++;
}
else
{
pobj = pc_get_cwd(pdrive);
}
if (!pobj)
return (0);
/* Search through the path til exausted */
while (*path)
{
path = pc_nibbleparse((char*) filename,(char*) fileext, path );
if (!path)
{
pc_freeobj(pobj);
return (0);
}
#if (RTFS_SUBDIRS)
if (pc_isdot( filename, fileext ))
;
#endif
else
{
/* Find Filename in pobj. and initialize lpobj with result */
pchild = pc_get_inode(0, pobj, filename, fileext, FALSE);
if (!pchild)
{
pc_freeobj(pobj);
return (0);
}
#if (RTFS_SUBDIRS)
/* 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);
/* We're done with pobj for now */
pc_freeobj(pobj);
if (!pmom)
{
pc_freeobj(pchild);
return (0);
}
else
{
/* We found the parent now free the child */
pobj = pmom;
pc_freeobj(pchild);
}
}
else
#endif /* SUBDIRS */
{
/* We're done with pobj for now */
pc_freeobj(pobj);
/* Make sure pobj points at the next inode */
pobj = pchild;
#if (RTFS_SUBDIRS)
#else
/* No subdirectory support. Return the one we found */
return (pobj);
#endif
}
}
}
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, byte *filename, byte *fileext, BOOLEAN dowildcard) /*__fn__*/
{
BOOLEAN starting = FALSE;
/* Create the child if just starting */
if (!pobj)
{
starting = TRUE;
pobj = pc_mkchild(pmom);
if (!pobj)
return(0);
}
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 (0);
}
else
pobj->blkinfo.my_index = 0;
}
}
if (pc_findin(pobj, filename, fileext,dowildcard))
{
return (pobj);
}
else
{
if (starting)
pc_freeobj(pobj);
return (0);
}
}
#if (VFAT)
void pcdel2lfi(LFNINODE *lfi, int nsegs) /* __fn__ */
{
for (;nsegs;nsegs--, lfi--)
lfi->lfnorder = PCDELETE;
}
BOOLEAN pc_deleteseglist(DDRIVE *pdrive, SEGDESC *s) /* __fn__ */
{
BLKBUFF *rbuf;
LFNINODE *lfi;
int ntodo;
if (!s->nsegs)
return(TRUE);
/* Read segblock[0] and copy text */
rbuf = pc_read_blk(pdrive, s->segblock[0]);
if (!rbuf)
return(FALSE);
lfi = (LFNINODE *) &rbuf->data[0];
lfi += s->segindex;
/* If the lfn segments span two blocks then segblock[0] contains the
second block and segblock[1] contains the first.
We delete all of the segments up to and including segindex
in the second block block value stored in segblock[0]. */
/* 2-17-99 We add the check for s->segblock[1] here because
nsegs >= segindex was inadvertantly catching the case where
segindex == 1, nsegs == 1 and entry 0 in the block contained
a valid entry from another file or volume name */
//DM: 3/14/99: fixed. Problem is that in some cases, ntodo is actually
// increased (by 1) rather than decreased. For example, if nsegs is 1
// and segindex is 1, then the file to delete is the 2nd directory entry.
// The old logic would delete 2 entries, not 1, as requested, meaning
// the directory entry for the file before the one being deleted got
// hosed too!
if (s->nsegs > s->segindex+1)
// if (s->nsegs >= s->segindex && s->segblock[1]) WRONG
ntodo = s->segindex+1;
else
ntodo = s->nsegs;
pcdel2lfi(lfi, ntodo);
if ( !pc_write_blk ( rbuf ) )
{
pc_free_buf(rbuf,TRUE); /* Error. Chuck the buffer */
return (FALSE);
}
else
{
pc_free_buf(rbuf,FALSE);
}
if (s->segblock[1])
{
rbuf = pc_read_blk(pdrive, s->segblock[1]);
if (!rbuf)
return (FALSE);
lfi = (LFNINODE *) &rbuf->data[0];
lfi += 15; /* The last index */
pcdel2lfi(lfi, s->nsegs - ntodo);
if ( !pc_write_blk ( rbuf ) )
{
pc_free_buf(rbuf,TRUE); /* Error. Chuck the buffer */
return (FALSE);
}
else
pc_free_buf(rbuf,FALSE);
}
return(TRUE);
}
#if (1)
void text2lfi(char *lfn, LFNINODE *lfi, int nsegs, byte ncksum, byte order) /* __fn__ */
{
int n;
BOOLEAN end_of_lfn = FALSE;
for (;nsegs && !end_of_lfn;nsegs--, lfi--, order++)
{
for(n=0; n<10; n += 2)
{
if (end_of_lfn)
lfi->lfname1[n] = lfi->lfname1[n+1]= 0xff;
else
{
lfi->lfname1[n] = *lfn++;
/* bug fix win95 lfn */
lfi->lfname1[n+1] = 0;
if (lfi->lfname1[n] == 0)
end_of_lfn = TRUE;
}
}
for(n=0; n<12; n += 2)
{
if (end_of_lfn)
lfi->lfname2[n] = lfi->lfname2[n+1] = 0xff;
else
{
lfi->lfname2[n] = *lfn++;
/* bug fix win95 lfn */
lfi->lfname2[n+1] = 0;
if (lfi->lfname2[n] == 0)
end_of_lfn = TRUE;
}
}
for(n=0; n<4; n+=2)
{
if (end_of_lfn)
lfi->lfname3[n] = lfi->lfname3[n+1] = 0xff;
else
{
lfi->lfname3[n] = *lfn++;
/* bug fix win95 lfn */
lfi->lfname3[n+1] = 0;
if (lfi->lfname3[n] == 0)
end_of_lfn = TRUE;
}
}
if(*lfn == 0)
{
end_of_lfn = TRUE;
}
if (end_of_lfn)
order |= FIRST_NAMESEG;
lfi->lfnorder = order;
lfi->lfnattribute = 0x0F;
lfi->lfnres = 0;
lfi->lfncksum = ncksum;
lfi->lfncluster = 0x0000;
}
}
#else
void text2lfi(char *lfn, LFNINODE *lfi, int nsegs, byte ncksum, byte order) /* __fn__ */
{
int n;
BOOLEAN end_of_lfn = FALSE;
for (;nsegs && !end_of_lfn;nsegs--, lfi--, order++)
{
for(n=0; n<5; n++)
{
if (end_of_lfn)
lfi->lfname1[n] = 0xffff;
else
{
lfi->lfname1[n] = *lfn++;
if (lfi->lfname1[n] == 0)
end_of_lfn = TRUE;
}
}
for(n=0; n<6; n++)
{
if (end_of_lfn)
lfi->lfname2[n] = 0xffff;
else
{
lfi->lfname2[n] = *lfn++;
if (lfi->lfname2[n] == 0)
end_of_lfn = TRUE;
}
}
for(n=0; n<2; n++)
{
if (end_of_lfn)
lfi->lfname3[n] = 0xffff;
else
{
lfi->lfname3[n] = *lfn++;
if (lfi->lfname3[n] == 0)
end_of_lfn = TRUE;
}
}
if (end_of_lfn)
order |= FIRST_NAMESEG;
lfi->lfnorder = order;
lfi->lfnattribute = 0x0F;
lfi->lfnres = 0;
lfi->lfncksum = ncksum;
lfi->lfncluster = 0x0000;
}
}
#endif
BOOLEAN pc_seglist2disk(DDRIVE * pdrive, SEGDESC *s, char *lfn) /* __fn__*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -