📄 filesystem.c
字号:
}
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 + -