📄 filesystem.c
字号:
header.seq = last_sequence + 1;
header.ver = 0;
header.fs_version = FS_VERSION;
header.flag = FS_USED;
header.file = f->name;
new_block = fs_block_new(&header, buf, write_size);
//update table
fs_blocklist_get(block, &link);
link.next_block = new_block;
fs_blocklist_set(block, &link);
link.name = f->name;
link.used = 1;
link.next_block = -1;
fs_blocklist_set(new_block, &link);
fs_blocks_used++;
if(f->name < 128 || f->name > 143)
fs_nonpriv_blocks_used++;
}
else
{
//add to existing block
if(len > (int)FS_BLOCK_SIZE - header.last_byte)
{
write_size = (int)FS_BLOCK_SIZE - header.last_byte;
}
else
{
write_size = len;
}
new_block = fs_block_append(block, buf, write_size);
if(f->current_block == block)
{
f->current_block = new_block;
}
if(previous_block == -1)
{
f->first_block = new_block;
fs_filelist_set(f->name, new_block);
}
else
{
//update next pointer for previous block
fs_blocklist_get(previous_block, &link);
link.next_block = new_block;
fs_blocklist_set(previous_block, &link);
}
//unset old block in table
link.used = 0;
link.next_block = -1;
fs_blocklist_set(block, &link);
//update new block in table
link.name = f->name;
link.used = 1;
link.next_block = -1;
fs_blocklist_set(new_block, &link);
}
len -= write_size;
buf += write_size;
written += write_size;
} //end of while(len)
return written;
}
/*** BeginHeader fshift */
int fshift(File *f, int count, char *buf);
/*** EndHeader */
/* START FUNCTION DESCRIPTION ********************************************
fshift <filesystem.lib>
SYNTAX: int fshift(File *f, int count, char *buffer)
KEYWORDS: file system
DESCRIPTION: removes 'count' number of bytes from the beginning of a file.
These bytes will be copied into the buffer if it is not null
PARAMETER1: file pointer
PARAMETER2: number of bytes to shift out
PARAMETER3: buffer to store shifted bytes. If this is NULL, it will not
be used.
RETURN VALUE: number of bytes shifted out
0 - error
SEE ALSO:
END DESCRIPTION **********************************************************/
nodebug int fshift(File *f, int count, char *buf)
{
auto int shifted, shift_size, block, new_block;
auto FSHeader header;
auto FSBlockLink link;
shifted = 0;
while(count > 0)
{
block = fs_filelist_get(f->name);
if(block < 0)
return 0; //no starting block listed
fs_get_header(block, &header);
if(count >= header.last_byte - header.first_byte)
{
//shift out all of the block
shift_size = header.last_byte - header.first_byte;
if(buf)
{
fs_block_read(block, header.first_byte, buf, shift_size);
buf += shift_size;
}
fs_blocklist_get(block, &link);
new_block = link.next_block;
if(new_block == FS_NOBLOCK)
{
count = 0; //stop shifting, file is empty
header.first_byte = header.last_byte;
header.crc = 0;
header.ver++;
new_block = fs_block_update(block, &header);
fs_blocklist_set(new_block, &link);
}
else
{
fs_get_header(new_block, &header);
f->num_blocks--;
f->first_sequence = header.seq;
fs_erase_block(block, 0);
fs_blocks_used--;
if(f->name < 128 || f->name > 143)
fs_nonpriv_blocks_used--;
}
if(f->current_block == block)
{
f->current_block = new_block;
f->current_offset = header.first_byte;
}
}
else
{
//just shift out some of the block
shift_size = count;
if(buf)
{
fs_block_read(block, header.first_byte, buf, shift_size);
}
header.first_byte += shift_size;
header.crc = fs_checksum_far(block, header.first_byte,
header.last_byte - header.first_byte, 0, 0);
header.ver++;
fs_blocklist_get(block, &link);
new_block = fs_block_update(block, &header);
fs_blocklist_set(new_block, &link);
if(f->current_block = block)
{
f->current_block = new_block;
if(header.first_byte > f->current_offset)
f->current_offset = header.first_byte;
}
}
link.next_block = -1;
link.used = 0;
link.name = 0;
fs_blocklist_set(block, &link);
fs_filelist_set(f->name, new_block);
f->first_block = new_block;
f->position -= shift_size;
if(f->position < 0)
f->position == 0;
count -= shift_size;
shifted += shift_size;
}
return shifted;
}
/*** BeginHeader fread */
int fread(File *f, char *buf, int len);
/*** EndHeader */
/* START FUNCTION DESCRIPTION ********************************************
fread <filesystem.lib>
SYNTAX: int fread(File *f, char *buf, int len)
KEYWORDS: file system
DESCRIPTION: read len bytes from the file starting at the current
offset in the file into buf.
PARAMETER1: file pointer
PARAMETER2: destination buffer
PARAMETER3: number of bytes to copy
RETURN VALUE: number of bytes read
0 - error
SEE ALSO:
END DESCRIPTION **********************************************************/
nodebug int fread(File *f, char *buf, int len)
{
auto int remaining, read_len, bytes_read;
auto int block;
auto FSHeader header;
if(f->mode!=FS_WRITE && f->mode!=FS_READ) return 0;
bytes_read = 0;
while(len) {
/* loop through blocks until we read all they requested */
fs_get_header(f->current_block, &header);
if(len > header.last_byte - f->current_offset) {
read_len = header.last_byte - f->current_offset;
} else {
read_len = len;
}
#ifdef FS_CHECKSUM_READS
/* verify the checksum */
if(header.crc != fs_checksum_far(f->current_block, header.first_byte,
header.last_byte - header.first_byte, 0, 0)) {
/* ERROR IN CHECKSUM! */
#ifdef FS_DEBUG
printf("--> Block #%d has a bad checksum!\n",f->current_block);
#endif
return 0;
}
#endif
#ifdef FS_DEBUG
printf("--> reading <%d> bytes from block <%d>, seq = %d\n",read_len,f->current_block, header.seq);
#endif
fs_block_read(f->current_block, f->current_offset, buf, read_len);
buf += read_len;
bytes_read += read_len;
len -= read_len;
f->current_offset += read_len;
f->position += read_len;
if(f->current_offset == header.last_byte)
{
/* move to the next block */
block = fs_get_next_block(f->current_block);
if(block == FS_NOBLOCK) {
/* block not found - we hit the end of the file */
return bytes_read;
}
else
{
f->current_sequence++;
f->current_block = block;
fs_get_header(f->current_block, &header);
f->current_offset = header.first_byte;
}
}
}
return bytes_read;
}
/*** BeginHeader ftell */
long ftell(File *f);
/*** EndHeader */
/* START FUNCTION DESCRIPTION ********************************************
ftell <filesystem.lib>
SYNTAX: long ftell(File *f)
KEYWORDS: file system
DESCRIPTION: This function returns the current pointer.
PARAMETER1: file pointer
PARAMETER2: offset in file
RETURN VALUE: offset in file
-1 - failure
SEE ALSO:
END DESCRIPTION **********************************************************/
nodebug long ftell(File *f)
{
auto int block;
auto FSSeq i;
auto long len;
auto FSHeader header;
if(f->mode!=FS_WRITE && f->mode!=FS_READ) return -1;
block = fs_filelist_get(f->name);
if(block == FS_NOBLOCK) return -1;
len = 0;
while(block >= 0)
{
fs_get_header(block, &header);
if(header.seq == f->current_sequence)
{
//current block
len += f->current_offset - header.first_byte;
break;
}
else
{
len += header.last_byte - header.first_byte;
}
block = fs_get_next_block(block);
}
return len;
}
/*** BeginHeader fseek */
int fseek(File *f, long to, char whence);
/*** EndHeader */
/* START FUNCTION DESCRIPTION ********************************************
fseek <filesystem.lib>
SYNTAX: int fseek(File *f, long where, char whence)
KEYWORDS: file system
DESCRIPTION: This function places the current read pointer at
where in the file.
SEEK_SET - offset is measured from the beginning
SEEK_CUR - offset is measured from the current offset
SEEK_END - offset is measured backwards from end.
PARAMETER1: file pointer
PARAMETER2: offset in file
PARAMETER3: where to measure the offset.
RETURN VALUE: 0 - success
1 - failure
SEE ALSO:
END DESCRIPTION **********************************************************/
nodebug int fseek(File *f, long to, char whence)
{
auto long prev, filelength, currentpos, seekpos;
auto int block, current_mark;
auto FSSeq i;
auto FSHeader header;
if(f->mode!=FS_WRITE && f->mode!=FS_READ) return 1;
prev = 0;
//calculate file length
filelength = 0;
currentpos = 0;
current_mark = 0; //flag set when current position is hit
block = fs_filelist_get(f->name);
if(block == FS_NOBLOCK) return 1;
while(block >= 0)
{
fs_get_header(block, &header);
filelength += header.last_byte - header.first_byte;
if(header.seq == f->current_sequence)
{
currentpos += f->current_offset - header.first_byte;
current_mark = 1;
}
else if(current_mark == 0)
{
currentpos += header.last_byte - header.first_byte;
}
block = fs_get_next_block(block);
}
switch(whence)
{
case SEEK_SET:
seekpos = to;
break;
case SEEK_CUR:
seekpos = currentpos + to;
break;
case SEEK_END:
seekpos = filelength + to;
break;
default:
/* ERROR - unknown 'whence' value! */
return 1;
}
//check limits
if(seekpos < 0 || seekpos > filelength)
return 1;
f->position = seekpos;
//set file pointer
block = fs_filelist_get(f->name);
while(block >= 0)
{
fs_get_header(block, &header);
if(seekpos > header.last_byte - header.first_byte)
{
seekpos -= header.last_byte - header.first_byte;
}
else
{
//this is our block
f->current_block = block;
f->current_sequence = header.seq;
f->current_offset = header.first_byte + (int)seekpos;
return 0;
}
block = fs_get_next_block(block);
}
return 1; //end of file, this shouldn't happen
}
/*** BeginHeader fs_level_wear */
int fs_level_wear(int seconds);
/*** EndHeader */
/* START FUNCTION DESCRIPTION ********************************************
fs_level_wear <filesystem.lib>
SYNTAX: int fs_level_wear(int seconds)
KEYWORDS: file system
DESCRIPTION: Wear level flash - Unimplemented.
PARAMETER1: number of seconds to wearlevel
RETURN VALUE: 0 - success
1 - failure
SEE ALSO:
END DESCRIPTION **********************************************************/
nodebug int fs_level_wear(int seconds)
{
/* not implemented yet */
}
/*** Beginheader fs_reserve_blocks */
int fs_reserve_blocks(int blocks);
/*** EndHeader */
/* START FUNCTION DESCRIPTION ********************************************
fs_reserve_blocks <filesystem.lib>
SYNTAX: int fs_reserve_blocks(int blocks)
KEYWORDS: file system
DESCRIPTION: Sets up a number of blocks that will be guarenteed to be
available for priveleged files (128-143)
PARAMETER1: number of blocks to reserve
RETURN VALUE: 0 - success
1 - failure
SEE ALSO:
END DESCRIPTION **********************************************************/
nodebug int fs_reserve_blocks(int blocks)
{
if(blocks >= 0 && blocks < fs_num_blocks - fs_nonpriv_blocks_used)
{
fs_blocks_reserved = blocks;
return 0;
}
else
{
return 1; //failed
}
}
/*** BeginHeader fsck */
int fsck(int flags);
/*** EndHeader */
/* START FUNCTION DESCRIPTION ********************************************
fsck <filesystem.lib>
SYNTAX: int fsck(int flags)
KEYWORDS: file system
DESCRIPTION: Check the filesystem for errors.
PARAMETER1: A bitmask indicating which checks to NOT perform.
The following checks are avaliable:
FSCK_HEADERS - Block headers
FSCK_CHECKSUMS - Data checksums
FSCK_VERSION - Block versions, from a failed write.
RETURN VALUE: 0 - success
non 0 - A bitmask indicating which checks failed.
SEE ALSO:
END DESCRIPTION **********************************************************/
nodebug int fsck(int flags)
{
auto int i;
auto int retval;
FSHeader header;
retval = 0;
if(!(FSCK_HEADERS&flags)) {
#ifdef FS_DEBUG
printf("Checking filesystem block headers...\n");
#endif
for(i=0; i<fs_num_blocks; i++) {
if(fs_verify_block(i)) {
/* ERROR IN HEADER */
#ifdef FS_DEBUG
printf("Error in header for block #%d\n",i);
#endif
retval |= FSCK_HEADERS;
}
}
}
if(!(FSCK_CHECKSUMS&flags)) {
#ifdef FS_DEBUG
printf("Checking filesystem checksums...\n");
#endif
for(i=0; i<fs_num_blocks; i++) {
fs_get_header(i, &header);
if(header.flag == FS_USED)
if(header.crc != fs_checksum_far(i, header.first_byte,
header.last_byte - header.first_byte, 0, 0)) {
/* ERROR IN BLOCK! */
#ifdef FS_DEBUG
printf("Error in checksum on block #%d!\n",i);
#endif
retval |= FSCK_CHECKSUMS;
}
}
}
if(!(FSCK_VERSION&flags)) {
#ifdef FS_DEBUG
printf("Checking for duplicate blocks...\n");
#endif
for(i=0; i<fs_num_blocks; i++) {
if(fs_verify_version(i)) {
retval |= FSCK_VERSION;
}
}
}
return retval;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -