📄 fcb.c
字号:
/*
* asixos/fs/FCB.c
*
* Copyright (C) 2002 Asic Center
*
* 2002-08-05 Created by Julias.
* 2002-08-23 Modify the return value when the operation
* fails in function del_RAMFCB.
* Modify the write_block mode from IMMEDIATE_WRITE
* to NORMAL_WRITE, because when the file is created
* we will operate with it normaly.
* 2002-08-24 Add create a new dirctory in function get_FCB.
* 2002-08-28 Modify the type(add register) of varable in every function.
* Check the return value of every function when we tranfer it.
* 2002-09-04 Modify the function del_FCB. Add write_block function.
*/
/*
* 'FCB.c' is the file of FCB module .
* It contains functions(find_FCB, get_FCB, read_FCB,
* del_RAMFCB, del_FCB) which needn't check input-parameter.
*/
//#include <stdio.h>//for simulation
#include <stdlib.h>//for simulation
#include <string.h>
#include <filesys\fs.h>
#include "parse.h"
#include "iobuf.h"
#include "block.h"
#include "iobuf.h"
//#include "simu.h"//just for debug
/*
* Function Prototype
*/
FCB_S *get_FCB( char *path, char flag );
FCB_S *read_FCB( unsigned int blkid, DLIST_S *link );
int del_RAMFCB( FCB_S *fcb_point, DLIST_S *link );
int del_FCB( unsigned int blkid );
SUBFCB_S *new_SUBFCB( FCB_S *fcb );
DLIST_S *list_get_end( DLIST_S *head )
{
DLIST_S *pos;
pos = head->prev;
return pos;
}
#if 0
int init_cache_data()
{
int num;
// DIR_CACHE_NODE_S *dir_node;
/*
* initial the dirctory root to the first dir_cache_node
*/
cache_data.dir_cache_data[0].flag = 1;
INIT_LIST_HEAD( &cache_data.dir_cache_data[0].child );
INIT_LIST_HEAD( &cache_data.dir_cache_data[0].next );
memcpy( cache_data.dir_cache_data[0].dir, &root_dir, sizeof(DIR_S) );
/*
* initial the dir cache struct
*/
cache_data.freenum = DIR_CACHE_NODE_MAX_NUM - 1;
cache_data.freehead = &(cache_data.dir_cache_data[1]);
INIT_LIST_HEAD( &cache_data.treehead );
list_add( &((cache_data.dir_cache_data[0]).next), &cache_data.treehead );
list_add( &cache_data.dir_cache_data[0].next, &cache_data.dir_cache_data[0].child );
// dir_node = list_entry( &cache_data[0].treehead.next, DIR_CACHE_NODE_S, next );
for( num = 1; num < DIR_CACHE_NODE_MAX_NUM; num++ )
{
memset( &(cache_data.dir_cache_data[num]), 0, DIR_CACHE_NODE_MAX_NUM );
}
return FS_OK;
}
#endif
/*
* get_FCB :
* function: Get the FCB according to the path.
* if the flag is FS_CREATE_FILE and the file/directory
* has existed, return FS_ERROR, if the flag is
* FS_OPEN_FILE and the file/directory hasn't existed,
* return FS_ERROR.
* parameter:
* path : the absulote path
* flag : flag whether open a file or create a file
* return value:
* FS_ERROR: fail
* FCB_S*: success
*/
FCB_S *get_FCB( char *path, char flag )
{
PATH_NODE_S *path_node;
DIR_CACHE_NODE_S *temp_dir_node, *head_dir_node, *temp_head_node;
DIR_CACHE_S *dir = &cache_data;
DCB_S *fatherdir;
DLIST_S *dlist;
FCB_S *fcb,*dircb;
unsigned char *block, writemode;
unsigned long j = 0;
int i = 0, useflag, type;
char *p;//point to the dir/file name/
/*parst the path*/
if ( ( path_node = (PATH_NODE_S *)FS_MALLOC( sizeof(PATH_NODE_S) ) ) == NULL )
return (FCB_S *)FS_ERROR;
if ( parse_path( path, path_node ) != FS_OK )
return (FCB_S *)FS_ERROR;
/*
* Search the father directory of the file/directory
* according to the path.
*/
/*Get the pointer of root dir_cache_node*/
head_dir_node = list_entry( &(dir->treehead.next->next), DIR_CACHE_NODE_S, next );
temp_head_node = head_dir_node;
temp_dir_node = head_dir_node;
p = (char *)path_node->node;
/*we begin from the dirctory subjected to root*/
p += NODE_LEN;
/*Search father directory in the dir_cache_node one by one*/
for ( i = 1; i < path_node->depth - 1; i++ )
{
/*circle search the dir_tree*/
list_for_each( dlist, &temp_head_node->child )
{
temp_dir_node = list_entry( dlist, DIR_CACHE_NODE_S, next );
/*
* dir_node->dir is the one we searching for,
* we will move it from present position to the lefted
* position in cache_node link.
*/
if ( !strcmp( p, ((FCB_S *)temp_dir_node->dir)->file_name ) )
{
list_move_to_head( &(temp_dir_node->next), &(temp_head_node->child) );
break;
}
}
/* The directory we searching is not in cache node link */
if ( dlist == &(temp_head_node->child) )
{
/* Search this directory's infomation in
its father directory */
dircb = (FCB_S *)temp_head_node->dir;
dircb++;
fatherdir = (DCB_S *)dircb;
for ( dircb = (FCB_S *)temp_head_node->dir,
j = 0; j < dircb->file_length; fatherdir++, j++ )
/*check whether the fatherdir is a directory*/
if ( fatherdir->dirtype == FS_DIR )
if ( !strcmp( p, fatherdir->dirname ) )
break;
/*this dir dosn't exist*/
if ( j == dircb->file_length )
return (FCB_S *)FS_ERROR;
else
{
/*add this dir to cache node*/
if ( &cache_data.freehead != NULL )
{
/*
* search the free node
*/
/*this node is used*/
temp_dir_node = cache_data.freehead;
while( temp_dir_node->flag == BE_USED )
temp_dir_node++;
}
else
{
/*
* search the node which hasn't been read for
* the longest time.
*/
temp_dir_node = head_dir_node;
while( temp_dir_node->child.next != NULL )
temp_dir_node = list_entry( list_get_end(&(temp_dir_node->child)),
DIR_CACHE_NODE_S, child );
}
/*
* add this dir to cache node
*/
temp_dir_node->flag = BE_USED;
INIT_LIST_HEAD( &(temp_dir_node->child) );
INIT_LIST_HEAD( &(temp_dir_node->next) );
/*here we read dirctory, it is beyond the file,
so the parameter DLIST *head here is NULL*/
read_block( NULL, fatherdir->blkid, 0,
BLOCKSIZE, (unsigned char *)(temp_dir_node->dir) );
// fcb = (FCB_S* )temp_dir_node->dir;//for debug
list_add( &(temp_dir_node->next), &(temp_head_node->child) );
cache_data.freenum--;
if ( cache_data.freenum == 0 )
cache_data.freehead = NULL;
else
cache_data.freehead++;
}
}
temp_head_node = list_entry( &(temp_dir_node->child), DIR_CACHE_NODE_S, child);
p += NODE_LEN;
}/*end of search dir, and the pointer temp_dir_node points to this file's father dirctory*/
/*now we find FCB we want*/
dircb = (FCB_S *)temp_dir_node->dir;
dircb++;
fatherdir = (DCB_S *)dircb;
for( dircb--, j = 0; j < dircb->file_length; j++, fatherdir++ )
{
if ( fatherdir->dirtype == FS_EXIST_FILE )
if ( !strcmp( p, fatherdir->dirname ) )
break;
}
/*we find the FCB we want*/
if ( j != dircb->file_length )
{
if ( flag == FS_CREATE_FILE )
return (FCB_S *)FS_ERROR;
/*read FCB*/
/*here the second parameter is NULL,
because the file link is NULL*/
if ( (int)(fcb = read_FCB( fatherdir->blkid, NULL )) < 0 )
return (FCB_S *)FS_ERROR;
}
/*
*the file we want doesn't exist.we will create it
*/
else
{
if ( flag == FS_OPEN_FILE )
return (FCB_S *)FS_ERROR;
/*here we assume that the FCB block is never full*/
/*
* We will create a new FCB or DCB not only in ram
* but also in rom according the filename. If the
* last character is '/', we will create a new DCB,
* else we will create a new FCB.
*/
if( *(path + strlen( path ) - 1) == '/' )//thing we should create is a dirctory
{
i = sizeof(DIR_S);
j = FILE_MAGIC;
writemode = IMMEDIATE_WRITE;
useflag = NOT_BE_USED;
type = FS_DIR;
}
else
{
i = BLOCKSIZE;
j = FCB_MAGIC;
writemode = NORMAL_WRITE;
// writemode = IMMEDIATE_WRITE;//test code 02-8-27 14:03 Pessia
useflag = BE_USED;
type = FS_EXIST_FILE;
}
block = (unsigned char *)FS_MALLOC( i );
if ( block == NULL )
return (FCB_S *)FS_ERR_NOMEM;
memset ( block, 0, BLOCKSIZE );
fcb = (FCB_S *)block;
fcb->flag = useflag;
fcb->magic = j;
if ( ( fcb->blkid = get_block( dircb->partition ) ) == FS_ERROR )
goto ERROR_EXIT;
fcb->nextfcb = NULL;
fcb->nextblk = 0;
fcb->partition = dircb->partition;
memcpy( fcb->file_name, p, NAME_MAX );
fcb->file_length = 0;
/*fill father FCB*/
dircb->flag = useflag;
dircb->file_length++;
fatherdir->blkid = fcb->blkid;
fatherdir->dirtype = type;
memcpy( fatherdir->dirname, p, NAME_MAX );
if ( (int)write_block( NULL, fcb->blkid, 0,
BLOCKSIZE, block, writemode ) < 0 )
goto ERROR_EXIT;
if ( (int)write_block( NULL, dircb->blkid, 0, BLOCKSIZE,
(unsigned char *)dircb, writemode ) < 0 )
goto ERROR_EXIT;
}
FS_FREE( path_node );
return fcb;
ERROR_EXIT:
FS_FREE( block );
FS_FREE( path_node );
return (FCB_S *)FS_ERROR;
}
/*
* read_FCB :
* function: create a FCB struct in ram,
* then read the FCB from physical rom to ram.
* parameter:
* blkid : the block stores FCB
* return value:
* FS_ERROR: fail
* FCB_S*: success
*/
FCB_S *read_FCB( unsigned int blkid, DLIST_S *link )
{
unsigned char *block;
block = (unsigned char *)FS_MALLOC( BLOCKSIZE );
if ( block == NULL )
return (FCB_S *)FS_ERR_NOMEM;
read_block( link, blkid, 0, BLOCKSIZE, block );
return (FCB_S *)block;
}
/*
* new_SUBFCB :
* function: get two blocks(one in physical rom,
* and the other in ram) to store SUBFCB_S.
* parameter:
* fcb : the FCB that this new subfcb belongs to
* return value:
* FS_ERROR: fail
* SUBFCB_S*: success
*/
SUBFCB_S *new_SUBFCB( FCB_S *fcb )
{
register SUBFCB_S *subfcb;
register unsigned char *block;
block = FS_MALLOC( BLOCKSIZE );
if ( block == NULL )
return (SUBFCB_S *)FS_ERR_NOMEM;
memset ( block, 0, BLOCKSIZE );
subfcb = (SUBFCB_S *)block;
subfcb->flag = 1;
if ( ( subfcb->blkid = get_block( fcb->partition ) ) == FS_ERROR )
return (SUBFCB_S *)FS_ERROR;
subfcb->magic = FCB_MAGIC;
subfcb->nextblk = 0;
subfcb->nextfcb = NULL;
return subfcb;
}
/*
* del_RAMFCB :
* function: free this FCB(only this one) in ram
* parameter:
* fcb_point : the FCB will be delete
* link : the 'file' link
* return value:
* FS_ERROR: fail
* FS_OK: success
*/
int del_RAMFCB( FCB_S *fcb_point, DLIST_S *link )
{
SUBFCB_S *subfcb, *tempsub;
/*
* here we assume the subfcb is less than 10.
*/
unsigned int fcbadd[11];
int i;
/*
* if this fcb is modified, we will write it to physical rom
*/
memset( fcbadd, 0, 44 );
tempsub = (SUBFCB_S *)fcb_point;
fcbadd[0] = (unsigned int)tempsub;
for ( subfcb = tempsub->nextfcb, i = 1; subfcb != NULL; subfcb = tempsub->nextfcb, i++ )
{
fcbadd[i] = (unsigned int)subfcb;
if ( tempsub->flag == BE_USED )
{
tempsub->flag = NOT_BE_USED;
tempsub->nextfcb = NULL;
if ( write_block( link, tempsub->blkid, 0, BLOCKSIZE,
(unsigned char *)tempsub, NORMAL_WRITE ) != FS_OK )
return FS_ERROR;
}
tempsub = subfcb;
}
fcbadd[i] = (unsigned int)subfcb;//here has must store 0.
if ( tempsub->flag == BE_USED )
{
tempsub->flag = NOT_BE_USED;
// tempsub->nextfcb = NULL;
if ( write_block( link, tempsub->blkid, 0, BLOCKSIZE,
(unsigned char *)tempsub, NORMAL_WRITE ) != FS_OK )
return FS_ERROR;
}
sync_link( link );
/*
* delete all the fcb structs in the fcb link.
*/
for( i = 0; fcbadd[i] != 0; i++ )
FS_FREE( (unsigned char *)fcbadd[i] );
return FS_OK;
}
/*
* del_FCB :
* function: delete the FCB struct and all the block this FCB used
* in physical rom. the blkid is sure to be the address
* that store the FCB.
* parameter:
* blkid : the block that stores FCB
* return value:
* FS_OK: success
*/
int del_FCB( unsigned int blkid )
{
unsigned int p, tempid, blkmap, tempblk;
unsigned long rest_length, per_length;
SUBFCB_S *subfcb;
unsigned int *data, *tempdata;
rest_length = (((FCB_S *)blkid)->file_length + BLOCKSIZE - 1) / BLOCKSIZE;
/*
*free the blocks whose ID is stored in the block the fcb struct stores
*/
per_length = rest_length > FCB_BLK_NUM ? BLOCKSIZE : rest_length * 4 + sizeof(FCB_S);
p = blkid + sizeof(FCB_S);
if ( free_block( *((unsigned int *)p), &blkmap, &data ) < 0 )
return FS_ERROR;
for ( p = p + 4; p < blkid + per_length; p += 4 )
{
if ( free_block( *((unsigned int *)p), &tempblk, &tempdata ) < 0 )
return FS_ERROR;
if ( blkmap != tempblk )
{
write_block( NULL, blkmap, 0, BLOCKSIZE, data, IMMEDIATE_WRITE );
blkmap = tempblk;
data = tempdata;
}
}
/*
* free the blocks whose ID is stored in the same block of subfcb struct,
* then free this block.
*/
tempid = blkid;
for ( subfcb = (SUBFCB_S *)((SUBFCB_S *)tempid)->nextblk, rest_length = rest_length - FCB_BLK_NUM; (unsigned int)subfcb != 0; subfcb = (SUBFCB_S *)((SUBFCB_S *)tempid)->nextblk )
{
/* Free the preFCB_S */
if ( free_block( tempid, &tempblk, &tempdata ) < 0 )
return FS_ERROR;
if ( blkmap != tempblk )
{
write_block( NULL, blkmap, 0, BLOCKSIZE, data, IMMEDIATE_WRITE );
blkmap = tempblk;
data = tempdata;
}
/* Free the block whose ID is stored in the block of SUB_FCB_S */
per_length = rest_length > SUBFCB_BLK_NUM ? BLOCKSIZE : rest_length * 4 + sizeof(SUBFCB_S);
for ( p = (unsigned int)subfcb + sizeof(SUBFCB_S); p < (unsigned int)subfcb + per_length; p += 4 )
{
if ( free_block( *((unsigned int *)p), &tempblk, &tempdata ) < 0 )
return FS_ERROR;
if ( blkmap != tempblk )
{
write_block( NULL, blkmap, 0, BLOCKSIZE, data, IMMEDIATE_WRITE );
blkmap = tempblk;
data = tempdata;
}
}
tempid = (unsigned int)subfcb;
rest_length = rest_length - SUBFCB_BLK_NUM;
}
if ( free_block( tempid, &tempblk, &tempdata ) < 0 )
return FS_ERROR;
if ( blkmap != tempblk )
write_block( NULL, tempblk, 0, BLOCKSIZE, tempdata, IMMEDIATE_WRITE );
write_block( NULL, blkmap, 0, BLOCKSIZE, data, IMMEDIATE_WRITE );
return FS_OK;
}
#if 0
int main()
{
FCB_S *firstfcb;
/*initial all the block*/
dir_init();
firstfcb = get_FCB( "/pessia/music/sense", FS_OPEN_FILE );
return FS_OK;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -