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

📄 filesystem.c

📁 支持nvram盘
💻 C
📖 第 1 页 / 共 3 页
字号:
		}
		else
		{
			len -= FS_SECTOR_SIZE;
			root2xmem(fs_sectorbuf, buf, FS_SECTOR_SIZE);
			buf += FS_SECTOR_SIZE;
		}
		fs_writesector(first_sector + i, fs_sectorbuf, FS_SECTOR_SIZE);
		i++; //next sector
	}
	return new_block;
}

/*** BeginHeader fs_block_update */
int fs_block_update(int block, FSHeader *header_ptr);
/*** EndHeader */

//allows a block header to be changed, returns new block number
nodebug int fs_block_update(int block, FSHeader *header_ptr)
{
	auto FSHeader old_header;
	auto int i, first_sector, new_block, block_pos;

	new_block = fs_find_free();
	if(new_block == FS_NOBLOCK)
		return -1;
	first_sector = new_block*((int)FS_BLOCK_SIZE/FS_SECTOR_SIZE);
	fs_get_header(new_block, &old_header);
	//update wear level
	header_ptr->wear = old_header.wear + 1;
	for(i = 0; i < (int)FS_BLOCK_SIZE/FS_SECTOR_SIZE;i++)
	{
		if(i == 0)
		{
			//write new header into first sector
			root2xmem(fs_sectorbuf, header_ptr, FS_HEADER);				
			fs_block_move(fs_sectorbuf + FS_HEADER,
				block, FS_HEADER, FS_SECTOR_SIZE - FS_HEADER);
			fs_writesector(first_sector, fs_sectorbuf, FS_SECTOR_SIZE);
		}
		else if(header_ptr->first_byte < (i+1)*FS_SECTOR_SIZE)
		{
			fs_block_move(fs_sectorbuf, block, i*FS_SECTOR_SIZE, FS_SECTOR_SIZE);
			fs_writesector(first_sector+i, fs_sectorbuf, FS_SECTOR_SIZE);
			if(header_ptr->last_byte < i*FS_SECTOR_SIZE)
				break; //stop iterating through sectors, were done
		}
	}
	fs_erase_block(block, 0);
	return new_block;
}
			
	
/*****************
 * API functions *
 *****************/

/*** BeginHeader fs_format */
int fs_format(long reserveblocks, int num_blocks, unsigned long wearlevel);
/*** EndHeader */

/* START FUNCTION DESCRIPTION ********************************************
fs_format                      <filesystem.lib>

SYNTAX: int fs_format(long baseaddress, int num_blocks, unsigned wearlevel)

KEYWORDS:      file system

DESCRIPTION:   Initalize internal data structures and file system.

PARAMETER1:    The number of blocks to reserve at the start of the flash
               This parameter is ignored if you have FS_RAM defined.
PARAMETER2:    number of 4096 byte blocks
PARAMETER3:    initial wearlevel value.  This should be 1 if you have a
               new flash, and some larger number if the flash is used.
               If you are reformatting a flash, you can use 0 to use
               the old flash wear levels.

RETURN VALUE:  0 - success
               1 - failure

SEE ALSO:

END DESCRIPTION **********************************************************/
   
/*
 * should this just format, not open? for now it's just like fs_init,
 * but blanks the FS as it opens.
 */
nodebug int fs_format(long reserveblocks,
	int num_blocks, unsigned long wearlevel)
{
	auto int i;

#GLOBAL_INIT {
	fs_temp_buf = xalloc(FS_TEMPBUF_SIZE);
}
	
#ifdef FS_RAM
	fs_offset = 0;
#else	
	fs_offset = reserveblocks*FS_BLOCK_SIZE;
#endif

	fs_num_blocks = num_blocks;
	
	/* Initilize the underlying medium */
	if(fs_block_init(fs_offset, num_blocks))
		return 1;

	/* format all the blocks */
	for(i=0;i<num_blocks;i++) {
		fs_erase_block(i, wearlevel);
	}
	// setup tables
	fs_table_alloc(num_blocks);
	//set up sector buffer
	fs_sectorbuf = xalloc(FS_SECTOR_SIZE);
	fs_blocks_used = 0;
	fs_nonpriv_blocks_used = 0;
	fs_blocks_reserved = 0;
	return 0;
}

/*** BeginHeader fs_init */
int fs_init(long reserveblocks, int num_blocks);
/*** EndHeader */

/* START FUNCTION DESCRIPTION ********************************************
fs_init                        <filesystem.lib>

SYNTAX: int fs_init(long reserveblocks, int num_blocks)

KEYWORDS:      file system

DESCRIPTION:   Initalize internal data structures for an existing file
               system.

PARAMETER1:    The number of blocks to reserve at the start of the flash
               This parameter is ignored if you have FS_RAM defined.
PARAMETER2:    number of 4096 byte blocks

RETURN VALUE:  0 - success
               1 - failure

SEE ALSO:

END DESCRIPTION **********************************************************/

nodebug int fs_init(long reserveblocks, int num_blocks)
{
	auto int i, bad_fs;

#ifdef FS_RAM
	/* format only if we are in ram */
	return 1;
#endif

	fs_offset = reserveblocks*FS_BLOCK_SIZE;

	fs_num_blocks = num_blocks;

	/* Initilize the underlying medium */
	if(fs_block_init(fs_offset, num_blocks))
		return 1;

	/* verify all existing blocks */
	bad_fs = 0;
	for(i=0; i<num_blocks; i++) {
		if(fs_verify_block(i)) {
			bad_fs = 1;
		}
	}

	/* verify version numbers */
	for(i=0; i<num_blocks; i++) {
		if(fs_verify_version(i)) {
			bad_fs = 1;
		}
	}

	//build tables
	fs_table_alloc(num_blocks);
	fs_build_tables();
	fs_blocks_reserved = 0;
	//set up sector buffer
	fs_sectorbuf = xalloc(FS_SECTOR_SIZE);		
	return bad_fs;
}

/*** BeginHeader fcreate_unused */
FileNumber fcreate_unused(File *f);
/*** EndHeader */

/* START FUNCTION DESCRIPTION ********************************************
fcreate_unused                 <filesystem.lib>

SYNTAX: FileNumber fcreate_unused(File *f)

KEYWORDS:      file system

DESCRIPTION:   create a file selecting an unused file number

PARAMETER1:    file pointer

RETURN VALUE:  !=0 - file pointer
               0   - error

SEE ALSO:

END DESCRIPTION **********************************************************/

/* this will search for an unused file number, and fcreate it.
	This is much slower than just fcreate() */
/* returnes 0 on error (none free) */
nodebug FileNumber fcreate_unused(File *f)
{
	auto FileNumber i, j, used;
	auto FSHeader header;
		
	/* find an unused FileNumber */
	for(i=1; i<127; i++) {
		used = 0;
		for(j=0; j<fs_num_blocks; j++) {
			fs_get_header(j, &header);
			if(header.flag == FS_USED)
				if(header.file == i) {
					used = 1;
					break;
				}
		}
		if(!used) {
			if(fcreate(f, i) == 0)
			{
				//fcreate succeeded
				return i;
			}
			else
			{
				return 0;
			}
		}
	}

	return 0;
}

/*** BeginHeader fcreate */
int fcreate(File *f, FileNumber name);
/*** EndHeader */

/* START FUNCTION DESCRIPTION ********************************************
fcreate                        <filesystem.lib>

SYNTAX: int fcreate(File *f, FileNumber name)

KEYWORDS:      file system

DESCRIPTION:   create a file.

PARAMETER1:    file pointer
PARAMETER2:    name of file

RETURN VALUE:  0 - success
               1 - failure

SEE ALSO:

END DESCRIPTION **********************************************************/

nodebug int fcreate(File *f, FileNumber name)
{
	auto int block;
	auto FSBlockLink block_link;
	auto FSHeader header;
	
#ifdef FS_DEBUG
	printf("--> Creating file <%d>\n",name);
#endif

	/* verify that it doesnt exist? */
	if(fs_open_common(f,name)==0)
		return 1;

	//do we have room?
	if(fs_blocks_used > fs_num_blocks - 2)
		return 1; //no blocks left
	if((name < 128 || name > 143) &&
		(fs_nonpriv_blocks_used > fs_num_blocks-fs_blocks_reserved-2))
		return 1;		//no non-priveleged blocks available
		
	/* allocate the first block */
	block = fs_find_free();
	if(block == FS_NOBLOCK)
		return 1; /* no free blocks */

	/* get the old header for the free block */
	fs_get_header(block, &header);
		
	header.flag = FS_USED;
	header.file = name;
	header.first_byte = FS_HEADER;
	header.last_byte = FS_HEADER;
	header.seq = 1;
	header.ver = 0;
	header.wear++;
	header.fs_version=FS_VERSION;
	header.crc = 0;

	/* update the block */
	fs_block_write(block, (char *)&header, FS_HEADER);

	//update the block list
	block_link.name = name;
	block_link.used = 1;
	block_link.next_block = -1;
	fs_blocklist_set(block, &block_link);	
	//update file list
	fs_filelist_set(name, block);
					
	f->name = name;
	f->current_sequence = f->first_sequence = header.seq;
	f->current_block = f->first_block = block;
	f->current_offset = FS_HEADER; /* init to just past the header */
	f->position = 0;
	f->num_blocks = 1;
	fs_blocks_used++;
	if(name < 128 || name > 143)
		fs_nonpriv_blocks_used++;		
	
	f->mode = FS_WRITE;
	return 0;
}

/*** BeginHeader fdelete */
int fdelete(FileNumber name);
/*** EndHeader */
/* START FUNCTION DESCRIPTION ********************************************
fdelete                        <filesystem.lib>

SYNTAX: int fdelete(FileNumber name)

KEYWORDS:      file system

DESCRIPTION:   delete a file

PARAMETER1:    file number of file to delete

RETURN VALUE:  0 - success
               1 - failure

SEE ALSO:

END DESCRIPTION **********************************************************/

nodebug int fdelete(FileNumber name)
{
	auto int block, next;
	
	block = fs_filelist_get(name);
	fs_filelist_set(name, -1); //remove from filelist
	while(block >= 0)
	{
		next = fs_get_next_block(block);
		fs_erase_block(block, 0);
		block = next;
		fs_blocks_used--;
		if(name < 128 || name > 143)
			fs_nonpriv_blocks_used--;		
	}		
}

/*** BeginHeader fopen_rd */
int fopen_rd(File *f, FileNumber name);
/*** EndHeader */

/* START FUNCTION DESCRIPTION ********************************************
fopen_rd                       <filesystem.lib>

SYNTAX: int fopen_rd(File *f, FileNumber name)

KEYWORDS:      file system

DESCRIPTION:   open a file for reading.

PARAMETER1:    file pointer
PARAMETER2:    name of file

RETURN VALUE:  0 - success
               1 - failure

SEE ALSO:

END DESCRIPTION **********************************************************/

nodebug int fopen_rd(File *f, FileNumber name)
{
	auto FSHeader header;

	if(fs_open_common(f, name))
		return 1;

	fs_get_header(f->first_block, &header);		
		
	f->mode = FS_READ;
	
	/* init the current pointer to the first block */
	f->current_sequence = f->first_sequence;
	f->current_block = f->first_block;
	f->position = 0;
	f->current_offset = header.first_byte;

#ifdef FS_DEBUG
	printf("--> open_rd: cur_seq = %d, cur_block = %d, position = %d, cur_offset = %d\n",
		f->current_sequence, f->current_block, f->position, f->current_offset);
#endif	
	return 0;
}

/*** BeginHeader fopen_wr */
int fopen_wr(File *f, FileNumber name);
/*** EndHeader */

/* START FUNCTION DESCRIPTION ********************************************
fopen_wr                       <filesystem.lib>

SYNTAX: int fopen_wr(File *f, FileNumber name)

KEYWORDS:      file system

DESCRIPTION:   open a file for writing.

PARAMETER1:    file pointer
PARAMETER2:    name of file

RETURN VALUE:  0 - success
               1 - failure

SEE ALSO:

END DESCRIPTION **********************************************************/

nodebug int fopen_wr(File *f, FileNumber name)
{
	auto FSHeader header;

	if(fs_open_common(f, name))
		return 1;
		
	f->mode = FS_WRITE;

	/* find the last block */
	fs_get_header(f->current_block, &header);
	
	f->position = ((f->num_blocks - 1)*((int)FS_BLOCK_SIZE - FS_HEADER))
		+ (header.last_byte - header.first_byte);
	f->current_offset = header.first_byte;

	return 0;
}

/*** BeginHeader fclose */
void fclose(File *f);
/*** EndHeader */

/* START FUNCTION DESCRIPTION ********************************************
fclose                         <filesystem.lib>

SYNTAX: void fclose(File *f)

KEYWORDS:      file system

DESCRIPTION:   close the file pointed to by f.

PARAMETER1:    file pointer

RETURN VALUE:  none

SEE ALSO:

END DESCRIPTION **********************************************************/

nodebug void fclose(File *f)
{
	/* just mark it as invalid */
	f->mode = FS_NOTOPEN;
}

/*** BeginHeader fwrite */
int fwrite(File *f, char *buf, int len);
/*** EndHeader */

/* START FUNCTION DESCRIPTION ********************************************
fwrite                         <filesystem.lib>

SYNTAX: int fwrite(File *f, char *buf, int len)

KEYWORDS:      file system

DESCRIPTION:   write len bytes to the file starting at the current
               offset in the file from buf.

PARAMETER1:    file pointer
PARAMETER2:    source buffer
PARAMETER3:    number of bytes to write

RETURN VALUE:  number of bytes written
               0 - error

SEE ALSO:

END DESCRIPTION **********************************************************/

nodebug int fwrite(File *f, char *buf, int len)
{
	auto int block, new_block, previous_block;
	auto FSBlockLink link;
	auto FSHeader header, old_header;
	auto int written;
	auto int write_size;
	auto long last_sequence;
	
	written = 0;
	while(len > 0)
	{			
		//get previous and current blocks
		previous_block = -1;
		block = fs_filelist_get(f->name);
		if(block == -1)
			return 0; //file does not exist
		while(1)
		{
			if(fs_get_next_block(block) == -1)
			{
				break;
			}
			else
			{
				previous_block = block;
				block = fs_get_next_block(block);
			}
		}
		fs_get_header(block, &header);
		last_sequence = header.seq;
		if( header.last_byte == (int)FS_BLOCK_SIZE)
		{
			//start writing to new block
			//do we have room?
			if(fs_blocks_used > fs_num_blocks - 2)
				return written; //no blocks left
			if((f->name < 128 || f->name > 143) &&
				(fs_nonpriv_blocks_used > fs_num_blocks-fs_blocks_reserved-2))
				return written;	//no non-priveleged blocks available
				
			//setup new header
			if(len > FS_BLOCK_SIZE - FS_HEADER)
			{
				write_size = FS_BLOCK_SIZE - FS_HEADER;
			}
			else
			{
				write_size = len;
			}
			header.crc = fs_checksum(buf, write_size, 0, 0);
			header.first_byte = FS_HEADER;
			header.last_byte = write_size + FS_HEADER;

⌨️ 快捷键说明

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