⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fstouser.c

📁 一个操作系统源代码 用于嵌入式设备 在Vc++环境下仿真 成功移植到多款处理器上
💻 C
字号:
/*
 *  asixos/fs/FCB.c
 *
 *  Copyright (C) 2002 Asic Center
 *	
 *	2002-08-05	Created by Julias
 *	2002-08-30	Modify the function fdelete. Add delete a empty directory.
 *	2002-09-03	Add the check  in function fopen.
 *
 */

/*
 * '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 <math.h>

#include <filesys\fs.h>
#include "parse.h"
#include "fcb.h"
#include "filebuf.h"
#include "file.h"
#include "iobuf.h"
#include "block.h"
#include "multsk.h"



/*
 * Function Prototype
 */
FILE_S *fopen( char *fname, char *mode );
int fclose( FILE_S *fp );
int fseek( FILE_S *fp, long offset, int base );
int fwrite( void *buf, int size, int count, FILE_S *fp );
int fread( void *buf, int size, int count, FILE_S *fp );
int fcreate( char *path );
int fdelete( char *path );


/* 
 * fopen :
 *	function:	Open the file user wants, if this file does't exist, create it. 
 *				Here we only support two open types: 'rb+' and 'wb+'.
 *	parameter:
 *		fname :	file name user wants to open
 *		mode  :	mode user wants to open( here this parameter we reserve )
 *	return value:
 *		ERROR:	fail
 *		OK:		success
 */
FILE_S *fopen( char *fname, char *mode )
{
	PATH_NODE_S		*path_node;
	FILE_S			*fp;
	unsigned long	openmode;

	if( check_opened_file_num() < 0 )//02-8-24 13:47
//		return (FILE_S *)FS_ERROR;
		return NULL;
	
	if ( fname == NULL && mode == NULL )
//		return (FILE_S *)FS_ERR_PAR;
		return NULL;
		
	if ( ( path_node = (PATH_NODE_S *)FS_MALLOC( sizeof(PATH_NODE_S) ) ) == NULL )
//		return (FILE_S *)FS_ERROR;	
		return NULL;

	if ( (int)parse_path( fname, path_node ) < 0 )
//		return (FILE_S *)FS_ERROR;
		return NULL;
	
	if ( path_node->magic != PATH_NODE_MAGIC )
//		return (FILE_S *)FS_ERR_MAGIC;
		return NULL;
		
	FS_FREE( path_node );

	/*
	 * check the parameter 'mode' and change it to the type
	 * we use inside filesystem.2002-9-3 17:30
	 */
	/* Here we use if-else instead of switch, because the machine 
	 * doesn't recegnize character in switch.
	 */
	/*
	switch ( mode )
	{
		case "rb+":
			openmode = FS_OPEN_FILE;
			break;
		case "wb+":
			openmode = FS_CREATE_FILE;
			break;
		default:
			return (FILE_S *)FS_ERROR;
	}*/
	if( strcmp( mode, "rb+" ) == 0 )
		openmode = FS_OPEN_FILE;
	else 
		if( strcmp( mode, "wb+" ) == 0 ) openmode = FS_CREATE_FILE;
//	else
//		return (FILE_S *)FS_ERROR;
	else
		return NULL;
		
	if ( (int)( fp = get_FILE( fname, openmode ) ) < 0 )
//		return (FILE_S *)FS_ERROR;
		return NULL;

	return fp;
}

 
/* 
 * fclose :
 *	function:	Close the file user wants 
 *	parameter:
 *		fp :	FILE pointer points the file user wants to close.
 *	return value:
 *		FS_ERROR:	fail
 *		FS_OK:		success
 */
int fclose( FILE_S *fp )
{
	if ( fp == NULL )
		return FS_ERR_PAR;

	if ( fp->magic != FILE_MAGIC )
		return FS_ERR_MAGIC;

	if ( (int)remove_FILE( fp ) < 0 )
		return FS_ERROR;
		
	if( remove_fscb_item( (unsigned int)fp ) < 0 )
		return FS_ERROR;//02-8-24 13:52

	return FS_OK;
}

/*
*  add by dsa 2002/11/04 
*  close file immediately and use --
*
*/
int fclosenow( FILE_S *fp )
{
	if ( fp == NULL )
		return FS_ERR_PAR;

	if ( fp->magic != FILE_MAGIC )
		return FS_ERR_MAGIC;

	if ( (int)remove_FILEnow( fp ) < 0 )
		return FS_ERROR;
		
	if( remove_fscb_item( (unsigned int)fp ) < 0 )
		return FS_ERROR;//02-8-24 13:52

	return FS_OK;
}

 /* 
 * fseek :
 *	function:	Move the pointer to specified position.
 *	parameter:
 *		fp :		pointer points to the file will be written to.
 *		offset :	offset to move from specified position.
 *		base :		jumping-off point.
 *	return value:
 *		FS_ERROR:	fail
 *		FS_OK:		success
 */
int fseek( FILE_S *fp, long offset, int base )
{
	unsigned long		curp, end;
//	long				i, length;//the number of subfcb from head to current pointer
//	register SUBFCB_S	*subfcb, *tempsub;

	/*
	 * check fp
	 */
	if ( fp == NULL )
		return FS_ERR_PAR;
	if ( fp->magic != FILE_MAGIC )
		return FS_ERR_MAGIC;
	
	/*check offset*/
	if ( fabs(offset) > fp->fcb->file_length )
		return FS_ERROR;


	switch( base )
	{
		case SEEK_SET:
			/*check offset whether it's beyond the file*/
			if ( offset < 0 )
				return FS_ERROR;

			end = offset;
			break;
		case SEEK_CUR:
			curp = get_curp( (unsigned int)fp );
			if ( offset < 0 )
				if ( fabs(offset) > curp )
					return FS_ERROR;
			else if ( curp + offset > fp->fcb->file_length )
				return FS_ERROR;

			end = curp + offset;
			break;
		case SEEK_END:
			if ( offset > 0 )
				return FS_ERROR;

			end = fp->fcb->file_length + offset;
			break;
	}

#if 0
	length = ( (end - FCB_BLK_NUM) + (SUBFCB_BLK_NUM - 1) ) / SUBFCB_BLK_NUM;
	if ( length > 0 )
	{
		/*
		 * read subfcb to ram
		 */
		for ( subfcb = (SUBFCB_S *)fp->fcb, i = 0; i < length; i++ )
		{
			if ( subfcb->nextfcb == NULL )
			{
				if ( (tempsub = (SUBFCB_S *)read_FCB( subfcb->nextblk, &fp->link )) == FS_ERROR )
					return FS_ERROR;

				subfcb->nextfcb = tempsub;
				subfcb->flag = 1;
			}
			subfcb = subfcb->nextfcb;
		}
	}
#endif	

	set_curp( (unsigned int)fp, end );

	return FS_OK;
}

 /* 
 * fwrite :
 *	function:	Write data from buf to file.
 *	parameter:
 *		buf :		pointer points to the buffer stors data that will be written to file.	
 *		size :		the size of a unit be written.
 *		count :		the number of unit.
 *		fp :		pointer points to the file will be written to.
 *	return value:
 *		FS_ERROR:	fail
 *		FS_OK:		success
 */
int fwrite( void *buf, int size, int count, FILE_S *fp )
{
	unsigned int	length;

	if ( buf == NULL || fp == NULL )
		return FS_ERR_PAR;

	if ( fp->magic != FILE_MAGIC )
		return FS_ERR_MAGIC;

	length = size * count;

	if ( (int)write_file( fp, buf, length ) < 0 )
		return FS_ERROR;

	return FS_OK;
}

/* 
 * fread :
 *	function:	Read data from file to buf.
 *	parameter:
 *		buf :		pointer points to the buffer will stor data that be read from file.
 *		size :		the size of a unit be read.
 *		count :		the number of unit.
 *		fp :		pointer points to the file will be read from.
 *	return value:
 *		FS_ERROR:	fail
 *		FS_OK:		success
 */
int fread( void *buf, int size, int count, FILE_S *fp )
{
	unsigned int		length;

	if ( buf == NULL || fp == NULL )
		return FS_ERR_PAR;

	if ( fp->magic != FILE_MAGIC )
		return FS_ERR_MAGIC;

	length = size * count;

	if ( (int)read_file( fp, buf, length ) < 0 )
		return FS_ERROR;

	return FS_OK;
}

/* 
 * fcreate :
 *	function:	Create a file according to the path user gives
 *				and not open it. 
 *	parameter:
 *		path :	the absulote path
 *	return value:
 *		FS_ERROR:	fail
 *		fS_OK:		success
 */
/*
int fcreate( char *path )
{
	FILE_S			*fp;
	PATH_NODE_S		*path_node;

	if ( path == NULL )
		return FS_ERR_PAR;

	if ( parse_path( path, path_node ) != FS_OK )
		return FS_ERROR;
	
	if ( path_node->magic != PATH_NODE_MAGIC )
		return FS_ERR_MAGIC;

	if ( path_node->node[0][0] != '/' )
		return FS_ERROR;
	
	if ( (int)(fp = get_FILE( path, FS_CREATE_FILE )) < 0 )
		return FS_ERROR;
	
	return FS_OK;
}
*/

/* 
 * fdelete :
 *	function:	Delete a file not be used or a empty directory.
 *	parameter:
 *		path :	the absulote path
 *	return value:
 *		FS_ERROR:	fail
 *		fS_OK:		success
 */
int fdelete( char *path )
{
	register PATH_NODE_S	*path_node;
	register DIR_S			*dir;
	register DCB_S			*dcb;
	register char			*p, *block;
	int						i;
	unsigned long			j;
	unsigned int			blkid;
	unsigned int			*data;
	

	/* 
	 * Check the path
	 */
	if ( path == NULL )
		return FS_ERR_PAR;
	
	path_node = (PATH_NODE_S *)FS_MALLOC(sizeof(PATH_NODE_S));
	if ( (int)parse_path( path, path_node ) < 0 )
		goto EXIT_ENTRY;
	if ( path_node->magic != PATH_NODE_MAGIC )
		goto EXIT_ENTRY;

	/*
	 * Check whether the file is open.
	 */
	for ( i = 0; i < MAX_OPEN_FILE; i++ )
	{
		if ( !strcmp(filebuf[i].path, path) )
			goto EXIT_ENTRY;
	}

	dir = &RootDir[0];
	dcb = dir->subdir;
	p = (char *)path_node->node;
	p += NODE_LEN;
	
	/* We should lock this file */
	FS_LOCK( FILE_S_LOCK_ID );

	/*
	 * Search the father directory of given file/directory.
	 * All is done in rom.
	 */
	for ( i = 1; i < path_node->depth - 1; i++ )
	{
		for ( j = 0; j < dir->curdir.file_length; j++, dcb++ )
			if ( dcb->dirtype == FS_DIR )
				if ( !strcmp( p, dcb->dirname ) )
					break;

		/*the dirctory doesn't exist*/
		if ( j == dir->curdir.file_length )
			goto ERROR_EXIT;

		/* We find the father directory */
		dir = (DIR_S *)dcb->blkid;
		dcb = dir->subdir;
		p += NODE_LEN;
	}/*end of search father directory*/
	
	/* we search the DCB_S of given file/directory in father directory  */
	for ( i = 0; i < dir->curdir.file_length; i++, dcb++ )
		if ( dcb->dirtype != FS_FREE_FILE )
			if ( !strcmp( p, dcb->dirname ) )
				break;

	if ( *(path + strlen(path) - 1) == '/' )//what we will delete is a dirctory
	{
		/* check whether this directory is empty */
		if ( ((FCB_S *)(dcb->blkid))->file_length != 0 )
			goto ERROR_EXIT;

		if ( ((FCB_S *)(dcb->blkid))->magic != FILE_MAGIC )
			goto ERROR_EXIT;
		/*
		 * Here we assume that a directory uses a block.
		 */
		if ( free_block( dcb->blkid, &blkid, &data ) < 0 )
			goto ERROR_EXIT;
		
		write_block( NULL, blkid, 0, BLOCKSIZE, data, IMMEDIATE_WRITE );
	}
	else//what we will delete is a file
	{
		if ( ((FCB_S *)dcb->blkid)->magic != FCB_MAGIC )
			goto ERROR_EXIT;

		if ( (int)del_FCB( dcb->blkid ) < 0 )
			goto ERROR_EXIT;
	}

	/*
	 * Modify the infomation in father diretory.
	 * Here we read the block of father directory from rom, 
	 * then find the DCB_S of the file/directory we operating 
	 * and free it.
	 */
	block = FS_MALLOC( BLOCKSIZE );
	if ( block == NULL )
		goto ERROR_EXIT;
	read_block( NULL, (unsigned int)dir, 0, BLOCKSIZE, block );
	dcb = ((DIR_S *)block)->subdir;
	for ( j = 0; j < ((DIR_S *)block)->curdir.file_length; j++, dcb++ )
		if ( !strcmp( p, dcb->dirname ) )
			break;
	memset( dcb, 0, sizeof(DCB_S) );
	((DIR_S *)block)->curdir.file_length--;
	write_block( NULL, (unsigned int)dir, 0, BLOCKSIZE, block, IMMEDIATE_WRITE );
	FS_FREE(block);

	FS_FREE(path_node);
	FS_UNLOCK( FILE_S_LOCK_ID );
	return FS_OK;

ERROR_EXIT:
	FS_UNLOCK( FILE_S_LOCK_ID );
EXIT_ENTRY:
	FS_FREE(path_node);
	return FS_ERROR;
/*
EXIT_ENTRY:
	FS_FREE(path_node);
	return FS_ERROR;
*/
}

/* 
 * freaddir :
 *	function:	read all the files and the directories of given directory.
 *	parameter:
 *		path :	the absulote path
 *	return value:
 *		FS_ERROR:	fail
 *		fS_OK:		success
 */
int freaddir( char *path, DIRINFO_S *dirinfo )
{
	char					*p;
	int						i, j;
	DIR_S					*dir;
	register DCB_S			*dcb;
//	char					name[DIR_TREE_MAX_DEPTH][NAME_MAX];
	register PATH_NODE_S	*path_node;

	
	if ( path == NULL )
		return FS_ERR_PAR;
	/*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;

	dir = &RootDir[0];
	dcb = dir->subdir;
	p = (char *)path_node->node;
	p += NODE_LEN;

	/* We should lock this file */
//	FS_LOCK( FILE_S_LOCK_ID );

	/*
	 * Search the father directory of given file/directory.
	 * All is done in rom.
	 */
	for ( i = 1; i < path_node->depth; i++ )
	{
		for ( j = 0; j < dir->curdir.file_length; j++, dcb++ )
			if ( dcb->dirtype == FS_DIR )
				if ( !strcmp( p, dcb->dirname ) )
					break;

		/*the dirctory doesn't exist*/
		if ( j == dir->curdir.file_length )
			goto ERROR_EXIT;

		/* We find the father directory */
		dir = (DIR_S *)dcb->blkid;
		dcb = dir->subdir;
		p += NODE_LEN;
	}/*end of search father directory*/

	/* Read all the files and the directories in this directory. */
	memset ( dirinfo, 0, sizeof(DIRINFO_S) );
	dirinfo->allnum = dir->curdir.file_length;
	for( i = 0; i < dir->curdir.file_length; i++, dcb++ )
		if ( dcb->dirtype != FS_FREE_FILE )
		{
			dirinfo->siminfo[i].type = dcb->dirtype;
			memcpy( dirinfo->siminfo[i].name, dcb->dirname, NAME_MAX );
		}
	
//	FS_UNLOCK( FILE_S_LOCK_ID );
	return FS_OK;
	
ERROR_EXIT:
//	FS_UNLOCK( FILE_S_LOCK_ID );
	return FS_ERROR;

}
//add by dsa 2002.10.25
long GetFileLength( FILE_S *fp )
{
	long fl;
	fl = fp->fcb->file_length;
	return fl;	
}

#if 0
void main()
{
	dir_init();

	fdelete( "/pessia/music/kitaro" );
	
}
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -