mirror of
https://github.com/peteratebs/tinyfatfs.git
synced 2025-06-18 16:55:42 -04:00
first commit
This commit is contained in:
commit
45e1b1f8ba
6
Makefile
Normal file
6
Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
all: main
|
||||
|
||||
main: main.c rtfslconst.c rtfsldata.c rtfsldelete.c rtfslfailsafe.c rtfslfileseek.c rtfslfilestat.c rtfslfiliocore.c rtfslfiliord.c rtfslfiliowr.c rtfslfssystem.c rtfslgfirst.c rtfslitecore.c rtfsliteshell.c rtfslmkdir.c rtfslopenpath.c rtfslrename.c rtfslrmdir.c rtfslsystem.c rtfstlitefileload.c rtfstlitetestfileio.c rtfstlitetests.c rtfstlitetestutils.c
|
||||
gcc -g -o main main.c rtfslconst.c rtfsldata.c rtfsldelete.c rtfslfailsafe.c rtfslfileseek.c rtfslfilestat.c rtfslfiliocore.c rtfslfiliord.c rtfslfiliowr.c rtfslfssystem.c rtfslgfirst.c rtfslitecore.c rtfsliteshell.c rtfslmkdir.c rtfslopenpath.c rtfslrename.c rtfslrmdir.c rtfslsystem.c rtfstlitefileload.c rtfstlitetestfileio.c rtfstlitetests.c rtfstlitetestutils.c
|
104
README.MD
Normal file
104
README.MD
Normal file
@ -0,0 +1,104 @@
|
||||
Tinyfatfs Low footprint Embedded FAT file system
|
||||
|
||||
EBS - RTFS (Real Time File Manager)
|
||||
|
||||
* Copyright, Peter Van Oudenaren
|
||||
* EBS Inc. 1987-2015
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
|
||||
* contact sales@ebsembeddedsoftware.com
|
||||
|
||||
Rtfs tiny is a very low footprint implementation of the FAT file system.
|
||||
|
||||
This software was written as an experiment to create the smallest footprint FAT file system with the most attainable functionality.
|
||||
|
||||
The code achieves small code size by relying on experience providing commercial FAT file system products over many years.
|
||||
|
||||
The current code does not support vfat but that can be added pretty easilly in we estimate 1 to 2 K of code space.
|
||||
|
||||
|
||||
The code is still not totally refined so beware, send us an email if you'd find a bug or you would like to conrtibute a patch.
|
||||
|
||||
. The ram and rom requirements for rtfsl built under various configurations is provided below.
|
||||
. These are for the ARM processor using the IAR compiler, similar builds need to be made for AVR
|
||||
=============================================================================================
|
||||
read read read
|
||||
only only write Build
|
||||
code data data description.
|
||||
bytes bytes bytes
|
||||
------- ------- ------- ----------------------
|
||||
7422 52 1340 Full build with journaling optimized for size
|
||||
7098 86 792 Full build minus journaling un-optimized
|
||||
5480 52 792 Full build minus journaling optimized
|
||||
5192 20 780 Full build minus journaling, minus subdirectory support optimized for size
|
||||
3588 20 780 Read only file io, directory traversal and file stat functions.
|
||||
2896 12 532 Functionality to load a file from the root directory into memory, optimized for size.
|
||||
|
||||
Full build includes the follow functionality for fat12, fat16 and fat32.:
|
||||
. create a sub-directory in the root or in a subdirectory.
|
||||
. delete a sub-directory
|
||||
. create a file in the root or in a subdirectory.
|
||||
. write to a file.
|
||||
. read from a file.
|
||||
. seek within a file.
|
||||
. close a file.
|
||||
. delete a file
|
||||
When Failsafe support is enabled, the follow functionality is included.
|
||||
. journaling flush.
|
||||
. journaling journal of FAT table changes and directory entry changes.
|
||||
. journaling restore.
|
||||
|
||||
|
||||
|
||||
|
||||
To build the test applcation for a Linux target:
|
||||
type:.
|
||||
make
|
||||
|
||||
To run the symple command shell based example:
|
||||
|
||||
type:
|
||||
sudo ./main devicename
|
||||
|
||||
for example, to access a USB stick at /dev/sdb1:
|
||||
sudo ./main /dev/sdb1
|
||||
|
||||
If that is succesfulyou should see the following help screen:
|
||||
|
||||
LOAD FILENAME
|
||||
LMOUNT - re-mount rtfs lite drive
|
||||
LEXIT - Exit Lite mode refreshes device mount for rtfs
|
||||
LFLUSH - Flush rtfs lite buffers
|
||||
DIR
|
||||
RENAME oldname newname
|
||||
DELETE filename
|
||||
CHDIR path
|
||||
MKDIR dirname 0|1 (1 = fragment)
|
||||
RMDIR dirname
|
||||
FILLPAT filename nlongs 0|1 (1=fragment)
|
||||
APPENDPAT filename nlongs 0|1 (1=fragment)
|
||||
READPAT filename
|
||||
RANDREAD filename
|
||||
RANDWRITE filename
|
||||
FILLDISK filenamebase
|
||||
FSSTART Start Journaling
|
||||
FSSTOP Stop Journaling
|
||||
FSSYNC Sync volume, keep journaling
|
||||
FSFLUSH Flush journal keep journaling
|
||||
FSRESTORE Retore the volume from the journal
|
||||
|
||||
|
||||
The currently supported features include:
|
||||
. File io (create,reopen, read,write,seek,delete).
|
||||
. Subdirectory support (mkdir, rmdir and set working directory).
|
||||
. Failsafe journaling and restore support.
|
||||
. All features have been tested both with using Failsafe and not using Failsafe.
|
||||
. All tests have been performed with FAT12 so far, typically the most difficult case.
|
||||
|
||||
Ongoing development efforts include the following:
|
||||
. Tests still need to be performed on FAT16 and FAT32.
|
||||
. Testing is on-going with development of more rigorous tests planned for tomorrow.
|
||||
|
||||
|
308
codesizes.txt
Normal file
308
codesizes.txt
Normal file
@ -0,0 +1,308 @@
|
||||
Just file load root file system only, write support disabled in core.
|
||||
main.o 56
|
||||
rtfslfiliord.o 16 4
|
||||
rtfslitecore.o 3 948 40 512
|
||||
rtfstlitefileload.o 420
|
||||
rtfstlitetests.o 152 12 4
|
||||
sys.o 64 4
|
||||
-------------------------------------------------------
|
||||
Total: 4 656 52 520 4
|
||||
Just file load root file system only, write support enabled in core.
|
||||
main.o 64
|
||||
rtfslfiliord.o 16 4
|
||||
rtfslitecore.o 4 388 40 512
|
||||
rtfstlitefileload.o 420
|
||||
rtfstlitetests.o 152 12 4
|
||||
sys.o 64 4
|
||||
-------------------------------------------------------
|
||||
Total: 5 104 52 520 4
|
||||
Everything on include write in filiocore and litecore
|
||||
main.o 64
|
||||
rtfslfileseek.o 276
|
||||
rtfslfilestat.o 164
|
||||
rtfslfiliocore.o 1 164
|
||||
rtfslfiliord.o 312 4 132
|
||||
rtfslgfirst.o 392
|
||||
rtfslitecore.o 4 388 40 512
|
||||
rtfslopenpath.o 500
|
||||
rtfstlitefileload.o 420
|
||||
rtfstlitetests.o 1 060 296 4
|
||||
sys.o 64 4
|
||||
-------------------------------------------------------
|
||||
Total: 8 804 340 648 4
|
||||
Everything on exclude write in filiocore and litecore
|
||||
main.o 56
|
||||
rtfslfileseek.o 276
|
||||
rtfslfilestat.o 164
|
||||
rtfslfiliocore.o 992
|
||||
rtfslfiliord.o 312 4 132
|
||||
rtfslgfirst.o 392
|
||||
rtfslitecore.o 3 948 40 512
|
||||
rtfslopenpath.o 500
|
||||
rtfstlitefileload.o 420
|
||||
rtfstlitetests.o 1 060 296 4
|
||||
sys.o 64 4
|
||||
-------------------------------------------------------
|
||||
Total: 8 184 340 648 4
|
||||
Everything on include write in filiocore and litecore thumb mode
|
||||
main.o 34
|
||||
rtfslfileseek.o 172
|
||||
rtfslfilestat.o 100
|
||||
rtfslfiliocore.o 732
|
||||
rtfslfiliord.o 192 4 132
|
||||
rtfslfiliowr.o 872
|
||||
rtfslgfirst.o 268
|
||||
rtfslitecore.o 2 852 40 512
|
||||
rtfslopenpath.o 306
|
||||
rtfstlitefileload.o 264
|
||||
rtfstlitetests.o 722 308 4
|
||||
sys.o 64 4
|
||||
-------------------------------------------------------
|
||||
Total: 6 578 352 648 4
|
||||
|
||||
Everything on exclude write in filiocore and litecore thumb mode
|
||||
main.o 34
|
||||
rtfslfileseek.o 172
|
||||
rtfslfilestat.o 100
|
||||
rtfslfiliocore.o 624
|
||||
rtfslfiliord.o 192 4 132
|
||||
rtfslfiliowr.o 872
|
||||
rtfslgfirst.o 268
|
||||
rtfslitecore.o 2 554 40 512
|
||||
rtfslopenpath.o 306
|
||||
rtfstlitefileload.o 264
|
||||
rtfstlitetests.o 722 308 4
|
||||
sys.o 64 4
|
||||
-------------------------------------------------------
|
||||
Total: 6 172 352 648 4
|
||||
D:\dev\Projects\IAR\arm\examples\NXP\LPC24xx\IAR-LPC-2478\RtfsLite\Flash Debug\Obj: [1]
|
||||
main.o 30
|
||||
rtfslfiliord.o 12 4
|
||||
rtfslitecore.o 2 554 40 512
|
||||
rtfstlitefileload.o 264
|
||||
rtfstlitetests.o 106 12 4
|
||||
sys.o 64 4
|
||||
-------------------------------------------------------
|
||||
Total: 3 030 52 520 4
|
||||
|
||||
============
|
||||
July 2 .....
|
||||
|
||||
Full build unoptimized
|
||||
------ ------- ------- ------- -------
|
||||
D:\dev\Projects\IAR\arm\examples\NXP\LPC24xx\IAR-LPC-2478\RtfsLite\Flash Debug\Obj: [1]
|
||||
main.o 34
|
||||
rtfslconst.o 44 8
|
||||
rtfsldata.o 8 1 328
|
||||
rtfsldelete.o 200
|
||||
rtfslfailsafe.o 2 212 24
|
||||
rtfslfileseek.o 172
|
||||
rtfslfilestat.o 112
|
||||
rtfslfiliocore.o 1 080
|
||||
rtfslfiliord.o 308
|
||||
rtfslfiliowr.o 1 180
|
||||
rtfslgfirst.o 268
|
||||
rtfslitecore.o 3 480 32
|
||||
rtfslmkdir.o 292
|
||||
rtfslopenpath.o 306
|
||||
rtfslrmdir.o 144
|
||||
rtfsltime.o 20
|
||||
rtfstlitefileload.o 292
|
||||
rtfstlitetests.o 954 568 4
|
||||
sys.o 64 4
|
||||
-------------------------------------------------------
|
||||
Total: 11 118 676 1 340 4
|
||||
1 394 568
|
||||
Adjusted: 9 724 612 1 340 4
|
||||
|
||||
// ===================
|
||||
Full build optimized
|
||||
D:\dev\Projects\IAR\arm\examples\NXP\LPC24xx\IAR-LPC-2478\RtfsLite\Flash Debug\Obj: [1]
|
||||
main.o 30
|
||||
rtfslconst.o 44 8
|
||||
rtfsldata.o 8 1 328
|
||||
rtfsldelete.o 140
|
||||
rtfslfailsafe.o 1 584
|
||||
rtfslfileseek.o 100
|
||||
rtfslfilestat.o 96
|
||||
rtfslfiliocore.o 772
|
||||
rtfslfiliord.o 220
|
||||
rtfslfiliowr.o 928
|
||||
rtfslgfirst.o 236
|
||||
rtfslitecore.o 2 736
|
||||
rtfslmkdir.o 240
|
||||
rtfslopenpath.o 240
|
||||
rtfslrmdir.o 108
|
||||
rtfsltime.o 20
|
||||
rtfstlitefileload.o 220
|
||||
rtfstlitetests.o 1 324 4
|
||||
sys.o 48 4
|
||||
-------------------------------------------------------
|
||||
Total: 9 042 52 1 340 4
|
||||
1 620
|
||||
Adjusted: 7 422 52 1 340 0
|
||||
|
||||
// ===================
|
||||
Full build minus failsafe un-optimized
|
||||
D:\dev\Projects\IAR\arm\examples\NXP\LPC24xx\IAR-LPC-2478\RtfsLite\Flash Debug\Obj: [1]
|
||||
main.o 34
|
||||
rtfslconst.o 44 8
|
||||
rtfsldata.o 8 780
|
||||
rtfsldelete.o 200
|
||||
rtfslfileseek.o 172
|
||||
rtfslfilestat.o 112
|
||||
rtfslfiliocore.o 964
|
||||
rtfslfiliord.o 308
|
||||
rtfslfiliowr.o 1 032
|
||||
rtfslgfirst.o 268
|
||||
rtfslitecore.o 3 332 32
|
||||
rtfslmkdir.o 240
|
||||
rtfslopenpath.o 306
|
||||
rtfslrmdir.o 144
|
||||
rtfsltime.o 20
|
||||
rtfstlitefileload.o 292
|
||||
rtfstlitetests.o 942 568 4
|
||||
sys.o 64 4
|
||||
-------------------------------------------------------
|
||||
Total: 8 430 652 792 4
|
||||
1 332 568
|
||||
Adjusted: 7 098 86 792 0
|
||||
Full build minus failsafe optimized
|
||||
D:\dev\Projects\IAR\arm\examples\NXP\LPC24xx\IAR-LPC-2478\RtfsLite\Flash Debug\Obj: [1]
|
||||
main.o 30
|
||||
rtfslconst.o 44 8
|
||||
rtfsldata.o 8 780
|
||||
rtfsldelete.o 140
|
||||
rtfslfileseek.o 100
|
||||
rtfslfilestat.o 96
|
||||
rtfslfiliocore.o 688
|
||||
rtfslfiliord.o 220
|
||||
rtfslfiliowr.o 824
|
||||
rtfslgfirst.o 236
|
||||
rtfslitecore.o 2 600
|
||||
rtfslmkdir.o 208
|
||||
rtfslopenpath.o 240
|
||||
rtfslrmdir.o 108
|
||||
rtfsltime.o 20
|
||||
rtfstlitefileload.o 220
|
||||
rtfstlitetests.o 1 312 4
|
||||
sys.o 48 4
|
||||
-------------------------------------------------------
|
||||
Total: 7 090 52 792 4
|
||||
1 610
|
||||
Adjusted: 5 480 52 792 0
|
||||
|
||||
Full build minus failsafe, minus subdirectory support optimized
|
||||
main.o 30
|
||||
rtfslconst.o 12
|
||||
rtfsldata.o 8 780
|
||||
rtfsldelete.o 140
|
||||
rtfslfileseek.o 100
|
||||
rtfslfilestat.o 96
|
||||
rtfslfiliocore.o 688
|
||||
rtfslfiliord.o 220
|
||||
rtfslfiliowr.o 824
|
||||
rtfslgfirst.o 236
|
||||
rtfslitecore.o 2 600
|
||||
rtfslopenpath.o 160
|
||||
rtfslrmdir.o 108
|
||||
rtfsltime.o 20
|
||||
rtfstlitefileload.o 220
|
||||
rtfstlitetests.o 1 296 4
|
||||
sys.o 48 0
|
||||
-------------------------------------------------------
|
||||
Total: 6 786 20 784 4
|
||||
1 594 4
|
||||
Adjusted: 5 192 20 780 4
|
||||
|
||||
Full build minus failsafe, minus subdirectory support, minus write support
|
||||
D:\dev\Projects\IAR\arm\examples\NXP\LPC24xx\IAR-LPC-2478\RtfsLite\Flash Debug\Obj: [1]
|
||||
main.o 26
|
||||
rtfslconst.o 12
|
||||
rtfsldata.o 8 780
|
||||
rtfslfileseek.o 100
|
||||
rtfslfilestat.o 96
|
||||
rtfslfiliocore.o 532
|
||||
rtfslfiliord.o 196
|
||||
rtfslgfirst.o 236
|
||||
rtfslitecore.o 2 268
|
||||
rtfslopenpath.o 160
|
||||
rtfstlitefileload.o 220
|
||||
rtfstlitetests.o 916 4
|
||||
sys.o 48 4
|
||||
-------------------------------------------------------
|
||||
Total: 4 798 20 784 4
|
||||
1 210 4
|
||||
Adjusted: 3 588 20 780 0
|
||||
|
||||
Full build minus failsafe, minus subdirectory support, minus write support inus read api, enough to load a file from the root directory into memory
|
||||
D:\dev\Projects\IAR\arm\examples\NXP\LPC24xx\IAR-LPC-2478\RtfsLite\Flash Debug\Obj: [1]
|
||||
main.o 26
|
||||
rtfslconst.o 12
|
||||
rtfsldata.o 532
|
||||
rtfslfiliord.o 12
|
||||
rtfslgfirst.o 236
|
||||
rtfslitecore.o 2 268
|
||||
rtfslopenpath.o 160
|
||||
rtfstlitefileload.o 220
|
||||
rtfstlitetests.o 532 4
|
||||
sys.o 48 4
|
||||
-------------------------------------------------------
|
||||
Total: 3 502 12 536 4
|
||||
606 4
|
||||
Adjusted: 2 896 12 532 0
|
||||
|
||||
The small file system development is going well.
|
||||
|
||||
The currently supported features include:
|
||||
. File io (create,reopen, read,write,seek,delete).
|
||||
. Subdirectory support (mkdir, rmdir and set working directory).
|
||||
. Failsafe journaling and restore support.
|
||||
. All features have been tested both with using Failsafe and not using Failsafe.
|
||||
. All tests have been performed with FAT12 so far, typically the most difficult case.
|
||||
|
||||
Ongoing development efforts include the following:
|
||||
. Tests still need to be performed on FAT16 and FAT32.
|
||||
. Testing is on-going with development of more rigorous tests planned for tomorrow.
|
||||
|
||||
|
||||
. The ram and rom requirements for rtfsl built under various configurations is provided below.
|
||||
=============================================================================================
|
||||
read read read
|
||||
only only write Build
|
||||
code data data description.
|
||||
bytes bytes bytes
|
||||
------- ------- ------- ----------------------
|
||||
9724 52 1340 Full build with failsafe unoptimized
|
||||
10210 52 1340 Full build with failsafe unoptimized after eliminating passing drive structure. (removal of const * optimization to blame, need to re-insert const where possible)
|
||||
7422 52 1340 Full build with failsafe optimized for size
|
||||
7098 86 792 Full build minus failsafe un-optimized
|
||||
5480 52 792 Full build minus failsafe optimized
|
||||
5192 20 780 Full build minus failsafe, minus subdirectory support optimized for size
|
||||
3588 20 780 Read only file io, directory traverasal and file stat functions.
|
||||
2896 12 532 Functionality to load a file from the root directory into memory, optimized for size.
|
||||
|
||||
Full build includes the follow functionality for fat12, fat16 and fat32.:
|
||||
. create a sub-directory in the root or in a subdirectory.
|
||||
. delete a sub-directory
|
||||
. create a file in the root or in a subdirectory.
|
||||
. write to a file.
|
||||
. read from a file.
|
||||
. seek within a file.
|
||||
. close a file.
|
||||
. delete a file
|
||||
When Failsafe support is enabled, the follow functionality is included.
|
||||
. failsafe flush.
|
||||
. failsafe journal of FAT table changes and directory entry changes.
|
||||
. failsafe restore.
|
||||
|
||||
main.o 34
|
||||
rtfstlitefileload.o 216
|
||||
rtfstlitetestfileio.o 744 260
|
||||
rtfstlitetests.o 726 548 532
|
||||
rtfstlitetestutils.o 774 12
|
||||
sys.o 64 4
|
||||
---------------------------------------------------------
|
||||
Total: 12 710 960 1 864 4
|
||||
2 500
|
||||
10 210
|
30
main.c
Normal file
30
main.c
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
#include "rtfslitetests.h"
|
||||
#ifdef __linux__
|
||||
int rtfsl_open_disk(char *raw_dev_name);
|
||||
#endif
|
||||
|
||||
void main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
printf("Usage: %s block_dev_name\n", argv[0]);
|
||||
printf("Usage: You must provide the device name of fat formatted device\n");
|
||||
return;
|
||||
}
|
||||
if (rtfsl_open_disk(argv[1]) < 0)
|
||||
{
|
||||
printf("Could not open device: %s\n", argv[1]);
|
||||
return;
|
||||
}
|
||||
rtfslite_shell();
|
||||
}
|
75
manual.txt
Normal file
75
manual.txt
Normal file
@ -0,0 +1,75 @@
|
||||
|
||||
Table of contents..
|
||||
|
||||
|
||||
Introduction.
|
||||
|
||||
|
||||
Configuration and porting
|
||||
|
||||
|
||||
API
|
||||
|
||||
RTFSL_ERROR_NONE
|
||||
RTFSL_ERROR_ARGS
|
||||
RTFSL_ERROR_CONSISTENCY
|
||||
RTFSL_ERROR_DIR_FULL
|
||||
RTFSL_ERROR_DISK_FULL
|
||||
RTFSL_ERROR_FDALLOC
|
||||
RTFSL_ERROR_FORMAT
|
||||
RTFSL_ERROR_JOURNAL_FULL
|
||||
RTFSL_ERROR_NOTFOUND
|
||||
RTFSL_ERROR_PATH
|
||||
RTFSL_ERROR_EXIST
|
||||
RTFSL_ERROR_TEST
|
||||
/* Recommended device driver error return values, RTFSL does not generate these */
|
||||
RTFSL_ERROR_IO_WRITE_PROTECT
|
||||
RTFSL_ERROR_IO_NO_MEDIA
|
||||
RTFSL_ERROR_IO_ERROR
|
||||
|
||||
|
||||
int rtfslfs_start(void)
|
||||
int rtfslfs_flush(void)
|
||||
int rtfslfs_sync(void)
|
||||
int rtfslfs_restore(void)
|
||||
int rtfsl_delete(unsigned char *name)
|
||||
|
||||
int rtfsl_create(unsigned char *name,unsigned char attribute)
|
||||
int rtfsl_open(unsigned char *name)
|
||||
int rtfsl_close(int fd)
|
||||
int rtfsl_read(int fd, unsigned char *in_buff, int count)
|
||||
long rtfsl_lseek(int fd, long offset, int origin)
|
||||
int rtfsl_write(int fd, unsigned char *in_buff, int count)
|
||||
int rtfsl_fstat(int fd, struct rtfsl_statstructure *pstat)
|
||||
int rtfsl_flush(int fd)
|
||||
|
||||
int rtfsl_diskopen(void)
|
||||
void rtfsl_setpath(unsigned char **pathnamearray)
|
||||
int rtfsl_flush_info_sec(void)
|
||||
int rtfsl_flush_all_buffers(void)
|
||||
|
||||
int rtfsl_gfirst(struct rtfsl_dstat *statobj, unsigned char *name)
|
||||
int rtfsl_gnext(struct rtfsl_dstat *statobj)
|
||||
void rtfsl_done(struct rtfsl_dstat *statobj)
|
||||
|
||||
int rtfsl_enumerate_file(struct rtfsl_file *pfile,FileScanCallback pCallback, void *puser_data)
|
||||
int rtfsl_enumerate_directory(struct rtfsl_file *pdirectory_file,struct rtfsl_file *pcurrent_entry_file,DirScanCallback pCallback, void *puser_data)
|
||||
|
||||
int rtfsl_mkdir(unsigned char *name)
|
||||
int rtfsl_rmdir(unsigned char *name)
|
||||
|
||||
int rtfsl_load_file(unsigned char *filename, unsigned long load_address)
|
||||
|
||||
int rtfsl_read_sector(unsigned long sector, unsigned char *buffer)
|
||||
int rtfsl_write_sector(unsigned long sector, unsigned char *buffer)
|
||||
void rtfsl_get_system_date(unsigned short *time, unsigned short *date)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Application notes
|
||||
|
||||
|
||||
|
14
rtfslconst.c
Normal file
14
rtfslconst.c
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
|
||||
const char *dotname = ". ";
|
||||
const char *dotdotname = ".. ";
|
||||
const unsigned char end_name[11] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
|
16
rtfsldata.c
Normal file
16
rtfsldata.c
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
|
||||
|
||||
struct rtfsl_context rtfsl;
|
||||
unsigned char rtfsl_sector_buffer[RTFSL_CFG_MAXBLOCKSIZE*RTFSL_CFG_NUMBUFFERS];
|
||||
|
||||
|
51
rtfsldelete.c
Normal file
51
rtfsldelete.c
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
|
||||
int rtfsl_delete(unsigned char *name) /*__apifn__*/
|
||||
{
|
||||
return _rtfsl_delete(name,0);
|
||||
}
|
||||
|
||||
int _rtfsl_delete(unsigned char *name,unsigned char attribute)
|
||||
{
|
||||
int fd,rval,offset;
|
||||
rval= _rtfsl_open(name,attribute);
|
||||
if (rval >= 0)
|
||||
{
|
||||
fd=rval;
|
||||
rval=rtfsl_read(fd, 0, rtfsl.rtfsl_files[fd].segment_size_bytes);
|
||||
while (rval>0)
|
||||
{
|
||||
unsigned long cluster,value;
|
||||
value=0;
|
||||
for (offset=0;rtfsl.rtfsl_files[fd].cluster_segment_array[offset][0]&&offset<RTFSL_CFG_FILE_FRAG_BUFFER_SIZE;offset++)
|
||||
{
|
||||
for (cluster = rtfsl.rtfsl_files[fd].cluster_segment_array[offset][0]; cluster <= rtfsl.rtfsl_files[fd].cluster_segment_array[offset][1];cluster++)
|
||||
{
|
||||
rval= fatop_buff_get_frag(cluster|RTFSL_WRITE_CLUSTER, &value, 1);
|
||||
if (rval<0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rval>=0)
|
||||
rval=rtfsl_read(fd, 0, rtfsl.rtfsl_files[fd].segment_size_bytes);
|
||||
}
|
||||
if (rval==0)
|
||||
{
|
||||
rtfsl.rtfsl_files[fd].dos_inode.fname[0]=PCDELETE;
|
||||
rval=rtfsl_flush(fd);
|
||||
}
|
||||
rtfsl.rtfsl_files[fd].rtfsl_file_flags=0; /* Deallocates the file */
|
||||
}
|
||||
return rval;
|
||||
}
|
695
rtfslfailsafe.c
Normal file
695
rtfslfailsafe.c
Normal file
@ -0,0 +1,695 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
#include <stdio.h>
|
||||
#if (RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
|
||||
/* Frame structure
|
||||
1xxx :28:32 = 64 CLUSTER - OPCODE START LENGTH
|
||||
031 :32 = 64 DOSINODE - OPCODE SECTOR INDEX|TABLEINDEX|DELETED
|
||||
*/
|
||||
|
||||
#define DIRENT_RECORD 0x80000000
|
||||
#define DIRENT_SECTOR_MASK 0x7fffffff
|
||||
#define CLUSTER_DELETE_RECORD 0x30000000
|
||||
#define CLUSTER_CHAIN_RECORD 0x20000000
|
||||
#define CLUSTER_TCHAIN_RECORD 0x10000000
|
||||
#define CLUSTER_INSTANCE_RECORD 0x00000000
|
||||
#define CLUSTER_RECORD_MASK 0x30000000
|
||||
#define CLUSTER_VALUE_MASK 0x0fffffff
|
||||
|
||||
#define REPLACEMENTRECORDSTART 1
|
||||
|
||||
#define DELETEEDINODEMARKER 0xfffe
|
||||
|
||||
#define RELATIONSHIP_NONE 0
|
||||
#define RELATIONSHIP_OVERLAP 1
|
||||
#define RELATIONSHIP_ADJACENT_LEFT 2
|
||||
#define RELATIONSHIP_ADJACENT_RIGHT 3
|
||||
int rtfslfs_cluster_map(unsigned long cluster_number,unsigned long value)
|
||||
{
|
||||
int i;
|
||||
int get_next_record;
|
||||
unsigned long cluster_type;
|
||||
char emit_new_record;
|
||||
|
||||
struct rtfsl_failsafe_context *pfs=rtfsl.rtfsl_current_failsafe_context;
|
||||
if (!pfs)
|
||||
return 1;
|
||||
/* We may need up to 3 replacement records, fail if we don't have them */
|
||||
if (pfs->journal_buffer_free < (3*REPLACEMENT_RECORD_SIZE_BYTES))
|
||||
return RTFSL_JOURNALFULL_CLUSTER;
|
||||
|
||||
/* set up default instructions in case we don't overlap a region */
|
||||
emit_new_record=1;
|
||||
if (value==0)
|
||||
{
|
||||
cluster_type = CLUSTER_DELETE_RECORD;
|
||||
value = cluster_number;
|
||||
}
|
||||
else if (value == (rtfsl.current_dr.end_cluster_marker|0xf))
|
||||
{
|
||||
cluster_type = CLUSTER_TCHAIN_RECORD;
|
||||
value = cluster_number;
|
||||
}
|
||||
else if (cluster_number+1 == value)
|
||||
{
|
||||
cluster_type = CLUSTER_CHAIN_RECORD;
|
||||
value = cluster_number;
|
||||
}
|
||||
else
|
||||
{
|
||||
cluster_type = CLUSTER_INSTANCE_RECORD;
|
||||
}
|
||||
//
|
||||
//
|
||||
//REHERE - Add a new state to discard a cluster from all records if it is used.
|
||||
get_next_record=1;
|
||||
for (i = 0; get_next_record && i < (int)*pfs->preplacement_record_count;i++)
|
||||
{
|
||||
unsigned long end_record_cluster,start_record_cluster,record_type;
|
||||
int relationship;
|
||||
char overwrite_current_record,split_current_record,change_start_value,change_end_value,change_record_type;
|
||||
if ((pfs->preplacement_records[i][0]&DIRENT_RECORD)!=0) /* Skip non cluster remap records */
|
||||
continue;
|
||||
|
||||
start_record_cluster=pfs->preplacement_records[i][0]&CLUSTER_VALUE_MASK;
|
||||
record_type=pfs->preplacement_records[i][0]&CLUSTER_RECORD_MASK;
|
||||
if (record_type==CLUSTER_INSTANCE_RECORD)
|
||||
end_record_cluster=start_record_cluster;
|
||||
else
|
||||
end_record_cluster=pfs->preplacement_records[i][1];
|
||||
|
||||
overwrite_current_record=split_current_record=change_start_value=change_end_value=change_record_type=0;
|
||||
if (cluster_number+1 == start_record_cluster)
|
||||
relationship=RELATIONSHIP_ADJACENT_LEFT;
|
||||
else if (cluster_number-1 == end_record_cluster)
|
||||
relationship=RELATIONSHIP_ADJACENT_RIGHT;
|
||||
else if (start_record_cluster<=cluster_number&&end_record_cluster>=cluster_number)
|
||||
relationship=RELATIONSHIP_OVERLAP;
|
||||
else
|
||||
relationship=RELATIONSHIP_NONE;
|
||||
switch (relationship)
|
||||
{
|
||||
case RELATIONSHIP_NONE:
|
||||
default:
|
||||
break;
|
||||
case RELATIONSHIP_ADJACENT_LEFT: /* Cluster is 1 to the left of the region */
|
||||
switch (record_type)
|
||||
{
|
||||
case CLUSTER_TCHAIN_RECORD: /* Cluster is 1 to the left of a terminated chain record */
|
||||
switch (cluster_type)
|
||||
{
|
||||
case CLUSTER_TCHAIN_RECORD:
|
||||
case CLUSTER_INSTANCE_RECORD:
|
||||
case CLUSTER_DELETE_RECORD:
|
||||
default:
|
||||
break;
|
||||
case CLUSTER_CHAIN_RECORD:
|
||||
change_start_value=1; /* Chain cluster immed to left of a terminated chain, set new start of terminated chain to cluster number. */;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CLUSTER_INSTANCE_RECORD: /* Instance record is 1 to the left of a link record, no connection */
|
||||
break;
|
||||
case CLUSTER_DELETE_RECORD: /* Cluster is 1 to the left of an erase record */
|
||||
{
|
||||
switch (cluster_type)
|
||||
{
|
||||
case CLUSTER_TCHAIN_RECORD:
|
||||
case CLUSTER_INSTANCE_RECORD:
|
||||
case CLUSTER_CHAIN_RECORD:
|
||||
default:
|
||||
break;
|
||||
case CLUSTER_DELETE_RECORD:
|
||||
change_start_value=1; /* delete cluster immed to left of a deleted chain, set new start of deleted chain to cluster number. */;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CLUSTER_CHAIN_RECORD: /* Cluster is 1 to the left of a chain record */
|
||||
{
|
||||
switch (cluster_type)
|
||||
{
|
||||
case CLUSTER_TCHAIN_RECORD:
|
||||
case CLUSTER_INSTANCE_RECORD:
|
||||
case CLUSTER_DELETE_RECORD:
|
||||
default:
|
||||
break;
|
||||
case CLUSTER_CHAIN_RECORD:
|
||||
change_start_value=1; /* Chain cluster immed to left of a chain, set new start of chain to cluster number. */;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case RELATIONSHIP_ADJACENT_RIGHT: /* Cluster is 1 to the right of the region */
|
||||
switch (record_type)
|
||||
{
|
||||
case CLUSTER_TCHAIN_RECORD: /* Cluster is 1 to the right of a terminator record, no connection */
|
||||
case CLUSTER_INSTANCE_RECORD: /* Cluster is 1 to the right of a link record, no connection */
|
||||
default:
|
||||
break;
|
||||
case CLUSTER_DELETE_RECORD: /* Cluster is 1 to the right of an erase record */
|
||||
{
|
||||
switch (cluster_type)
|
||||
{
|
||||
case CLUSTER_TCHAIN_RECORD:
|
||||
case CLUSTER_INSTANCE_RECORD:
|
||||
case CLUSTER_CHAIN_RECORD:
|
||||
break;
|
||||
case CLUSTER_DELETE_RECORD:
|
||||
change_end_value=1; /* delete cluster immed to right of a deleted region, set new end of deleted chain to cluster number. */;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CLUSTER_CHAIN_RECORD: /* Cluster is 1 to the right of the chain region */
|
||||
{
|
||||
switch (cluster_type)
|
||||
{
|
||||
case CLUSTER_INSTANCE_RECORD:
|
||||
case CLUSTER_DELETE_RECORD:
|
||||
default:
|
||||
break;
|
||||
case CLUSTER_TCHAIN_RECORD:
|
||||
change_record_type=1; /* Append a tchain to a chain so change type, fall through to change end */
|
||||
case CLUSTER_CHAIN_RECORD:
|
||||
change_end_value=1; /* Chain cluster immed to right of a chain, set new end of chain to cluster number. */;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case RELATIONSHIP_OVERLAP: /* Cluster overlaps the region */
|
||||
switch (record_type)
|
||||
{
|
||||
case CLUSTER_TCHAIN_RECORD:
|
||||
{
|
||||
switch (cluster_type)
|
||||
{
|
||||
case CLUSTER_TCHAIN_RECORD: /* terminate cluster overlaps a terminated chain, split the record into 2 terminated chains and don't emit a new record */
|
||||
{
|
||||
if (cluster_number==end_record_cluster)
|
||||
{
|
||||
/* Writing a terminator at the current end of a terminated chain is a no-op */
|
||||
get_next_record=0;
|
||||
emit_new_record=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
split_current_record=1; /* terminate cluster overlaps a terminated chain, split into two terminated chains no need to emit a new record */
|
||||
emit_new_record=0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CLUSTER_INSTANCE_RECORD: /* link cluster overlaps a terminated chain */
|
||||
case CLUSTER_DELETE_RECORD: /* erase cluster overlaps a terminated chain */
|
||||
{
|
||||
split_current_record=1; /* Split current record in two and emit a new record where the hole is */
|
||||
}
|
||||
break;
|
||||
case CLUSTER_CHAIN_RECORD: /* chain cluster overlaps a terminated chain */
|
||||
{
|
||||
if (cluster_number==end_record_cluster)
|
||||
{
|
||||
change_record_type=1; /* End of a terminated chain record is now a chain, change to a chain record and return */;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A chain cluster overlapping a tchain in the middle is a no-op */
|
||||
get_next_record=0;
|
||||
emit_new_record=0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CLUSTER_INSTANCE_RECORD: /* The record is a one cluster instance record and they overlap, force an overwrite of the record with the current cluster */
|
||||
{
|
||||
overwrite_current_record=1;
|
||||
break;
|
||||
}
|
||||
case CLUSTER_DELETE_RECORD: /* The record is an erase and they overlap */
|
||||
{
|
||||
switch (cluster_type)
|
||||
{
|
||||
case CLUSTER_TCHAIN_RECORD:
|
||||
case CLUSTER_CHAIN_RECORD:
|
||||
case CLUSTER_INSTANCE_RECORD:
|
||||
{
|
||||
split_current_record=1;
|
||||
}
|
||||
break;
|
||||
case CLUSTER_DELETE_RECORD:
|
||||
get_next_record=0;
|
||||
emit_new_record=0;
|
||||
get_next_record=0;
|
||||
/* Already erased.. is a no-op */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CLUSTER_CHAIN_RECORD: /* The record i a chain and they overlap */
|
||||
{
|
||||
switch (cluster_type)
|
||||
{
|
||||
case CLUSTER_TCHAIN_RECORD:
|
||||
{
|
||||
if (cluster_number==end_record_cluster)
|
||||
{
|
||||
change_record_type=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
split_current_record=1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CLUSTER_DELETE_RECORD:
|
||||
case CLUSTER_INSTANCE_RECORD:
|
||||
{
|
||||
split_current_record=1;
|
||||
}
|
||||
break;
|
||||
case CLUSTER_CHAIN_RECORD:
|
||||
emit_new_record=0;
|
||||
/* A chain overlapping a chain is a no-op */
|
||||
get_next_record=0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (change_record_type)
|
||||
{
|
||||
pfs->preplacement_records[i][0]=cluster_type|(pfs->preplacement_records[i][0]&CLUSTER_VALUE_MASK);
|
||||
emit_new_record=0;
|
||||
get_next_record=0;
|
||||
}
|
||||
if (change_start_value)
|
||||
{
|
||||
pfs->preplacement_records[i][0]=cluster_number|(pfs->preplacement_records[i][0]&CLUSTER_RECORD_MASK);
|
||||
emit_new_record=0;
|
||||
get_next_record=0;
|
||||
}
|
||||
if (change_end_value)
|
||||
{
|
||||
pfs->preplacement_records[i][1]=cluster_number;
|
||||
emit_new_record=0;
|
||||
get_next_record=0;
|
||||
}
|
||||
/* Overwrite the current record if instructed or if we are inserting a new record between
|
||||
the start and end of a record that is only one cluster long */
|
||||
if (overwrite_current_record||(split_current_record&&(end_record_cluster==start_record_cluster)))
|
||||
{
|
||||
pfs->preplacement_records[i][0]=start_record_cluster|cluster_type;
|
||||
pfs->preplacement_records[i][1]=value;
|
||||
split_current_record=0;
|
||||
emit_new_record=0;
|
||||
get_next_record=0;
|
||||
}
|
||||
/* We are splitting a record in two. If emit_new_record is non zero we need to remove one cluster from the range that
|
||||
we are splitting. If emit_new_record is non zero we know that the start and end are not the same. */
|
||||
if (split_current_record)
|
||||
{
|
||||
get_next_record=0;
|
||||
/* Copy the record we are going to split into the next free record slot, don't reserve it yet */
|
||||
*pfs->preplacement_records[*pfs->preplacement_record_count]=*pfs->preplacement_records[i];
|
||||
|
||||
if (emit_new_record)
|
||||
{
|
||||
if (cluster_number==start_record_cluster)
|
||||
{ /* We're overwriting the first cluster in a range, don't split it just move the start, let emit create a new record */
|
||||
pfs->preplacement_records[i][0]=(start_record_cluster+1)|(pfs->preplacement_records[i][0]&CLUSTER_RECORD_MASK);
|
||||
}
|
||||
else
|
||||
{ /* We're overwriting a cluster in the range, it isn't the first cluster and the range is > 1, split the range */
|
||||
/* Change the end of the original record */
|
||||
pfs->preplacement_records[i][1]=cluster_number-1;
|
||||
/* If the original record was a tchain make it a chain */
|
||||
if (record_type==CLUSTER_TCHAIN_RECORD)
|
||||
{
|
||||
pfs->preplacement_records[i][0]=CLUSTER_CHAIN_RECORD|(pfs->preplacement_records[i][0]&CLUSTER_VALUE_MASK);
|
||||
}
|
||||
/* If we are at the end, don't split, the emit further down will creat the new record */
|
||||
if (cluster_number==end_record_cluster)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{ /* Consume the cloned record, for the fragment of the region after the cluster we carved out. Just change the start point */
|
||||
pfs->preplacement_records[*pfs->preplacement_record_count][0]=(start_record_cluster+1)|(pfs->preplacement_records[*pfs->preplacement_record_count][0]&CLUSTER_RECORD_MASK);
|
||||
*pfs->preplacement_record_count= *pfs->preplacement_record_count + 1;
|
||||
pfs->journal_buffer_free -= REPLACEMENT_RECORD_SIZE_BYTES;
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* We splitting a record but not taking a cluster away */
|
||||
{
|
||||
if (cluster_number==start_record_cluster)
|
||||
{ /* We're splitting at the start of a range, terminate the old record at the start */
|
||||
pfs->preplacement_records[i][1]=cluster_number;
|
||||
/* Consume the cloned record, for the fragment of the region after the cluster we carved out. Just change the start point */
|
||||
pfs->preplacement_records[*pfs->preplacement_record_count][0]=(cluster_number+1)|(pfs->preplacement_records[*pfs->preplacement_record_count][0]&CLUSTER_RECORD_MASK);
|
||||
}
|
||||
else
|
||||
{ /* We're splitting but not at the start of a range, terminate the old record at the cluster - 1 */
|
||||
pfs->preplacement_records[i][1]=cluster_number-1;
|
||||
pfs->preplacement_records[*pfs->preplacement_record_count][0]=(cluster_number)|(pfs->preplacement_records[*pfs->preplacement_record_count][0]&CLUSTER_RECORD_MASK);
|
||||
}
|
||||
/* If the original record was a tchain make it a chain */
|
||||
if (record_type==CLUSTER_TCHAIN_RECORD)
|
||||
{
|
||||
pfs->preplacement_records[i][0]=CLUSTER_CHAIN_RECORD|(pfs->preplacement_records[i][0]&CLUSTER_VALUE_MASK);
|
||||
}
|
||||
*pfs->preplacement_record_count= *pfs->preplacement_record_count + 1;
|
||||
pfs->journal_buffer_free -= REPLACEMENT_RECORD_SIZE_BYTES;
|
||||
}
|
||||
}
|
||||
} /* End for loop */
|
||||
if (emit_new_record)
|
||||
{ /* or one past if we are making a hole */
|
||||
pfs->preplacement_records[*pfs->preplacement_record_count][0]= cluster_number|cluster_type;
|
||||
pfs->preplacement_records[*pfs->preplacement_record_count][1]= value;
|
||||
*pfs->preplacement_record_count= *pfs->preplacement_record_count + 1;
|
||||
pfs->journal_buffer_free -= REPLACEMENT_RECORD_SIZE_BYTES;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long rtfslfs_cluster_remap(unsigned long cluster,unsigned long value)
|
||||
{
|
||||
int i;
|
||||
unsigned long new_instance_cluster,new_delete_start,new_chain_start,new_instance_value,new_chain_end,new_delete_end;
|
||||
struct rtfsl_failsafe_context *pfs=rtfsl.rtfsl_current_failsafe_context;
|
||||
if (!pfs)
|
||||
return value;
|
||||
new_delete_start=new_chain_start=new_instance_cluster=new_delete_end=new_chain_end=new_instance_value=0;
|
||||
|
||||
|
||||
for (i = 0; i < (int)*pfs->preplacement_record_count;i++)
|
||||
{
|
||||
unsigned long cluster_record_type;
|
||||
unsigned long end_record_cluster,start_record_cluster;
|
||||
|
||||
if ((pfs->preplacement_records[i][0]&DIRENT_RECORD)!=0) /* Skip non cluster remap records */
|
||||
continue;
|
||||
start_record_cluster=pfs->preplacement_records[i][0]&CLUSTER_VALUE_MASK;
|
||||
cluster_record_type=pfs->preplacement_records[i][0]&CLUSTER_RECORD_MASK;
|
||||
if (cluster_record_type==CLUSTER_INSTANCE_RECORD)
|
||||
end_record_cluster=start_record_cluster;
|
||||
else
|
||||
end_record_cluster=pfs->preplacement_records[i][1];
|
||||
if (cluster<start_record_cluster) /* No relationship */
|
||||
continue;
|
||||
if (cluster_record_type==CLUSTER_INSTANCE_RECORD)
|
||||
{
|
||||
if (start_record_cluster==cluster)
|
||||
return pfs->preplacement_records[i][1];
|
||||
}
|
||||
else
|
||||
{ /* It a delete, chain or tchain */
|
||||
if (start_record_cluster<=cluster&&end_record_cluster>=cluster)
|
||||
{
|
||||
if (cluster_record_type==CLUSTER_DELETE_RECORD)
|
||||
return RTFSL_JOURNALDELETED_CLUSTER;
|
||||
/* It's either a tchain or a chain */
|
||||
/* last cluster of a tchain is chain terminator */
|
||||
if (cluster_record_type==CLUSTER_TCHAIN_RECORD && end_record_cluster==cluster)
|
||||
return rtfsl.current_dr.end_cluster_marker|0xf;
|
||||
else
|
||||
return cluster+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Fall through and return the unmapped value */
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
int rtfslfs_dirent_remap(unsigned long sector,unsigned long index, struct rtfsl_dosinode *p_dos_inode,int reading)
|
||||
{
|
||||
struct rtfsl_failsafe_context *pfs=rtfsl.rtfsl_current_failsafe_context;
|
||||
int replacement_record_index=-1;
|
||||
int remap_index=0;
|
||||
if (pfs)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < (int)*pfs->preplacement_record_count;i++)
|
||||
{
|
||||
if ((pfs->preplacement_records[i][0]&DIRENT_RECORD)==0) /* Skip non dirent remap records */
|
||||
continue;
|
||||
if ((pfs->preplacement_records[i][0]&DIRENT_SECTOR_MASK)==sector)
|
||||
{
|
||||
if ((pfs->preplacement_records[i][1]&0x0000ffff)==index)
|
||||
{
|
||||
unsigned long remap_index = pfs->preplacement_records[i][1]>>16;
|
||||
if (reading)
|
||||
{
|
||||
if (remap_index == DELETEEDINODEMARKER)
|
||||
p_dos_inode->fname[0]=PCDELETE;
|
||||
else
|
||||
ANSImemcpy(p_dos_inode, pfs->journal_buffer+remap_index,REPLACEMENT_DOSINODESIZE_SIZE_BYTES);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p_dos_inode->fname[0]==PCDELETE)
|
||||
{ /* Mark the dosinode deleted. we can't reclaim the dossinode space in the buffer but it will be ignored */
|
||||
pfs->preplacement_records[i][1]= (unsigned long)(DELETEEDINODEMARKER)<<16|(unsigned long)index;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (remap_index != DELETEEDINODEMARKER)
|
||||
{
|
||||
ANSImemcpy(pfs->journal_buffer+remap_index, p_dos_inode,REPLACEMENT_DOSINODESIZE_SIZE_BYTES);
|
||||
return 1;
|
||||
}
|
||||
/* We found a record for the dossinode but its flagged deleted and we need to copy record in place */
|
||||
replacement_record_index=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (reading)
|
||||
return 0;
|
||||
/* If we get here we have to allocate a records */
|
||||
{
|
||||
int bytes_needed=0;
|
||||
if (p_dos_inode->fname[0]!=PCDELETE)
|
||||
bytes_needed+=REPLACEMENT_DOSINODESIZE_SIZE_BYTES;
|
||||
if (replacement_record_index<0)
|
||||
bytes_needed+=REPLACEMENT_RECORD_SIZE_BYTES;
|
||||
if (pfs->journal_buffer_free < bytes_needed)
|
||||
return RTFSL_ERROR_JOURNAL_FULL;
|
||||
}
|
||||
if (p_dos_inode->fname[0]==PCDELETE)
|
||||
remap_index=DELETEEDINODEMARKER;
|
||||
else
|
||||
{
|
||||
*pfs->pcurrent_dosinode_offset-=REPLACEMENT_DOSINODESIZE_SIZE_BYTES;
|
||||
pfs->journal_buffer_free-=REPLACEMENT_DOSINODESIZE_SIZE_BYTES;
|
||||
remap_index=(int)*pfs->pcurrent_dosinode_offset;
|
||||
ANSImemcpy(pfs->journal_buffer+remap_index,p_dos_inode,REPLACEMENT_DOSINODESIZE_SIZE_BYTES);
|
||||
}
|
||||
if (replacement_record_index<0)
|
||||
{
|
||||
replacement_record_index=*pfs->preplacement_record_count;
|
||||
*pfs->preplacement_record_count= *pfs->preplacement_record_count + 1;
|
||||
}
|
||||
pfs->preplacement_records[replacement_record_index][0]=sector|DIRENT_RECORD;
|
||||
pfs->preplacement_records[replacement_record_index][1]=remap_index<<16|index;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* Format of the buffer: replacement_record_count|replacement_records|->growsup Grows down<-dosinode1|dosinode0|]*/
|
||||
int rtfslfs_start(void) /*__apifn__*/
|
||||
{
|
||||
int rval;
|
||||
struct rtfsl_failsafe_context *pfs;
|
||||
|
||||
pfs=rtfsl.rtfsl_current_failsafe_context=&rtfsl.rtfsl_failsafe_context;
|
||||
ANSImemset(rtfsl.rtfsl_current_failsafe_context,0,sizeof(*rtfsl.rtfsl_current_failsafe_context));
|
||||
rtfsl.rtfsl_current_failsafe_context->journal_buffer=rtfsl.rtfslfs_sector_buffer;
|
||||
rtfsl.rtfsl_current_failsafe_context->journal_buffer_size=RTFSL_CFG_FSBUFFERSIZEBYTES;
|
||||
rval=rtfslfs_access_journal(RTFSLFS_JTEST);
|
||||
if (rval==0)
|
||||
{
|
||||
pfs->preplacement_record_count=(unsigned long *) pfs->journal_buffer;
|
||||
pfs->pcurrent_dosinode_offset=(unsigned long *) (pfs->journal_buffer+4);
|
||||
pfs->preplacement_records = (treplacement_record *) (pfs->journal_buffer+8);
|
||||
*pfs->pcurrent_dosinode_offset=pfs->journal_buffer_size;
|
||||
*pfs->preplacement_record_count=0;
|
||||
pfs->journal_buffer_free = pfs->journal_buffer_size-8;
|
||||
/*
|
||||
For reload..
|
||||
pfs->journal_buffer_free = (pfs->journal_buffer_size-8-( (*pfs->preplacement_record_count*8)+ pfs->journal_buffer_size-*pfs->pcurrent_dosinode_offset) );
|
||||
*/
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
int rtfslfs_flush(void) /*__apifn__*/
|
||||
{
|
||||
int rval;
|
||||
rval=rtfsl_flush_info_sec();
|
||||
if (rval==0)
|
||||
rval=rtfslfs_access_journal(RTFSLFS_JWRITE);
|
||||
return rval;
|
||||
}
|
||||
|
||||
static int _rtfslfs_sync(void);
|
||||
int rtfslfs_sync(void) /*__apifn__*/
|
||||
{
|
||||
int rval;
|
||||
rval=_rtfslfs_sync();
|
||||
if (rval==0)
|
||||
rval=rtfslfs_start();
|
||||
return rval;
|
||||
}
|
||||
|
||||
int rtfslfs_restore(void) /*__apifn__*/
|
||||
{
|
||||
int rval=0;
|
||||
rval=rtfslfs_start(); /* Initialize offset, pointers etc. */
|
||||
if (rval==0)
|
||||
{
|
||||
rval=rtfslfs_access_journal(RTFSLFS_JREAD); /* read the journal */
|
||||
if (rval==0)
|
||||
rval=_rtfslfs_sync();
|
||||
}
|
||||
if (rval==0)
|
||||
rval=rtfsl_diskopen();
|
||||
return rval;
|
||||
}
|
||||
|
||||
static int _rtfslfs_sync(void)
|
||||
{
|
||||
int rval=0;
|
||||
struct rtfsl_failsafe_context *pfs=rtfsl.rtfsl_current_failsafe_context;
|
||||
if (pfs)
|
||||
{
|
||||
unsigned char *b=0;
|
||||
struct rtfsl_dosinode *p_dos_inode;
|
||||
unsigned long sector,offset,index;
|
||||
int replacement_record_index;
|
||||
int buffernumber;
|
||||
/* null out the failsafe context pointer so the cluster routines go to the volume, not the journal */
|
||||
rtfsl.rtfsl_current_failsafe_context=0;
|
||||
|
||||
for (replacement_record_index=0;replacement_record_index<(int)*pfs->preplacement_record_count;replacement_record_index++)
|
||||
{
|
||||
if (pfs->preplacement_records[replacement_record_index][0]&DIRENT_RECORD)
|
||||
sector=pfs->preplacement_records[replacement_record_index][0]&DIRENT_SECTOR_MASK;
|
||||
else
|
||||
sector=0;
|
||||
if (pfs->preplacement_records[replacement_record_index][0]&DIRENT_RECORD)
|
||||
{
|
||||
index = pfs->preplacement_records[replacement_record_index][1]&0x0000ffff;
|
||||
offset = pfs->preplacement_records[replacement_record_index][1]>>16;
|
||||
buffernumber=rtfsl_read_sector_buffer(sector);
|
||||
if (buffernumber<0)
|
||||
return buffernumber;
|
||||
b = rtfsl_buffer_address(buffernumber);
|
||||
p_dos_inode = (struct rtfsl_dosinode *) b;
|
||||
p_dos_inode += index;
|
||||
if (offset == DELETEEDINODEMARKER && p_dos_inode->fname[0]!=PCDELETE)
|
||||
{
|
||||
p_dos_inode->fname[0]=PCDELETE;
|
||||
rtfsl_mark_sector_buffer(buffernumber); /* Mark the buffer dirty */
|
||||
}
|
||||
#if (RTFSL_INCLUDE_FAT32)
|
||||
else if (sector==rtfsl.current_dr.infosec)
|
||||
{
|
||||
unsigned long *pl= (unsigned long *)p_dos_inode;
|
||||
pl++;
|
||||
rtfsl.current_dr.free_alloc=*pl++;
|
||||
rtfsl.current_dr.next_alloc=*pl;
|
||||
rtfsl.current_dr.flags|=RTFSL_FAT_CHANGED_FLAG;
|
||||
rval=rtfsl_flush_info_sec();
|
||||
if (rval<0)
|
||||
return rval;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
if (ANSImemcmp(p_dos_inode,pfs->journal_buffer+offset,REPLACEMENT_DOSINODESIZE_SIZE_BYTES)!=0)
|
||||
{
|
||||
ANSImemcpy(p_dos_inode,pfs->journal_buffer+offset,REPLACEMENT_DOSINODESIZE_SIZE_BYTES);
|
||||
rtfsl_mark_sector_buffer(buffernumber); /* Mark the buffer dirty */
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long cluster_record_type,end_record_cluster,current_cluster,value;
|
||||
current_cluster=pfs->preplacement_records[replacement_record_index][0]&CLUSTER_VALUE_MASK;
|
||||
cluster_record_type=pfs->preplacement_records[replacement_record_index][0]&CLUSTER_RECORD_MASK;
|
||||
end_record_cluster=pfs->preplacement_records[replacement_record_index][1];
|
||||
if (cluster_record_type==CLUSTER_DELETE_RECORD)
|
||||
{
|
||||
value=0;
|
||||
do {
|
||||
rval=fatop_buff_get_frag(current_cluster|RTFSL_WRITE_CLUSTER, &value, 1);
|
||||
} while(rval==0 && current_cluster++<end_record_cluster);
|
||||
}
|
||||
else if (cluster_record_type==CLUSTER_INSTANCE_RECORD)
|
||||
{
|
||||
value=end_record_cluster;
|
||||
rval=fatop_buff_get_frag(current_cluster|RTFSL_WRITE_CLUSTER, &value, 1);
|
||||
}
|
||||
else /* if (cluster_record_type==CLUSTER_CHAIN_RECORD)||cluster_record_type==CLUSTER_TCHAIN_RECORD */
|
||||
{
|
||||
value=current_cluster+1;
|
||||
while (rval==0 && current_cluster!=end_record_cluster)
|
||||
{
|
||||
rval=fatop_buff_get_frag(current_cluster|RTFSL_WRITE_CLUSTER, &value, 1);
|
||||
value+=1;
|
||||
current_cluster+=1;
|
||||
};
|
||||
if (cluster_record_type==CLUSTER_TCHAIN_RECORD)
|
||||
value = rtfsl.current_dr.end_cluster_marker|0xf;
|
||||
if (rval==0)
|
||||
rval=fatop_buff_get_frag(current_cluster|RTFSL_WRITE_CLUSTER, &value, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rval==0)
|
||||
rval=rtfsl_flush_all_buffers();
|
||||
if (rval==0 && *pfs->preplacement_record_count)
|
||||
{
|
||||
rtfsl.rtfsl_current_failsafe_context=pfs;
|
||||
rtfslfs_access_journal(RTFSLFS_JCLEAR);
|
||||
rtfsl.rtfsl_current_failsafe_context=0;
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
#endif
|
48
rtfslfileseek.c
Normal file
48
rtfslfileseek.c
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
|
||||
static unsigned long file_seek_callback (struct rtfsl_file const *pfile, unsigned long start_sector, unsigned long nbytes, void *puser_data)
|
||||
{
|
||||
unsigned long target = (unsigned long) puser_data;
|
||||
if (pfile->file_pointer+nbytes > target)
|
||||
return target-pfile->file_pointer;
|
||||
else
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
long rtfsl_lseek(int fd, long offset, int origin) /*__apifn__*/
|
||||
{
|
||||
unsigned long target_fp;
|
||||
int rval;
|
||||
if (origin == PSEEK_SET) /* offset from beginning of file */
|
||||
{
|
||||
target_fp = (unsigned long)offset;
|
||||
}
|
||||
else if (origin == PSEEK_CUR) /* offset from current file pointer */
|
||||
{
|
||||
target_fp=rtfsl.rtfsl_files[fd].file_pointer+offset;
|
||||
}
|
||||
else if (origin == PSEEK_END) /* offset from end of file */
|
||||
{
|
||||
if (offset>0)
|
||||
return RTFSL_ERROR_ARGS;
|
||||
target_fp=rtfsl.rtfsl_files[fd].dos_inode.fsize+offset;
|
||||
}
|
||||
else
|
||||
return RTFSL_ERROR_ARGS;
|
||||
rval=rtfsl_enumerate_file(&rtfsl.rtfsl_files[fd],file_seek_callback, (void *) target_fp);
|
||||
if (rval<0)
|
||||
return (long)rval;
|
||||
if (rtfsl.rtfsl_files[fd].file_pointer!=target_fp)
|
||||
return RTFSL_ERROR_CONSISTENCY;
|
||||
else
|
||||
return (long) rtfsl.rtfsl_files[fd].file_pointer;
|
||||
}
|
24
rtfslfilestat.c
Normal file
24
rtfslfilestat.c
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
|
||||
int rtfsl_fstat(int fd, struct rtfsl_statstructure *pstat) /*__apifn__*/
|
||||
{
|
||||
ANSImemset(pstat,0,sizeof(*pstat));
|
||||
pstat->st_size = rtfsl.rtfsl_files[fd].dos_inode.fsize;
|
||||
pstat->fattribute= rtfsl.rtfsl_files[fd].dos_inode.fattribute;
|
||||
pstat->st_atime = rtfsl.rtfsl_files[fd].dos_inode.adate<<16;
|
||||
pstat->st_mtime = rtfsl.rtfsl_files[fd].dos_inode.fdate<<16|rtfsl.rtfsl_files[fd].dos_inode.ftime;
|
||||
pstat->st_ctime = rtfsl.rtfsl_files[fd].dos_inode.cdate<<16|rtfsl.rtfsl_files[fd].dos_inode.ctime;
|
||||
pstat->st_blocks = (pstat->st_size+rtfsl.current_dr.bytespsector-1)/rtfsl.current_dr.bytespsector;
|
||||
pstat->st_blocks = rtfsl.current_dr.bytespcluster;
|
||||
return(0);
|
||||
|
||||
}
|
202
rtfslfiliocore.c
Normal file
202
rtfslfiliocore.c
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
|
||||
static long rtfsl_map_region_clusterwindow(int fd,unsigned long file_pointer, unsigned long *sector, unsigned long *offset)
|
||||
{
|
||||
int region;
|
||||
unsigned long startcluster,file_pointer_past_segment_end,file_pointer_at_region_base,file_pointer_past_region_end;
|
||||
/* */
|
||||
*offset = file_pointer%rtfsl.current_dr.bytespsector;
|
||||
if (rtfsl.rtfsl_files[fd].rtfsl_file_flags & TRTFSFILE_SECTOR_REGION )
|
||||
{
|
||||
*sector = rtfsl.rtfsl_files[fd].cluster_segment_array[0][0]+file_pointer/rtfsl.current_dr.bytespsector;
|
||||
return (rtfsl.rtfsl_files[fd].cluster_segment_array[0][1]-rtfsl.rtfsl_files[fd].cluster_segment_array[0][0])*rtfsl.current_dr.bytespsector-file_pointer;
|
||||
}
|
||||
startcluster=0;
|
||||
file_pointer_past_segment_end=rtfsl.rtfsl_files[fd].file_pointer_at_segment_base+rtfsl.rtfsl_files[fd].segment_size_bytes;
|
||||
if (file_pointer >= file_pointer_past_segment_end)
|
||||
{
|
||||
startcluster = rtfsl.rtfsl_files[fd].next_segment_base;
|
||||
}
|
||||
else if (file_pointer >= rtfsl.rtfsl_files[fd].file_pointer_at_segment_base) /* Scan up from current */
|
||||
startcluster = rtfsl.rtfsl_files[fd].cluster_segment_array[0][0];
|
||||
|
||||
if (!startcluster)
|
||||
{
|
||||
startcluster = to_USHORT((unsigned char *)& rtfsl.rtfsl_files[fd].dos_inode.fclusterhi);
|
||||
startcluster <<= 16;
|
||||
startcluster |= to_USHORT((unsigned char *)& rtfsl.rtfsl_files[fd].dos_inode.fcluster);
|
||||
rtfsl.rtfsl_files[fd].segment_size_bytes=0;
|
||||
rtfsl.rtfsl_files[fd].file_pointer_at_segment_base=0;
|
||||
}
|
||||
while (file_pointer >= file_pointer_past_segment_end)
|
||||
{
|
||||
long rval;
|
||||
rval=rtfsl_load_next_segment(&rtfsl.rtfsl_files[fd],startcluster);
|
||||
if (rval<=0)
|
||||
return rval;
|
||||
file_pointer_past_segment_end=rtfsl.rtfsl_files[fd].file_pointer_at_segment_base+rtfsl.rtfsl_files[fd].segment_size_bytes;
|
||||
startcluster=0;
|
||||
}
|
||||
file_pointer_at_region_base=file_pointer_past_region_end=rtfsl.rtfsl_files[fd].file_pointer_at_segment_base;
|
||||
for(region=0; region < RTFSL_CFG_FILE_FRAG_BUFFER_SIZE && rtfsl.rtfsl_files[fd].cluster_segment_array[region][0];region++)
|
||||
{
|
||||
unsigned long region_length;
|
||||
region_length = (rtfsl.rtfsl_files[fd].cluster_segment_array[region][1]-rtfsl.rtfsl_files[fd].cluster_segment_array[region][0]+1)*rtfsl.current_dr.bytespcluster;
|
||||
|
||||
file_pointer_past_region_end += region_length;
|
||||
if (file_pointer_past_region_end>file_pointer)
|
||||
{
|
||||
*sector = rtfsl_cl2sector(rtfsl.rtfsl_files[fd].cluster_segment_array[region][0])+(file_pointer-file_pointer_at_region_base)/rtfsl.current_dr.bytespsector;
|
||||
return file_pointer_past_region_end-file_pointer;
|
||||
}
|
||||
file_pointer_at_region_base += region_length;
|
||||
|
||||
}
|
||||
return RTFSL_ERROR_CONSISTENCY;
|
||||
}
|
||||
|
||||
#if (RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
static int _rtfsl_journal_io(unsigned long sector, int index, unsigned char *pdata, long n_bytes)
|
||||
{
|
||||
int rval;
|
||||
long copied;
|
||||
for (copied=0; copied<n_bytes;copied+=32,index++,pdata+=32)
|
||||
{
|
||||
rval=rtfslfs_dirent_remap(sector,index, (struct rtfsl_dosinode *) pdata,0);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
long _rtfsl_bfilio_io(int fd, unsigned char *pdata, long n_bytes, unsigned char opflags)
|
||||
{
|
||||
long n_left,copied,count_inregion;
|
||||
unsigned long file_pointer; // ,region_byte_next,file_region_byte_base, file_region_block_base;
|
||||
unsigned long sector,residual,offset;
|
||||
int rval=0;
|
||||
/* use local copies of file info so if we fail the pointers will not advance */
|
||||
file_pointer = rtfsl.rtfsl_files[fd].file_pointer;
|
||||
n_left = n_bytes;
|
||||
sector=count_inregion=residual=offset=0;
|
||||
|
||||
|
||||
while (n_left)
|
||||
{
|
||||
if (!residual)
|
||||
{
|
||||
count_inregion = rtfsl_map_region_clusterwindow(fd, file_pointer, §or, &offset);
|
||||
if (count_inregion<0)
|
||||
return count_inregion;
|
||||
if (count_inregion==0)
|
||||
break;
|
||||
if (count_inregion > n_left)
|
||||
count_inregion = n_left;
|
||||
}
|
||||
if (residual||offset)
|
||||
{
|
||||
unsigned char *p;
|
||||
int startcopyfr;
|
||||
if (offset)
|
||||
{
|
||||
/* If reading and writing are enabled use opflags to ccheck for write */
|
||||
copied=rtfsl.current_dr.bytespsector-offset;
|
||||
startcopyfr=(int)offset;
|
||||
offset=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
copied=residual;
|
||||
startcopyfr=0;
|
||||
}
|
||||
if (copied > n_left)
|
||||
copied = n_left;
|
||||
if (pdata)
|
||||
{
|
||||
int buffernumber=rtfsl_read_sector_buffer(rtfsl.current_dr.partition_base+sector);
|
||||
if (buffernumber<0)
|
||||
return buffernumber;
|
||||
p = rtfsl_buffer_address(buffernumber);
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT)
|
||||
if (opflags & RTFSL_FIO_OP_WRITE)
|
||||
{
|
||||
if (rtfsl.rtfsl_files[fd].rtfsl_file_flags&TRTFSFILE_ISMKDIR)
|
||||
{
|
||||
struct rtfsl_dosinode *pdos_inode=(struct rtfsl_dosinode *)pdata;
|
||||
unsigned short w;
|
||||
unsigned long cl=rtfsl_sec2cluster(rtfsl.rtfsl_files[fd].sector);
|
||||
/* "." points to self */
|
||||
pdos_inode->fclusterhi=rtfsl.rtfsl_files[fd].dos_inode.fclusterhi;
|
||||
pdos_inode->fcluster=rtfsl.rtfsl_files[fd].dos_inode.fcluster;
|
||||
pdos_inode++;
|
||||
/* ".." points to parent */
|
||||
w=(unsigned short) (cl>>16);
|
||||
fr_USHORT((unsigned char *)&pdos_inode->fclusterhi, w);
|
||||
w=(unsigned short) cl&0xffff;
|
||||
fr_USHORT((unsigned char*)&pdos_inode->fcluster, w);
|
||||
}
|
||||
#if (RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
/* A small write (32 or 64 bytes) needs to be journaled will always be offset or residual so all cases are covered */
|
||||
if (rtfsl.rtfsl_current_failsafe_context && (rtfsl.rtfsl_current_failsafe_context->flags&RTFSLFS_WRITE_DIRENTRY))
|
||||
rval=_rtfsl_journal_io(rtfsl.current_dr.partition_base+sector, startcopyfr/32, pdata, copied);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ANSImemcpy(p+startcopyfr, pdata,copied);
|
||||
rval=rtfsl_flush_sector_buffer(buffernumber,1);
|
||||
}
|
||||
if (rval<0)
|
||||
return rval;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ANSImemcpy(pdata,p+startcopyfr,copied);
|
||||
}
|
||||
pdata+=copied;
|
||||
}
|
||||
n_left-=copied;
|
||||
|
||||
file_pointer+=copied;
|
||||
count_inregion-=copied;
|
||||
sector+=1;
|
||||
}
|
||||
while (count_inregion >= rtfsl.current_dr.bytespsector)
|
||||
{
|
||||
copied=rtfsl.current_dr.bytespsector;
|
||||
if(pdata)
|
||||
{
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT)
|
||||
if (opflags & RTFSL_FIO_OP_WRITE)
|
||||
{
|
||||
rval = rtfsl_write_sectors(rtfsl.current_dr.partition_base+sector,1, pdata);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
rval=rtfsl_read_sectors(rtfsl.current_dr.partition_base+sector,1, pdata);
|
||||
}
|
||||
if (rval < 0)
|
||||
return rval;
|
||||
pdata+=copied;
|
||||
}
|
||||
n_left-=copied;
|
||||
file_pointer+=copied;
|
||||
sector+=1;
|
||||
count_inregion-=copied;
|
||||
}
|
||||
residual=(long)count_inregion;
|
||||
}
|
||||
rtfsl.rtfsl_files[fd].file_pointer=file_pointer;
|
||||
return(n_bytes-n_left);
|
||||
}
|
82
rtfslfiliord.c
Normal file
82
rtfslfiliord.c
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
|
||||
|
||||
extern long _rtfsl_bfilio_io(int fd, unsigned char *pdata, long n_bytes, unsigned char opflags);
|
||||
|
||||
void rtfsl_setpath(unsigned char **pathnamearray) /*__apifn__*/
|
||||
{
|
||||
rtfsl.current_dr.pathnamearray=pathnamearray;
|
||||
}
|
||||
|
||||
int rtfsl_alloc_fd(void)
|
||||
{
|
||||
int fd;
|
||||
for (fd=1;fd<RTFSL_CFG_NFILES;fd++)
|
||||
{
|
||||
if (rtfsl.rtfsl_files[fd].rtfsl_file_flags==0)
|
||||
{
|
||||
rtfsl.rtfsl_files[fd].rtfsl_file_flags=TRTFSFILE_ALLOCATED;
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
return RTFSL_ERROR_FDALLOC;
|
||||
}
|
||||
int rtfsl_open(unsigned char *name) /*__apifn__*/
|
||||
{
|
||||
return _rtfsl_open(name, 0);
|
||||
}
|
||||
int _rtfsl_open(unsigned char *name, unsigned char attributes)
|
||||
{
|
||||
struct rtfsl_file scratch_dir_file;
|
||||
int fd,rval;
|
||||
fd = rtfsl_alloc_fd();
|
||||
if (fd>=0)
|
||||
{
|
||||
unsigned char want_type=RTFSL_ENTRY_TYPE_FILE;
|
||||
if (attributes&ADIRENT)
|
||||
want_type=RTFSL_ENTRY_TYPE_DIRECTORY;
|
||||
rval=rtfsl_open_path(rtfsl.current_dr.pathnamearray,name,&scratch_dir_file, &rtfsl.rtfsl_files[fd]);
|
||||
if (rval==0 && rtfsl.rtfsl_files[fd].rtfsl_direntry_type!=want_type)
|
||||
rval=RTFSL_ERROR_PATH;
|
||||
if (rval <0)
|
||||
{
|
||||
rtfsl.rtfsl_files[fd].rtfsl_file_flags=0; /* Deallocates the file */
|
||||
fd=rval;
|
||||
}
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
int rtfsl_read(int fd, unsigned char *in_buff, int count) /*__apifn__*/
|
||||
{
|
||||
long n_bytes;
|
||||
if (rtfsl.rtfsl_files[fd].file_pointer+count > rtfsl.rtfsl_files[fd].dos_inode.fsize) /* fsize is stores in native byte order */
|
||||
n_bytes=rtfsl.rtfsl_files[fd].dos_inode.fsize-rtfsl.rtfsl_files[fd].file_pointer;
|
||||
else
|
||||
n_bytes=(long)count;
|
||||
return _rtfsl_bfilio_io(fd, in_buff, n_bytes, 0);
|
||||
}
|
||||
|
||||
|
||||
int rtfsl_close(int fd) /*__apifn__*/
|
||||
{
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT)
|
||||
int rval=0;
|
||||
if (rtfsl.rtfsl_files[fd].rtfsl_file_flags&TRTFSFILE_DIRTY)
|
||||
rval=rtfsl_flush(fd);
|
||||
rtfsl.rtfsl_files[fd].rtfsl_file_flags=0; /* Deallocates the file */
|
||||
return(rval);
|
||||
#else
|
||||
rtfsl.rtfsl_files[fd].rtfsl_file_flags=0; /* Deallocates the file */
|
||||
return(0);
|
||||
#endif
|
||||
}
|
308
rtfslfiliowr.c
Normal file
308
rtfslfiliowr.c
Normal file
@ -0,0 +1,308 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
extern long _rtfsl_bfilio_io(int fd, unsigned char *pdata, long n_bytes, unsigned char opflags);
|
||||
|
||||
struct rtfsl_create_structure
|
||||
{
|
||||
unsigned char *name;
|
||||
int eof;
|
||||
unsigned long free_file_pointer;
|
||||
unsigned long file_pointer;
|
||||
unsigned char attribute;
|
||||
};
|
||||
|
||||
int rtfsl_clzero(unsigned long cluster)
|
||||
{
|
||||
int i, rval;
|
||||
unsigned long sector;
|
||||
sector=rtfsl_cl2sector(cluster);
|
||||
rval=0;
|
||||
for (i =0; rval==0 && i < rtfsl.current_dr.secpalloc; i++,sector++)
|
||||
{
|
||||
unsigned char *b;
|
||||
rval=rtfsl_read_sector_buffer(sector);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
b = rtfsl_buffer_address(rval);
|
||||
ANSImemset(b,0,rtfsl.current_dr.bytespsector);
|
||||
rval = rtfsl_write_sectors(rtfsl.current_dr.partition_base+sector,1, b);
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
#define NOFREEFILESFOUND 0xffffffff
|
||||
|
||||
static int create_callback(struct rtfsl_file const *pcurrent_entry_file, void *puser_data)
|
||||
{
|
||||
struct rtfsl_create_structure *pcreate_structure=(struct rtfsl_create_structure *) puser_data;
|
||||
|
||||
{
|
||||
if ((pcurrent_entry_file->rtfsl_direntry_type&RTFSL_ENTRY_AVAILABLE)!=0)
|
||||
{
|
||||
if (pcreate_structure->free_file_pointer==NOFREEFILESFOUND)
|
||||
pcreate_structure->free_file_pointer=pcreate_structure->file_pointer;
|
||||
if ((pcurrent_entry_file->rtfsl_direntry_type&RTFSL_ENTRY_TYPE_EOF)==0)
|
||||
pcreate_structure->eof=1;
|
||||
}
|
||||
else if (!pcreate_structure->eof && ANSImemcmp(pcreate_structure->name,pcurrent_entry_file->dos_inode.fname,11)==0)
|
||||
{ /* Don't allow any duplicate names even if different attributes */
|
||||
return RTFSL_ERROR_EXIST;
|
||||
}
|
||||
}
|
||||
pcreate_structure->file_pointer+=32;
|
||||
return 0; /* Continue */
|
||||
}
|
||||
|
||||
int rtfsl_create(unsigned char *name,unsigned char attribute) /*__apifn__*/
|
||||
{
|
||||
int rval;
|
||||
struct rtfsl_create_structure create_structure;
|
||||
struct rtfsl_file new_directory_file;
|
||||
unsigned short date, time;
|
||||
int fd;
|
||||
|
||||
fd = rtfsl_alloc_fd();
|
||||
if (fd<0)
|
||||
return fd;
|
||||
rtfsl_get_system_date(&time, &date);
|
||||
rval = rtfsl_open_path(rtfsl.current_dr.pathnamearray,0, &new_directory_file, &rtfsl.rtfsl_files[fd]);
|
||||
if (rval==0)
|
||||
{
|
||||
create_structure.free_file_pointer=NOFREEFILESFOUND;
|
||||
create_structure.file_pointer=0;
|
||||
create_structure.name = name;
|
||||
create_structure.attribute=attribute;
|
||||
create_structure.eof=0;
|
||||
/* Find a slot */
|
||||
rval = rtfsl_enumerate_directory(&rtfsl.rtfsl_files[fd],&new_directory_file, create_callback,(void *) &create_structure);
|
||||
if(rval==0)
|
||||
{
|
||||
unsigned long seek_to;
|
||||
rval = rtfsl_finode_open(&rtfsl.rtfsl_files[fd]);
|
||||
|
||||
if (create_structure.free_file_pointer==NOFREEFILESFOUND)
|
||||
seek_to=create_structure.file_pointer;
|
||||
else
|
||||
seek_to=create_structure.free_file_pointer;
|
||||
/* Will fail on 16 bit systems if the direcory extents > 32 K*/
|
||||
if ((unsigned long)rtfsl_write(fd,0,seek_to)!=seek_to)
|
||||
{
|
||||
rval=RTFSL_ERROR_CONSISTENCY;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (create_structure.free_file_pointer==NOFREEFILESFOUND && rtfsl.current_dr.fasize<8 && (rtfsl.rtfsl_files[fd].rtfsl_direntry_type&TRTFSFILE_ISROOT_DIR))
|
||||
rval=RTFSL_ERROR_DIR_FULL;
|
||||
}
|
||||
if (rval==0)
|
||||
{
|
||||
#if (RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
if (rtfsl.rtfsl_current_failsafe_context)
|
||||
rtfsl.rtfsl_current_failsafe_context->flags |= RTFSLFS_WRITE_DIRENTRY;
|
||||
#endif
|
||||
// Format the dos inode and write it
|
||||
ANSImemcpy(&new_directory_file.dos_inode.fname,name,11);
|
||||
new_directory_file.dos_inode.fattribute=attribute; /* File attributes */
|
||||
new_directory_file.dos_inode.reservednt=0;
|
||||
new_directory_file.dos_inode.create10msincrement=0;
|
||||
new_directory_file.dos_inode.ctime=time; /* time & date create */
|
||||
new_directory_file.dos_inode.cdate=date;
|
||||
new_directory_file.dos_inode.adate=date; /* Date last accessed */
|
||||
new_directory_file.dos_inode.ftime=time; /* time & date lastmodified */
|
||||
new_directory_file.dos_inode.fdate=date;
|
||||
new_directory_file.dos_inode.fsize =0;
|
||||
new_directory_file.dos_inode.fcluster=0;
|
||||
new_directory_file.dos_inode.fclusterhi=0;
|
||||
// call rtfsl_write on new_directory_file to extend it
|
||||
rval=rtfsl_write(fd,(unsigned char *)&new_directory_file.dos_inode,32);
|
||||
if (rval>=0)
|
||||
rval=rtfsl_flush(fd);
|
||||
#if (RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
if (rtfsl.rtfsl_current_failsafe_context)
|
||||
rtfsl.rtfsl_current_failsafe_context->flags &= ~RTFSLFS_WRITE_DIRENTRY;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
rtfsl.rtfsl_files[fd].rtfsl_file_flags=0;
|
||||
return rval;
|
||||
}
|
||||
#include <stdio.h>
|
||||
int rtfsl_write(int fd, unsigned char *in_buff, int count) /*__apifn__*/
|
||||
{
|
||||
unsigned long needed,bytespcluster,prev_cluster;
|
||||
int rval,i,updatesize=0;
|
||||
|
||||
bytespcluster=rtfsl.current_dr.bytespcluster;
|
||||
needed = rtfsl.rtfsl_files[fd].file_pointer+count;
|
||||
if (needed > rtfsl.rtfsl_files[fd].dos_inode.fsize)
|
||||
{
|
||||
unsigned long allocated =
|
||||
((rtfsl.rtfsl_files[fd].dos_inode.fsize+rtfsl.current_dr.bytespcluster-1)/rtfsl.current_dr.bytespcluster)
|
||||
*bytespcluster;
|
||||
unsigned long next_segment_base=0;
|
||||
prev_cluster=0;
|
||||
for (i =0;i < RTFSL_CFG_FILE_FRAG_BUFFER_SIZE;i++)
|
||||
{
|
||||
if(rtfsl.rtfsl_files[fd].cluster_segment_array[i][0])
|
||||
prev_cluster=rtfsl.rtfsl_files[fd].cluster_segment_array[i][1];
|
||||
else
|
||||
break;
|
||||
}
|
||||
updatesize=1;
|
||||
while (allocated < needed)
|
||||
{
|
||||
int n;
|
||||
unsigned long new_cluster,value;
|
||||
n=fatop_buff_get_frag(rtfsl.current_dr.next_alloc|RTFSL_ALLOC_CLUSTER, &new_cluster, 1);
|
||||
if (n==0)
|
||||
{
|
||||
rtfsl.current_dr.next_alloc=2;
|
||||
n=fatop_buff_get_frag(rtfsl.current_dr.next_alloc|RTFSL_ALLOC_CLUSTER, &new_cluster, 1);
|
||||
|
||||
}
|
||||
if (n==1)
|
||||
{
|
||||
rtfsl.current_dr.next_alloc=new_cluster;
|
||||
if (rtfsl.current_dr.free_alloc>=1)
|
||||
rtfsl.current_dr.free_alloc-=1;
|
||||
}
|
||||
else if (n<1)
|
||||
{
|
||||
if (n==0)
|
||||
return RTFSL_ERROR_DISK_FULL;
|
||||
else
|
||||
return n;
|
||||
}
|
||||
#if (RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
if (!rtfsl.rtfsl_current_failsafe_context)
|
||||
#endif
|
||||
{
|
||||
/* Write a terminate chain value before linking to it.
|
||||
This is safer if not using Failsafe, but it reduces the journal file efficiency when using it */
|
||||
value=rtfsl.current_dr.end_cluster_marker|0xf;
|
||||
rval=fatop_buff_get_frag(new_cluster|RTFSL_WRITE_CLUSTER, &value, 1);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
}
|
||||
|
||||
if (prev_cluster)
|
||||
{ /* Link the previous cluster to the new one */
|
||||
value=new_cluster;
|
||||
rval=fatop_buff_get_frag(prev_cluster|RTFSL_WRITE_CLUSTER, &value, 1);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
}
|
||||
else
|
||||
{
|
||||
fr_USHORT((unsigned char *) &rtfsl.rtfsl_files[fd].dos_inode.fcluster,(unsigned short)(new_cluster&0xffff));
|
||||
fr_USHORT((unsigned char *) &rtfsl.rtfsl_files[fd].dos_inode.fclusterhi,(unsigned short)((new_cluster>>16)&0xffff));
|
||||
}
|
||||
#if (RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
if (rtfsl.rtfsl_current_failsafe_context)
|
||||
{
|
||||
/* Write failsafe terminating the chain after extending it makes it easier to coalesce chains in the journal */
|
||||
value=rtfsl.current_dr.end_cluster_marker|0xf;
|
||||
rval=fatop_buff_get_frag(new_cluster|RTFSL_WRITE_CLUSTER, &value, 1);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
}
|
||||
#endif
|
||||
if (!next_segment_base) /* We are allocating, but not loading the chain, this allows load next segment to follw the chain */
|
||||
rtfsl.rtfsl_files[fd].next_segment_base=next_segment_base=new_cluster;
|
||||
prev_cluster=new_cluster;
|
||||
allocated+=bytespcluster;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
rval=_rtfsl_bfilio_io(fd, in_buff, (long)count, RTFSL_FIO_OP_WRITE);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
if (updatesize)
|
||||
{
|
||||
rtfsl.rtfsl_files[fd].rtfsl_file_flags|=TRTFSFILE_DIRTY;
|
||||
rtfsl.rtfsl_files[fd].dos_inode.fsize=rtfsl.rtfsl_files[fd].file_pointer;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int rtfsl_flush(int fd) /*__apifn__*/
|
||||
{
|
||||
unsigned long l;
|
||||
unsigned char *p;
|
||||
int rval;
|
||||
|
||||
if (rtfsl.rtfsl_files[fd].rtfsl_file_flags&(TRTFSFILE_ISROOT_DIR|TRTFSFILE_SECTOR_REGION))
|
||||
return 0;
|
||||
l=rtfsl.rtfsl_files[fd].dos_inode.fsize;
|
||||
if (rtfsl.rtfsl_files[fd].dos_inode.fattribute&(ADIRENT|AVOLUME))
|
||||
fr_ULONG((unsigned char *) &rtfsl.rtfsl_files[fd].dos_inode.fsize,0);
|
||||
else
|
||||
fr_ULONG((unsigned char *) &rtfsl.rtfsl_files[fd].dos_inode.fsize,l);
|
||||
#if (RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
/* Submit the entry to the journal failsafe is on */
|
||||
if (rtfsl.rtfsl_current_failsafe_context)
|
||||
{
|
||||
rval=rtfslfs_dirent_remap(rtfsl.current_dr.partition_base+rtfsl.rtfsl_files[fd].sector,rtfsl.rtfsl_files[fd].index, &rtfsl.rtfsl_files[fd].dos_inode,0);
|
||||
rtfsl.rtfsl_files[fd].dos_inode.fsize=l;
|
||||
if (rval<0)
|
||||
return rval;
|
||||
else if (rval !=1)
|
||||
return RTFSL_ERROR_CONSISTENCY;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
rval=rtfsl_read_sector_buffer(rtfsl.current_dr.partition_base+rtfsl.rtfsl_files[fd].sector);
|
||||
if (rval<0)
|
||||
return (int) rval;
|
||||
p = rtfsl_buffer_address(rval)+rtfsl.rtfsl_files[fd].index*32;
|
||||
ANSImemcpy(p,&rtfsl.rtfsl_files[fd].dos_inode,32);
|
||||
rtfsl.rtfsl_files[fd].dos_inode.fsize=l;
|
||||
rval=rtfsl_flush_sector_buffer(rval,1);
|
||||
return rval;
|
||||
}
|
||||
int rtfsl_flush_info_sec(void) /*__apifn__*/
|
||||
{
|
||||
#if (RTFSL_INCLUDE_FAT32)
|
||||
int rval=0;
|
||||
if ((rtfsl.current_dr.flags&RTFSL_FAT_CHANGED_FLAG) && rtfsl.current_dr.infosec)
|
||||
{
|
||||
rtfsl.current_dr.flags&=~RTFSL_FAT_CHANGED_FLAG;
|
||||
#if (RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
if (rtfsl.rtfsl_current_failsafe_context)
|
||||
{
|
||||
struct rtfsl_dosinode info_inode;
|
||||
unsigned long *pl;
|
||||
info_inode.fname[0]='A'; /* As long as it is not the delete character */
|
||||
pl=(unsigned long *)&info_inode;
|
||||
pl++;
|
||||
*pl++=rtfsl.current_dr.free_alloc;
|
||||
*pl=rtfsl.current_dr.next_alloc;
|
||||
/* Put the information in a fake dos_inode record in the journal. restore will recognize the sector as the info sector and call rtfsl_flush_info_sec() to update */
|
||||
if (rtfsl.rtfsl_current_failsafe_context)
|
||||
return rtfslfs_dirent_remap(rtfsl.current_dr.partition_base+rtfsl.current_dr.infosec,0, &info_inode,0);
|
||||
}
|
||||
#endif
|
||||
rval=rtfsl_read_sector_buffer(rtfsl.current_dr.partition_base+rtfsl.current_dr.infosec);
|
||||
if (rval>=0)
|
||||
{
|
||||
unsigned char *p = rtfsl_buffer_address(rval);
|
||||
fr_ULONG((p+488),rtfsl.current_dr.free_alloc);
|
||||
fr_ULONG((p+492),rtfsl.current_dr.next_alloc);
|
||||
rval=rtfsl_flush_sector_buffer(rval,1);
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
42
rtfslfssystem.c
Normal file
42
rtfslfssystem.c
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
//HEREHERE
|
||||
//#define RTFSLFS_JTEST 1
|
||||
//#define RTFSLFS_JCLEAR 2
|
||||
//#define RTFSLFS_JREAD 3
|
||||
//#define RTFSLFS_JWRITE 4
|
||||
|
||||
#include "rtfslite.h"
|
||||
#if (RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
int rtfslfs_access_journal(int command)
|
||||
{
|
||||
struct rtfsl_failsafe_context *pfs=rtfsl.rtfsl_current_failsafe_context;
|
||||
int i,rval;
|
||||
unsigned char *b=pfs->journal_buffer;
|
||||
unsigned long journal_file_start_sector;
|
||||
rval=0;
|
||||
/* Clear zeor fills the buffer and writes it */
|
||||
if (command==RTFSLFS_JCLEAR)
|
||||
ANSImemset(b,0,pfs->journal_buffer_size);
|
||||
if (RTFSL_CFG_FSBUFFERSIZESECTORS+1 > rtfsl.current_dr.partition_base)
|
||||
return RTFSL_ERROR_JOURNAL_NONE;
|
||||
/* JTEST Will fall through without doing any I/O */
|
||||
journal_file_start_sector=rtfsl.current_dr.partition_base-RTFSL_CFG_FSBUFFERSIZESECTORS;
|
||||
for (i=0;rval==0&&i<pfs->journal_buffer_size/rtfsl.current_dr.bytespsector; i++)
|
||||
{
|
||||
if (command==RTFSLFS_JREAD)
|
||||
rval=rtfsl_read_sectors(journal_file_start_sector+i,1,b);
|
||||
else if (command==RTFSLFS_JWRITE||command==RTFSLFS_JCLEAR)
|
||||
rval=rtfsl_write_sectors(journal_file_start_sector+i,1,b);
|
||||
b+=rtfsl.current_dr.bytespsector;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
#endif
|
72
rtfslgfirst.c
Normal file
72
rtfslgfirst.c
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
|
||||
/* Structure for use by rtfsl_gfirst, rtfsl_gnext */
|
||||
|
||||
#define GFIRST_EOF 2
|
||||
static int rtfsl_gfirst_callback(struct rtfsl_file const *pcurrent_entry_file, void *puser_data)
|
||||
{
|
||||
struct rtfsl_dstat *pdstat = (struct rtfsl_dstat *) puser_data;
|
||||
|
||||
if (pcurrent_entry_file->rtfsl_direntry_type==RTFSL_ENTRY_TYPE_EOF)
|
||||
return GFIRST_EOF;
|
||||
if ((pcurrent_entry_file->rtfsl_direntry_type&(RTFSL_ENTRY_TYPE_DIRECTORY|RTFSL_ENTRY_TYPE_VOLUME|RTFSL_ENTRY_TYPE_FILE))!=0)
|
||||
{
|
||||
if (!pdstat->nametomatch||ANSImemcmp(pcurrent_entry_file->dos_inode.fname,pdstat->nametomatch,11)==0)
|
||||
{
|
||||
ANSImemcpy(&pdstat->fnameandext,pcurrent_entry_file->dos_inode.fname,11);
|
||||
pdstat->fnameandext[11]=0; /* Null terminate file and extension */
|
||||
pdstat->fattribute=pcurrent_entry_file->dos_inode.fattribute;;
|
||||
pdstat->ftime=pcurrent_entry_file->dos_inode.ftime;
|
||||
pdstat->fdate=pcurrent_entry_file->dos_inode.fdate;
|
||||
pdstat->ctime=pcurrent_entry_file->dos_inode.ctime;
|
||||
pdstat->cdate=pcurrent_entry_file->dos_inode.cdate;
|
||||
pdstat->atime=0;
|
||||
pdstat->adate=pcurrent_entry_file->dos_inode.adate;
|
||||
pdstat->fsize=pcurrent_entry_file->dos_inode.fsize;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0; /* Continue */
|
||||
}
|
||||
|
||||
/* Return <0 on error, 1 if contents are valid and scan may continue, 0, if end of directory was reached. */
|
||||
int rtfsl_gfirst(struct rtfsl_dstat *statobj, unsigned char *name) /*__apifn__*/
|
||||
{
|
||||
int rval;
|
||||
ANSImemset(statobj,0,sizeof(*statobj));
|
||||
statobj->nametomatch=name;
|
||||
/* Open the current directory or root use current_matched_file as a scratch directory entry*/
|
||||
rval=rtfsl_open_path(rtfsl.current_dr.pathnamearray,0, &statobj->current_matched_file, &statobj->directory_file);
|
||||
if (rval >= 0)
|
||||
{
|
||||
/* Enumerate statobj->directory_file in search of name */
|
||||
rval = rtfsl_finode_open(&statobj->directory_file);
|
||||
if (rval==0)
|
||||
{
|
||||
rval=rtfsl_enumerate_directory(&statobj->directory_file,&statobj->current_matched_file,rtfsl_gfirst_callback,(void *) statobj);
|
||||
if (rval==GFIRST_EOF)
|
||||
rval=0;
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* Return <0 on error, 1 if contents are valid and scan may continue, 0, if end of directory was reached. */
|
||||
int rtfsl_gnext(struct rtfsl_dstat *statobj) /*__apifn__*/
|
||||
{
|
||||
statobj->nametomatch=0;
|
||||
return rtfsl_enumerate_directory(&statobj->directory_file,&statobj->current_matched_file,rtfsl_gfirst_callback,(void *) statobj);
|
||||
}
|
||||
|
||||
void rtfsl_done(struct rtfsl_dstat *statobj) /*__apifn__*/
|
||||
{
|
||||
}
|
314
rtfslite.h
Normal file
314
rtfslite.h
Normal file
@ -0,0 +1,314 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#ifndef __RTFSLITE__
|
||||
#include <string.h>
|
||||
|
||||
#define ANSImemset memset
|
||||
#define ANSImemcmp memcmp
|
||||
#define ANSImemcpy memcpy
|
||||
|
||||
|
||||
#define RTFSL_INCLUDE_SUBDIRECTORIES 1
|
||||
#define RTFSL_INCLUDE_FAT32 1
|
||||
#define RTFSL_INCLUDE_FAT12 1
|
||||
#define RTFSL_INCLUDE_MBR_SUPPORT 1 /* 180 bytes, need 3rd option as well */
|
||||
#define RTFSL_INCLUDE_WRITE_SUPPORT 1 /* XXX bytes */
|
||||
#define RTFSL_INCLUDE_FAILSAFE_SUPPORT 1 /* XXX bytes */
|
||||
#define RTFSL_INCLUDE_SECURE_DIGITAL 1
|
||||
#define RTFSL_CFG_FILE_FRAG_BUFFER_SIZE 4
|
||||
#define RTFSL_CFG_FSBUFFERSIZESECTORS 1
|
||||
#define RTFSL_CFG_FSBUFFERSIZEBYTES (RTFSL_CFG_FSBUFFERSIZESECTORS*512)
|
||||
#define RTFSL_CFG_NFILES 2
|
||||
#define RTFSL_CFG_MAXBLOCKSIZE 512
|
||||
#define RTFSL_CFG_NUMBUFFERS 2
|
||||
|
||||
/* Set this to 1 build a minimum system supporting only the API functions
|
||||
rtfsl_load_file and rtfsl_setpath. If being able to load only from the root is
|
||||
acceptable you can reduce footprint further by setting RTFSL_INCLUDE_SUBDIRECTORIES to 0 */
|
||||
|
||||
#define RTFSL_INCLUDE_LOAD_ONLY 0
|
||||
#if (RTFSL_INCLUDE_LOAD_ONLY)
|
||||
#undef RTFSL_INCLUDE_WRITE_SUPPORT
|
||||
#undef RTFSL_INCLUDE_FAILSAFE_SUPPORT
|
||||
#undef RTFSL_INCLUDE_SECURE_DIGITAL
|
||||
#undef RTFSL_CFG_NFILES
|
||||
#undef RTFSL_CFG_NUMBUFFERS
|
||||
#define RTFSL_INCLUDE_WRITE_SUPPORT 0
|
||||
#define RTFSL_INCLUDE_FAILSAFE_SUPPORT 0
|
||||
#define RTFSL_INCLUDE_SECURE_DIGITAL 0
|
||||
#define RTFSL_CFG_NFILES 1
|
||||
#define RTFSL_CFG_NUMBUFFERS 1
|
||||
#endif
|
||||
|
||||
#define RTFSL_ERROR_NONE 0
|
||||
#define RTFSL_ERROR_ARGS -1
|
||||
#define RTFSL_ERROR_CONSISTENCY -2
|
||||
#define RTFSL_ERROR_DIR_FULL -3
|
||||
#define RTFSL_ERROR_DISK_FULL -4
|
||||
#define RTFSL_ERROR_FDALLOC -5
|
||||
#define RTFSL_ERROR_FORMAT -6
|
||||
#define RTFSL_ERROR_JOURNAL_FULL -7
|
||||
#define RTFSL_ERROR_JOURNAL_NONE -8
|
||||
#define RTFSL_ERROR_NOTFOUND -9
|
||||
#define RTFSL_ERROR_PATH -10
|
||||
#define RTFSL_ERROR_EXIST -11
|
||||
#define RTFSL_ERROR_ENOTEMPTY -12
|
||||
#define RTFSL_ERROR_TEST -13
|
||||
|
||||
#define RTFSL_ERROR_IO_WRITE_PROTECT -14
|
||||
#define RTFSL_ERROR_IO_NO_MEDIA -15
|
||||
#define RTFSL_ERROR_IO_ERROR -16
|
||||
|
||||
#define RTFSL_WRITE_CLUSTER 0x8000000
|
||||
#define RTFSL_ALLOC_CLUSTER 0x4000000
|
||||
#define RTFSL_MASK_COMMAND 0xC000000
|
||||
#define RTFSL_JOURNALFULL_CLUSTER 0xffffffff
|
||||
#define RTFSL_JOURNALDELETED_CLUSTER 0xfffffffe
|
||||
|
||||
#define RTFSL_FIO_OP_WRITE 0x01
|
||||
#define RTFSL_FIO_OP_APPEND 0x02
|
||||
|
||||
void rtfsl_get_system_date(unsigned short *time, unsigned short *date);
|
||||
int rtfsl_read_sectors(unsigned long sector,int count, unsigned char *buffer);
|
||||
int rtfsl_write_sectors(unsigned long sector, int count, unsigned char *buffer);
|
||||
|
||||
struct rtfsl_dosinode {
|
||||
unsigned char fname[8];
|
||||
unsigned char fext[3];
|
||||
unsigned char fattribute; /* File attributes */
|
||||
unsigned char reservednt;
|
||||
unsigned char create10msincrement;
|
||||
unsigned short ctime; /* time & date create */
|
||||
unsigned short cdate;
|
||||
unsigned short adate; /* Date last accessed */
|
||||
unsigned short fclusterhi; /* This is where fat32 stores file location */
|
||||
unsigned short ftime; /* time & date lastmodified */
|
||||
unsigned short fdate;
|
||||
unsigned short fcluster; /* Cluster for data file */
|
||||
unsigned long fsize; /* File size */
|
||||
};
|
||||
|
||||
struct rtfsl_drive
|
||||
{
|
||||
unsigned long partition_base;
|
||||
unsigned long partition_size;
|
||||
unsigned long maxfindex;
|
||||
unsigned long numsecs;
|
||||
unsigned long secpfat;
|
||||
unsigned long rootbegin;
|
||||
unsigned long firstclblock;
|
||||
unsigned long free_alloc;
|
||||
unsigned long next_alloc;
|
||||
unsigned long end_cluster_marker;
|
||||
unsigned short bytespsector;
|
||||
unsigned long bytespcluster;
|
||||
unsigned short secreserved;
|
||||
unsigned short numroot;
|
||||
#define RTFSL_IOTYPE_FILE_FLAG 0x01
|
||||
#define RTFSL_FAT_CHANGED_FLAG 0x02 /* For FAT32 systems this is set when freespece has changed and the infosec needs a flush */
|
||||
unsigned short flags;
|
||||
unsigned short infosec;
|
||||
unsigned short backup;
|
||||
unsigned char secpalloc;
|
||||
unsigned char numfats;
|
||||
unsigned char fasize;
|
||||
unsigned char **pathnamearray;
|
||||
};
|
||||
struct rtfsl_file {
|
||||
unsigned long sector;
|
||||
struct rtfsl_dosinode dos_inode;
|
||||
unsigned long file_pointer;
|
||||
unsigned long file_pointer_at_segment_base;
|
||||
unsigned long segment_size_bytes;
|
||||
unsigned long next_segment_base;
|
||||
unsigned long cluster_segment_array[RTFSL_CFG_FILE_FRAG_BUFFER_SIZE][2];
|
||||
unsigned short index;
|
||||
#define TRTFSFILE_ISROOT_DIR 0x01
|
||||
#define TRTFSFILE_DIRTY 0x02
|
||||
#define TRTFSFILE_SECTOR_REGION 0x04
|
||||
#define TRTFSFILE_ALLOCATED 0x08
|
||||
#define TRTFSFILE_ISMKDIR 0x10
|
||||
unsigned char rtfsl_file_flags;
|
||||
#define RTFSL_ENTRY_TYPE_ERASED 1 /* Must be power of 2. */
|
||||
#define RTFSL_ENTRY_TYPE_DIRECTORY 2
|
||||
#define RTFSL_ENTRY_TYPE_VOLUME 4
|
||||
#define RTFSL_ENTRY_TYPE_LFN 8
|
||||
#define RTFSL_ENTRY_TYPE_FILE 16
|
||||
#define RTFSL_ENTRY_TYPE_EOF 32
|
||||
#define RTFSL_ENTRY_AVAILABLE (RTFSL_ENTRY_TYPE_ERASED|RTFSL_ENTRY_TYPE_EOF)
|
||||
unsigned char rtfsl_direntry_type;
|
||||
};
|
||||
|
||||
/* Structure for use by rtfsl_gfirst, rtfsl_gnext */
|
||||
struct rtfsl_dstat {
|
||||
unsigned char fnameandext[12]; /* Null terminated file and extension */
|
||||
unsigned char fattribute; /* File attributes */
|
||||
unsigned short ftime; /* time & date lastmodified. See date */
|
||||
unsigned short fdate; /* and time handlers for getting info */
|
||||
unsigned short ctime; /* time & date created */
|
||||
unsigned short cdate;
|
||||
unsigned short atime; /* time & date accessed */
|
||||
unsigned short adate; /* Date last accessed */
|
||||
unsigned long fsize; /* File size */
|
||||
/* INTERNAL */
|
||||
struct rtfsl_file directory_file;
|
||||
struct rtfsl_file current_matched_file;
|
||||
unsigned char *nametomatch;
|
||||
};
|
||||
/* Structure for use by rtfsl_stat and rtfsl_fstat */
|
||||
struct rtfsl_statstructure
|
||||
{
|
||||
int st_dev; /* (0) */
|
||||
int st_ino; /* (0) */
|
||||
unsigned long st_mode; /* (0) */
|
||||
int st_nlink; /* (0) */
|
||||
int st_rdev; /* (0) */
|
||||
unsigned long st_size; /* file size, in bytes */
|
||||
unsigned long st_atime; /* last access date in high 16 bits */
|
||||
unsigned long st_mtime; /* last modification date|time */
|
||||
unsigned long st_ctime; /* file create date|time */
|
||||
unsigned long st_blksize; /* optimal blocksize for I/O (cluster size) */
|
||||
unsigned long st_blocks; /* blocks allocated for file */
|
||||
unsigned char fattribute; /* File attributes - DOS attributes
|
||||
(non standard but useful) */
|
||||
};
|
||||
|
||||
#define PCDELETE (unsigned char) 0xE5
|
||||
#define ARDONLY 0x1 /* MS-DOS File attributes */
|
||||
#define AHIDDEN 0x2
|
||||
#define ASYSTEM 0x4
|
||||
#define AVOLUME 0x8
|
||||
#define ADIRENT 0x10
|
||||
#define ARCHIVE 0x20
|
||||
#define ANORMAL 0x00
|
||||
#define CHICAGO_EXT 0x0f /* Chicago extended filename attribute */
|
||||
|
||||
|
||||
#define PSEEK_SET 0 /* offset from begining of file*/
|
||||
#define PSEEK_CUR 1 /* offset from current file pointer*/
|
||||
#define PSEEK_END 2 /* offset from end of file*/
|
||||
|
||||
unsigned long to_ULONG( unsigned char *from);
|
||||
unsigned short to_USHORT( unsigned char *from);
|
||||
void fr_USHORT(unsigned char *to, unsigned short from);
|
||||
void fr_ULONG(unsigned char *to, unsigned long from);
|
||||
|
||||
|
||||
|
||||
int rtfsl_diskopen(void);
|
||||
unsigned long rtfsl_cl2sector(unsigned long cluster);
|
||||
int rtfsl_finode_get( struct rtfsl_file *pfile, unsigned long sector, unsigned short index);
|
||||
unsigned long rtfsl_sec2cluster( unsigned long sector);
|
||||
int rtfsl_finode_open(struct rtfsl_file *pfile);
|
||||
int rtfsl_root_finode_open(struct rtfsl_file *pfile);
|
||||
long rtfsl_load_next_segment(struct rtfsl_file *pfile,unsigned long current_cluster);
|
||||
|
||||
typedef int (*DirScanCallback) (struct rtfsl_file const *pcurrent_entry_file, void *puser_data);
|
||||
typedef unsigned long (*FileScanCallback) (struct rtfsl_file const *pfile, unsigned long start_sector, unsigned long nbytes, void *puser_data);
|
||||
|
||||
int rtfsl_enumerate_file(struct rtfsl_file *pfile,FileScanCallback pCallback, void *puser_data);
|
||||
int rtfsl_enumerate_directory(struct rtfsl_file *pdirectory_file,struct rtfsl_file *pcurrent_entry_file,DirScanCallback pCallback, void *puser_data);
|
||||
|
||||
int rtfsl_read_sector_buffer(unsigned long sector);
|
||||
int rtfsl_flush_sector_buffer(int bufferhandle,int force);
|
||||
void rtfsl_mark_sector_buffer(int bufferhandle);
|
||||
int rtfsl_flush_all_buffers(void);
|
||||
int fatop_buff_get_frag(unsigned long current_cluster, unsigned long *pnext_cluster, unsigned long max_length);
|
||||
int rtfsl_open_path(unsigned char **pathlist,unsigned char *pentryname, struct rtfsl_file *directory_file, struct rtfsl_file *ptarget_file);
|
||||
int rtfsl_clzero(unsigned long cluster);
|
||||
|
||||
int rtfsl_load_file(unsigned char *filename, unsigned long load_address);
|
||||
void rtfsl_setpath(unsigned char **pathnamearray);
|
||||
int rtfsl_gfirst(struct rtfsl_dstat *statobj, unsigned char *name);
|
||||
int rtfsl_gnext(struct rtfsl_dstat *statobj);
|
||||
void rtfsl_done(struct rtfsl_dstat *statobj);
|
||||
|
||||
int rtfsl_alloc_fd(void);
|
||||
int _rtfsl_open(unsigned char *name,unsigned char attributes);
|
||||
int rtfsl_open(unsigned char *name);
|
||||
#define rtfsl_dir_open(N) _rtfsl_open(N,ADIRENT)
|
||||
int rtfsl_read(int fd, unsigned char *in_buff, int count);
|
||||
int rtfsl_close(int fd);
|
||||
long rtfsl_lseek(int fd, long offset, int origin);
|
||||
int rtfsl_fstat(int fd, struct rtfsl_statstructure *pstat);
|
||||
int rtfsl_write(int fd, unsigned char *in_buff, int count);
|
||||
int rtfsl_flush(int fd);
|
||||
int rtfsl_flush_info_sec(void);
|
||||
int rtfsl_create(unsigned char *name, unsigned char attribute);
|
||||
int rtfsl_mkdir (unsigned char *name);
|
||||
int rtfsl_rmdir(unsigned char *name);
|
||||
int _rtfsl_delete(unsigned char *name, unsigned char attribute);
|
||||
int rtfsl_delete(unsigned char *name);
|
||||
int rtfsl_rename(unsigned char *name, unsigned char *newname);
|
||||
|
||||
|
||||
unsigned long rtfslfs_cluster_remap(unsigned long cluster,unsigned long value);
|
||||
int rtfslfs_cluster_map(unsigned long cluster,unsigned long value);
|
||||
int rtfslfs_dirent_remap(unsigned long sector,unsigned long index, struct rtfsl_dosinode *p_dos_inode,int reading);
|
||||
|
||||
#define RTFSLFS_JTEST 1
|
||||
#define RTFSLFS_JCLEAR 2
|
||||
#define RTFSLFS_JREAD 3
|
||||
#define RTFSLFS_JWRITE 4
|
||||
|
||||
int rtfslfs_start(void);
|
||||
int rtfslfs_flush(void);
|
||||
int rtfslfs_restore(void);
|
||||
int rtfslfs_sync(void);
|
||||
int rtfslfs_access_journal(int command);
|
||||
|
||||
|
||||
|
||||
#if (RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
typedef unsigned long treplacement_record[2];
|
||||
struct rtfsl_failsafe_context {
|
||||
/* Current cache */
|
||||
int journal_buffer_size;
|
||||
int journal_buffer_free;
|
||||
unsigned char *journal_buffer;
|
||||
#define REPLACEMENT_RECORD_SIZE_BYTES 8
|
||||
#define REPLACEMENT_DOSINODESIZE_SIZE_BYTES 32
|
||||
unsigned long *preplacement_record_count; /* The first entry in the journal is reserved for replacement_record_count:replacement_dosinode_count */
|
||||
unsigned long *pcurrent_dosinode_offset; /* The second entry in the journal is reserved for replacement_record_count:replacement_dosinode_count */
|
||||
treplacement_record *preplacement_records;
|
||||
#define RTFSLFS_WRITE_DIRENTRY 0x1
|
||||
#define RTFSLFS_MAPPED_CL_FOUND 0x2
|
||||
unsigned char flags;
|
||||
};
|
||||
#endif
|
||||
|
||||
extern const char *dotname;
|
||||
extern const char *dotdotname;
|
||||
extern const unsigned char end_name[11];
|
||||
|
||||
struct rtfsl_context {
|
||||
struct rtfsl_drive current_dr;
|
||||
struct rtfsl_file rtfsl_files[RTFSL_CFG_NFILES];
|
||||
unsigned long current_buffered_sectors[RTFSL_CFG_NUMBUFFERS];
|
||||
unsigned char buffer_pool_agingstack[RTFSL_CFG_NUMBUFFERS];
|
||||
unsigned char *pcurrent_buffer_pool;
|
||||
unsigned long buffer_pool_dirty;
|
||||
#if (RTFSL_INCLUDE_SECURE_DIGITAL)
|
||||
unsigned long buffer_isfiledata;
|
||||
#endif
|
||||
#if (RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
struct rtfsl_failsafe_context rtfsl_failsafe_context;
|
||||
unsigned char rtfslfs_sector_buffer[RTFSL_CFG_FSBUFFERSIZEBYTES];
|
||||
struct rtfsl_failsafe_context *rtfsl_current_failsafe_context;
|
||||
#endif
|
||||
};
|
||||
extern struct rtfsl_context rtfsl;
|
||||
|
||||
extern unsigned char rtfsl_sector_buffer[];
|
||||
|
||||
#define rtfsl_buffer_address(H) rtfsl.pcurrent_buffer_pool+((H)*rtfsl.current_dr.bytespsector)
|
||||
|
||||
|
||||
#endif /* __RTFSLITE__ */
|
929
rtfslitecore.c
Normal file
929
rtfslitecore.c
Normal file
@ -0,0 +1,929 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
|
||||
#include "rtfslite.h"
|
||||
|
||||
#define BUFHMASK(H) (1<<H)
|
||||
#define BUFHMASKNOT(H) (~(1<<H))
|
||||
|
||||
static const unsigned char dos_partition_types[]= {
|
||||
0x01,0x04,0x06,
|
||||
0x0E, /* Windows FAT16 Partition */
|
||||
0x0B, /* FAT32 Partition */
|
||||
0x0C, /* FAT32 Partition */
|
||||
0x55, /* FAT32 Partition */
|
||||
0x07 /* exFat Partition */
|
||||
};
|
||||
#if (RTFSL_CFG_FILE_FRAG_BUFFER_SIZE>1)
|
||||
int rtfsl_load_cluster_chain(unsigned long start_cluster, unsigned long *segment_length_clusters, unsigned long *start_next_segment, unsigned long cluster_segment_array[][2], int cluster_segment_array_size);
|
||||
#endif
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT)
|
||||
|
||||
|
||||
void rtfsl_mark_sector_buffer(int bufferhandle)
|
||||
{
|
||||
rtfsl.buffer_pool_dirty|=BUFHMASK(bufferhandle);
|
||||
}
|
||||
|
||||
int rtfsl_flush_sector_buffer(int bufferhandle,int force)
|
||||
{
|
||||
int rval=0;
|
||||
if (force||(rtfsl.buffer_pool_dirty&BUFHMASK(bufferhandle)))
|
||||
{
|
||||
unsigned char *b = rtfsl.pcurrent_buffer_pool+(bufferhandle*rtfsl.current_dr.bytespsector);
|
||||
rval = rtfsl_write_sectors(rtfsl.current_buffered_sectors[bufferhandle],1,b);
|
||||
if (rval==0&&rtfsl.current_dr.numfats==2)
|
||||
{
|
||||
unsigned long l;
|
||||
l=rtfsl.current_buffered_sectors[bufferhandle]-rtfsl.current_dr.partition_base;
|
||||
if (l>=rtfsl.current_dr.secreserved && l<rtfsl.current_dr.secreserved+(unsigned long)rtfsl.current_dr.secpfat)
|
||||
rval = rtfsl_write_sectors(rtfsl.current_buffered_sectors[bufferhandle]+(unsigned long)rtfsl.current_dr.secpfat,1,b);
|
||||
}
|
||||
rtfsl.buffer_pool_dirty&=BUFHMASKNOT(bufferhandle);
|
||||
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
int rtfsl_flush_all_buffers(void) /*__apifn__*/
|
||||
{
|
||||
int bufferhandle,rval;
|
||||
rval=0;
|
||||
for(bufferhandle=0;rval==0&&bufferhandle<RTFSL_CFG_NUMBUFFERS;bufferhandle++)
|
||||
rval=rtfsl_flush_sector_buffer(bufferhandle,0);
|
||||
#if (RTFSL_INCLUDE_FAT32)
|
||||
rval=rtfsl_flush_info_sec();
|
||||
#endif
|
||||
return rval;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int rtfsl_read_sector_buffer(unsigned long sector)
|
||||
{
|
||||
int found,rval;
|
||||
unsigned char *b,i,bufferhandle;
|
||||
found=0;
|
||||
bufferhandle=rtfsl.buffer_pool_agingstack[RTFSL_CFG_NUMBUFFERS-1];
|
||||
rval=0;
|
||||
#if(RTFSL_CFG_NUMBUFFERS>1)
|
||||
b=rtfsl.buffer_pool_agingstack;
|
||||
for(i=0;i<RTFSL_CFG_NUMBUFFERS;i++)
|
||||
{
|
||||
if (sector==rtfsl.current_buffered_sectors[i])
|
||||
{
|
||||
bufferhandle=i;
|
||||
found=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT)
|
||||
if (!found)
|
||||
rval = rtfsl_flush_sector_buffer(bufferhandle,0);
|
||||
#endif
|
||||
if (rval>=0)
|
||||
{
|
||||
if (!found)
|
||||
rval=rtfsl_read_sectors(sector,1, rtfsl.pcurrent_buffer_pool+(bufferhandle*rtfsl.current_dr.bytespsector));
|
||||
if (rval>=0)
|
||||
{
|
||||
int ntocopy=0;
|
||||
rtfsl.current_buffered_sectors[bufferhandle]=sector;
|
||||
rval=(int)bufferhandle;
|
||||
#if (RTFSL_CFG_NUMBUFFERS>1)
|
||||
if (b[0]!=bufferhandle)
|
||||
{ /* Move the buffer to the top of the aging stack if it isn;t already there */
|
||||
for (i=1;i<RTFSL_CFG_NUMBUFFERS-1;i++)
|
||||
{
|
||||
if(b[i]==bufferhandle)
|
||||
{
|
||||
ntocopy=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ntocopy)
|
||||
ntocopy=RTFSL_CFG_NUMBUFFERS-1;
|
||||
ANSImemcpy(b+1,b,ntocopy);
|
||||
}
|
||||
#endif
|
||||
b[0]=bufferhandle;
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
unsigned long rtfsl_sec2cluster(unsigned long sector)
|
||||
{
|
||||
if (sector < rtfsl.current_dr.firstclblock)
|
||||
return 0;
|
||||
return 2+(sector-rtfsl.current_dr.firstclblock)/rtfsl.current_dr.secpalloc;
|
||||
}
|
||||
|
||||
|
||||
unsigned long rtfsl_cl2sector(unsigned long cluster)
|
||||
{
|
||||
unsigned long cl;
|
||||
if (cluster > 1)
|
||||
cl = rtfsl.current_dr.firstclblock + (cluster - 2)*rtfsl.current_dr.secpalloc;
|
||||
else
|
||||
cl=0;
|
||||
return cl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int rtfsl_diskopen(void) /*__apifn__*/
|
||||
{
|
||||
unsigned char *sector_buffer;
|
||||
unsigned char i,*b;
|
||||
int rval;
|
||||
|
||||
|
||||
ANSImemset(&rtfsl, 0, sizeof(rtfsl));
|
||||
rtfsl.pcurrent_buffer_pool=rtfsl_sector_buffer;
|
||||
// ANSImemset(&rtfsl.current_dr, 0, sizeof(rtfsl.current_dr));
|
||||
/* Initialize a stack we use to age buffer usage. The bottom of the stack is the least recently used handle */
|
||||
for(i=0;i<RTFSL_CFG_NUMBUFFERS;i++)
|
||||
rtfsl.buffer_pool_agingstack[i]=i;
|
||||
/* Check for MBR */
|
||||
rval=rtfsl_read_sectors(0,1,rtfsl.pcurrent_buffer_pool);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
sector_buffer=rtfsl.pcurrent_buffer_pool;
|
||||
#if (RTFSL_INCLUDE_MBR_SUPPORT)
|
||||
if (sector_buffer[511]==0xaa)
|
||||
{
|
||||
if (sector_buffer[510]==0x55
|
||||
#if (INCLUDE_WINDEV)
|
||||
|| sector_buffer[510]==0x66
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int i;
|
||||
unsigned char *p=§or_buffer[446];
|
||||
for(i=0; rtfsl.current_dr.partition_base==0 && i < 4; i++,p+=16)
|
||||
{
|
||||
int j;
|
||||
unsigned char p_type = *(p+4);
|
||||
for (j = 0; j < sizeof(dos_partition_types);j++)
|
||||
{
|
||||
if(p_type==dos_partition_types[j])
|
||||
{
|
||||
rtfsl.current_dr.partition_base = to_ULONG (p+8);
|
||||
rtfsl.current_dr.partition_size = to_ULONG (p+12);
|
||||
rval=rtfsl_read_sectors(rtfsl.current_dr.partition_base,1,sector_buffer);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* Check for BPB signature */
|
||||
b=§or_buffer[0];
|
||||
/* The valid bpb test passes for NTFS. So identify NTFS and force jump to zero so the bpb test fails. */
|
||||
/* Check for EXFAT and NTFS */
|
||||
if (ANSImemcmp(b+3, (void *)"EXFAT",4)==0||ANSImemcmp(b+3, (void *)"NTFS",4)==0)
|
||||
{
|
||||
#if (INCLUDE_EXFAT)
|
||||
!!!!!!;
|
||||
#else
|
||||
return RTFSL_ERROR_FORMAT;
|
||||
#endif
|
||||
}
|
||||
if ( (*b!=0xE9) && (*b!=0xEB)
|
||||
#if (INCLUDE_WINDEV)
|
||||
&& (*b!=0xE9) /* E8 BPB signature so volume it is writeable*/
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return RTFSL_ERROR_FORMAT;
|
||||
}
|
||||
|
||||
rtfsl.current_dr.secpalloc = b[0xd];
|
||||
rtfsl.current_dr.numfats = b[0x10];
|
||||
rtfsl.current_dr.bytespsector = to_USHORT(b+0xb) ;
|
||||
rtfsl.current_dr.secreserved = to_USHORT(b+0xe) ;
|
||||
rtfsl.current_dr.numroot = to_USHORT(b+0x11);
|
||||
rtfsl.current_dr.numsecs = to_USHORT(b+0x13);
|
||||
rtfsl.current_dr.secpfat = (unsigned long) to_USHORT(b+0x16);
|
||||
rtfsl.current_dr.bytespcluster = (unsigned long) rtfsl.current_dr.bytespsector*rtfsl.current_dr.secpalloc;
|
||||
rtfsl.current_dr.rootbegin = rtfsl.current_dr.secreserved + rtfsl.current_dr.secpfat*rtfsl.current_dr.numfats;
|
||||
if (rtfsl.current_dr.numsecs==0)
|
||||
rtfsl.current_dr.numsecs = to_ULONG(b+0x20);/*X*/ /* # secs if > 32M (4.0) */
|
||||
if (rtfsl.current_dr.numroot == 0)
|
||||
rtfsl.current_dr.fasize = 8;
|
||||
else
|
||||
{ /* Check the bpb file sys type field. If it was initialized by format use that to determine FAT type */
|
||||
if (ANSImemcmp(b+0x36, (void *)"FAT1",4)==0)
|
||||
{
|
||||
if (*(b + 0x3A) == (unsigned char)'2')
|
||||
#if (RTFSL_INCLUDE_FAT12)
|
||||
rtfsl.current_dr.fasize = 3;
|
||||
#else
|
||||
return RTFSL_ERROR_FORMAT;
|
||||
#endif
|
||||
else
|
||||
if (*(b + 0x3A) == (unsigned char)'6')
|
||||
rtfsl.current_dr.fasize = 4;
|
||||
}
|
||||
else
|
||||
return RTFSL_ERROR_FORMAT;
|
||||
}
|
||||
if (rtfsl.current_dr.fasize == 8)
|
||||
{
|
||||
#if (RTFSL_INCLUDE_FAT32)
|
||||
rtfsl.current_dr.secpfat = to_ULONG(b+0x24);
|
||||
rtfsl.current_dr.flags = to_USHORT(b+0x28);
|
||||
rtfsl.current_dr.rootbegin = to_ULONG(b+0x2c);
|
||||
rtfsl.current_dr.infosec = to_USHORT(b+0x30);
|
||||
rtfsl.current_dr.backup = to_USHORT(b+0x32);
|
||||
/* Read one block */
|
||||
rval=rtfsl_read_sectors(rtfsl.current_dr.partition_base+rtfsl.current_dr.infosec,1,sector_buffer);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
b=sector_buffer;
|
||||
b += 484;
|
||||
#define FSINFOSIG 0x61417272ul
|
||||
if (FSINFOSIG == to_ULONG(b))
|
||||
{
|
||||
rtfsl.current_dr.free_alloc = to_ULONG(b+4);
|
||||
rtfsl.current_dr.next_alloc = to_ULONG(b+8);
|
||||
}
|
||||
else
|
||||
{ /* If the signature is not found default to the beginning of the FAT */
|
||||
rtfsl.current_dr.infosec = 0;
|
||||
rtfsl.current_dr.free_alloc = 0xffffffff;
|
||||
rtfsl.current_dr.next_alloc = 2;
|
||||
|
||||
}
|
||||
#else
|
||||
return RTFSL_ERROR_FORMAT;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{ /* If the signature is not found default to the beginning of the FAT */
|
||||
rtfsl.current_dr.free_alloc = 0xffffffff;
|
||||
rtfsl.current_dr.next_alloc = 2;
|
||||
}
|
||||
|
||||
rtfsl.current_dr.firstclblock = rtfsl.current_dr.secreserved + (unsigned long)rtfsl.current_dr.secpfat*rtfsl.current_dr.numfats;
|
||||
if (rtfsl.current_dr.fasize != 8)
|
||||
rtfsl.current_dr.firstclblock += ((unsigned long)rtfsl.current_dr.numroot*32+rtfsl.current_dr.bytespsector-1)/rtfsl.current_dr.bytespsector;
|
||||
#if (RTFSL_INCLUDE_FAT12)
|
||||
if (rtfsl.current_dr.fasize == 3)
|
||||
{
|
||||
rtfsl.current_dr.end_cluster_marker = 0xff7;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (rtfsl.current_dr.fasize == 4)
|
||||
{
|
||||
rtfsl.current_dr.end_cluster_marker = 0xfff7;
|
||||
}
|
||||
#if (RTFSL_INCLUDE_FAT32)
|
||||
else /* if (rtfsl.current_dr.fasize == 8) */
|
||||
{
|
||||
rtfsl.current_dr.end_cluster_marker = 0x0ffffff7;
|
||||
}
|
||||
#endif
|
||||
rtfsl.current_dr.maxfindex = (unsigned long)(1 + ((rtfsl.current_dr.numsecs-rtfsl.current_dr.firstclblock)/rtfsl.current_dr.secpalloc));
|
||||
{
|
||||
/* Make sure the calculated index doesn't overflow the fat sectors */
|
||||
unsigned long max_index;
|
||||
/* For FAT32 Each block of the fat holds 128 entries so the maximum index is
|
||||
(pdr->secpfat * pdr->drive_info.clpfblock32 (128 for block size 512) )-1; */
|
||||
max_index = (unsigned long) rtfsl.current_dr.secpfat;
|
||||
max_index *= (rtfsl.current_dr.bytespsector*2)/rtfsl.current_dr.fasize;
|
||||
max_index -= 1;
|
||||
if (rtfsl.current_dr.maxfindex > max_index)
|
||||
rtfsl.current_dr.maxfindex = max_index;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int rtfsl_finode_get(struct rtfsl_file *pfile, unsigned long sector, unsigned short index)
|
||||
{
|
||||
unsigned char *sector_buffer;
|
||||
struct rtfsl_dosinode *pdos_inode;
|
||||
int rval;
|
||||
ANSImemset(pfile, 0, sizeof(*pfile));
|
||||
rval=rtfsl_read_sector_buffer(rtfsl.current_dr.partition_base+sector);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
sector_buffer = rtfsl_buffer_address(rval);
|
||||
pfile->sector=sector;
|
||||
pfile->index=index;
|
||||
pdos_inode = (struct rtfsl_dosinode *) sector_buffer;
|
||||
pdos_inode += index;
|
||||
#if (RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
if (rtfsl.rtfsl_current_failsafe_context)
|
||||
{
|
||||
/* Check the journal file for an override directory entry and copy it into the buffer if one is found. */
|
||||
rval=rtfslfs_dirent_remap(rtfsl.current_dr.partition_base+sector,index, pdos_inode,1);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
}
|
||||
#endif
|
||||
pfile->dos_inode = *pdos_inode;
|
||||
if (pfile->dos_inode.fname[0]==0 || (ANSImemcmp(pfile->dos_inode.fname,end_name,8)==0) )
|
||||
pfile->rtfsl_direntry_type =RTFSL_ENTRY_TYPE_EOF;
|
||||
else if (pfile->dos_inode.fname[0]==PCDELETE)
|
||||
pfile->rtfsl_direntry_type =RTFSL_ENTRY_TYPE_ERASED;
|
||||
else
|
||||
{
|
||||
/* Convert Kanji esc character 0x05 to 0xE5 */
|
||||
if (pfile->dos_inode.fname[0]==0x05)
|
||||
pfile->dos_inode.fname[0]=PCDELETE;
|
||||
if (pfile->dos_inode.fattribute== CHICAGO_EXT)
|
||||
pfile->rtfsl_direntry_type =RTFSL_ENTRY_TYPE_LFN;
|
||||
else if (pfile->dos_inode.fattribute&AVOLUME)
|
||||
pfile->rtfsl_direntry_type =RTFSL_ENTRY_TYPE_VOLUME;
|
||||
else if (pfile->dos_inode.fattribute&ADIRENT)
|
||||
pfile->rtfsl_direntry_type =RTFSL_ENTRY_TYPE_DIRECTORY;
|
||||
else
|
||||
{
|
||||
/* Dos file size is set during get, direectory size during open */
|
||||
/* Swap pfile->dos_inode.fsize since we use it a lot */
|
||||
unsigned long l = to_ULONG((unsigned char *)&pfile->dos_inode.fsize);
|
||||
pfile->rtfsl_direntry_type =RTFSL_ENTRY_TYPE_FILE;
|
||||
pfile->dos_inode.fsize=l;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* Load cluster chains set file size if it's a directory */
|
||||
int rtfsl_finode_open(struct rtfsl_file *pfile)
|
||||
{
|
||||
unsigned long current_cluster,chain_length_bytes;
|
||||
long segments;
|
||||
pfile->file_pointer=0;
|
||||
pfile->file_pointer_at_segment_base=0;
|
||||
pfile->segment_size_bytes=0;
|
||||
if (pfile->rtfsl_file_flags & TRTFSFILE_SECTOR_REGION)
|
||||
return 0;
|
||||
else if (pfile->rtfsl_file_flags & TRTFSFILE_ISROOT_DIR)
|
||||
{
|
||||
#if (RTFSL_INCLUDE_FAT32)
|
||||
if (rtfsl.current_dr.fasize==8)
|
||||
current_cluster = rtfsl.current_dr.rootbegin;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
pfile->dos_inode.fsize = rtfsl.current_dr.numroot*32;
|
||||
pfile->cluster_segment_array[0][0]=rtfsl.current_dr.rootbegin;
|
||||
pfile->cluster_segment_array[0][1]=rtfsl.current_dr.rootbegin+pfile->dos_inode.fsize/rtfsl.current_dr.bytespsector;
|
||||
pfile->segment_size_bytes=pfile->dos_inode.fsize;
|
||||
pfile->next_segment_base=0;
|
||||
pfile->rtfsl_file_flags|=TRTFSFILE_SECTOR_REGION;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
current_cluster = to_USHORT((unsigned char *)&pfile->dos_inode.fclusterhi);
|
||||
current_cluster <<= 16;
|
||||
current_cluster |= to_USHORT((unsigned char *)&pfile->dos_inode.fcluster);
|
||||
}
|
||||
if (!current_cluster)
|
||||
return 0;
|
||||
/* Get the first segment */
|
||||
segments = rtfsl_load_next_segment(pfile,current_cluster);
|
||||
if (segments < 0)
|
||||
return (int)segments;
|
||||
/* Traverse the cluster chain, return the total number of segments, &chain_length_clusters and populate pfile->cluster_segment_array with up to RTFSL_CFG_FILE_FRAG_BUFFER_SIZE segments */
|
||||
chain_length_bytes=pfile->segment_size_bytes;
|
||||
if (pfile->cluster_segment_array[RTFSL_CFG_FILE_FRAG_BUFFER_SIZE-1][0])
|
||||
{
|
||||
while (pfile->cluster_segment_array[RTFSL_CFG_FILE_FRAG_BUFFER_SIZE-1][0])
|
||||
{
|
||||
segments = rtfsl_load_next_segment(pfile,0);
|
||||
if (segments < 0)
|
||||
return (int)segments;
|
||||
chain_length_bytes+=pfile->segment_size_bytes;
|
||||
}
|
||||
/* Get the first segment again */
|
||||
pfile->segment_size_bytes=0;
|
||||
pfile->file_pointer_at_segment_base=0;
|
||||
segments=rtfsl_load_next_segment(pfile,current_cluster);
|
||||
if (segments < 0)
|
||||
return (int)segments;
|
||||
}
|
||||
/* Dos file size is set during get, direectory size during open */
|
||||
if (pfile->dos_inode.fattribute & ADIRENT)
|
||||
{
|
||||
pfile->dos_inode.fsize = chain_length_bytes;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtfsl_root_finode_open(struct rtfsl_file *pfile)
|
||||
{
|
||||
ANSImemset(pfile, 0, sizeof(*pfile));
|
||||
pfile->rtfsl_file_flags = TRTFSFILE_ISROOT_DIR|TRTFSFILE_ALLOCATED;
|
||||
pfile->rtfsl_direntry_type=RTFSL_ENTRY_TYPE_DIRECTORY;
|
||||
pfile->dos_inode.fattribute = ADIRENT|TRTFSFILE_ISROOT_DIR;
|
||||
return rtfsl_finode_open(pfile);
|
||||
}
|
||||
/* Returns bytes */
|
||||
long rtfsl_load_next_segment(struct rtfsl_file *pfile,unsigned long current_cluster)
|
||||
{
|
||||
#if (RTFSL_CFG_FILE_FRAG_BUFFER_SIZE>1)
|
||||
long cluster_segments;
|
||||
unsigned long cluster_segment_length;
|
||||
#endif
|
||||
ANSImemset(pfile->cluster_segment_array,0,sizeof(pfile->cluster_segment_array));
|
||||
if (!current_cluster)
|
||||
current_cluster=pfile->next_segment_base;
|
||||
if (!current_cluster)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#if (RTFSL_CFG_FILE_FRAG_BUFFER_SIZE==1)
|
||||
{
|
||||
int length;
|
||||
length = fatop_buff_get_frag(current_cluster, &pfile->next_segment_base,pfile->rtfsl.current_dr.end_cluster_marker);
|
||||
if (length > 0)
|
||||
{
|
||||
pfile->segment_size_bytes = (unsigned long) length*pfile->rtfsl.current_dr.bytespcluster;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return length;
|
||||
}
|
||||
#else
|
||||
/* Traverse the cluster chain, return the total number of segments, &chain_length_clusters and populate pfile->cluster_segment_array with up to RTFSL_CFG_FILE_FRAG_BUFFER_SIZE segments */
|
||||
cluster_segments = (long)rtfsl_load_cluster_chain(current_cluster, &cluster_segment_length, &pfile->next_segment_base, pfile->cluster_segment_array, RTFSL_CFG_FILE_FRAG_BUFFER_SIZE);
|
||||
if (cluster_segments>=0)
|
||||
{
|
||||
pfile->file_pointer_at_segment_base += pfile->segment_size_bytes;
|
||||
cluster_segment_length = cluster_segment_length*rtfsl.current_dr.bytespcluster;
|
||||
pfile->segment_size_bytes=cluster_segment_length;
|
||||
}
|
||||
return cluster_segments;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if (RTFSL_CFG_FILE_FRAG_BUFFER_SIZE>1)
|
||||
/*
|
||||
|
||||
Scan from start_cluster, if chain_length_clusters is zero break out when is hit
|
||||
*/
|
||||
int rtfsl_load_cluster_chain(unsigned long start_cluster, unsigned long *segment_length_clusters, unsigned long *start_next_segment, unsigned long cluster_segment_array[][2], int cluster_segment_array_size)
|
||||
{
|
||||
unsigned long next_cluster;
|
||||
int segment_count;
|
||||
segment_count=0;
|
||||
*segment_length_clusters=0;
|
||||
*start_next_segment=0;
|
||||
ANSImemset(cluster_segment_array,0,sizeof(cluster_segment_array[0])*cluster_segment_array_size);
|
||||
while (start_cluster != 0)
|
||||
{
|
||||
int length;
|
||||
length = fatop_buff_get_frag(start_cluster, &next_cluster,rtfsl.current_dr.end_cluster_marker);
|
||||
if (length < 0)
|
||||
return length;
|
||||
|
||||
if (segment_count<cluster_segment_array_size)
|
||||
{
|
||||
cluster_segment_array[segment_count][0]=start_cluster;
|
||||
cluster_segment_array[segment_count][1]=start_cluster+length-1;
|
||||
if (segment_length_clusters)
|
||||
*segment_length_clusters += length;
|
||||
*start_next_segment=next_cluster;
|
||||
}
|
||||
else
|
||||
break;
|
||||
segment_count += 1;
|
||||
start_cluster=next_cluster;
|
||||
}
|
||||
return segment_count;
|
||||
}
|
||||
#endif
|
||||
int rtfsl_enumerate_file(struct rtfsl_file *pfile,FileScanCallback pCallback, void *puser_data) /*__apifn__*/
|
||||
{
|
||||
unsigned long start_sector,end_sector,nbytes,callback_value;
|
||||
int current_cluster_segment = RTFSL_CFG_FILE_FRAG_BUFFER_SIZE;
|
||||
|
||||
pfile->file_pointer=0;
|
||||
pfile->file_pointer_at_segment_base=0;
|
||||
pfile->segment_size_bytes=0;
|
||||
pfile->next_segment_base=0;
|
||||
pfile->cluster_segment_array[0][0]=0;
|
||||
pfile->next_segment_base = to_USHORT((unsigned char *)&pfile->dos_inode.fclusterhi);
|
||||
pfile->next_segment_base <<= 16;
|
||||
pfile->next_segment_base |= to_USHORT((unsigned char *)&pfile->dos_inode.fcluster);
|
||||
for(;;)
|
||||
{
|
||||
if (current_cluster_segment >= RTFSL_CFG_FILE_FRAG_BUFFER_SIZE)
|
||||
{
|
||||
int rval;
|
||||
rval = rtfsl_load_next_segment(pfile,0);
|
||||
if (rval<= 0)
|
||||
return rval;
|
||||
current_cluster_segment = 0;
|
||||
}
|
||||
if (!pfile->cluster_segment_array[current_cluster_segment][0])
|
||||
break;
|
||||
start_sector=rtfsl_cl2sector(pfile->cluster_segment_array[current_cluster_segment][0]);
|
||||
end_sector=rtfsl_cl2sector(pfile->cluster_segment_array[current_cluster_segment][1])+rtfsl.current_dr.secpalloc-1;
|
||||
nbytes = (end_sector-start_sector+1)*rtfsl.current_dr.bytespsector;
|
||||
if (pfile->file_pointer+nbytes > pfile->dos_inode.fsize)
|
||||
nbytes = pfile->dos_inode.fsize-pfile->file_pointer;
|
||||
if (nbytes==0)
|
||||
return 0;
|
||||
callback_value=pCallback(pfile,start_sector, nbytes, puser_data);
|
||||
if (callback_value==0)
|
||||
return 0;
|
||||
pfile->file_pointer += callback_value;
|
||||
if (pfile->file_pointer >= pfile->dos_inode.fsize)
|
||||
pfile->file_pointer=pfile->dos_inode.fsize;
|
||||
if (callback_value != nbytes ||pfile->file_pointer >= pfile->dos_inode.fsize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
current_cluster_segment += 1;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int rtfsl_enumerate_directory(struct rtfsl_file *pdirectory_file,struct rtfsl_file *pcurrent_entry_file,DirScanCallback pCallback, void *puser_data) /*__apifn__*/
|
||||
{
|
||||
unsigned long sector,start_sector,end_sector,sector_offset;
|
||||
int current_cluster_segment = 0;
|
||||
unsigned short start_index;
|
||||
sector_offset = pdirectory_file->file_pointer/rtfsl.current_dr.bytespsector;
|
||||
start_index = (unsigned short) (pdirectory_file->file_pointer%rtfsl.current_dr.bytespsector)/32;
|
||||
pcurrent_entry_file->rtfsl_direntry_type =RTFSL_ENTRY_TYPE_EOF;
|
||||
for(;;)
|
||||
{
|
||||
if (pdirectory_file->rtfsl_file_flags & TRTFSFILE_SECTOR_REGION)
|
||||
{
|
||||
start_sector=pdirectory_file->cluster_segment_array[current_cluster_segment][0];
|
||||
end_sector = pdirectory_file->cluster_segment_array[current_cluster_segment][1];
|
||||
}
|
||||
#if (RTFSL_INCLUDE_SUBDIRECTORIES)
|
||||
else
|
||||
{
|
||||
start_sector=rtfsl_cl2sector(pdirectory_file->cluster_segment_array[current_cluster_segment][0]);
|
||||
end_sector=rtfsl_cl2sector(pdirectory_file->cluster_segment_array[current_cluster_segment][1])+rtfsl.current_dr.secpalloc-1;
|
||||
|
||||
}
|
||||
#endif
|
||||
if (sector_offset)
|
||||
{
|
||||
unsigned long l = end_sector-start_sector+1;
|
||||
if (sector_offset>l)
|
||||
{
|
||||
sector_offset-=l;
|
||||
end_sector=start_sector-1; /* Dont scan any sectors just advance */
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
start_sector+=sector_offset;
|
||||
}
|
||||
}
|
||||
for (sector=start_sector;sector<=end_sector;sector++)
|
||||
{
|
||||
unsigned short index;
|
||||
for (index=start_index; index < rtfsl.current_dr.bytespsector/32; index++)
|
||||
{
|
||||
int callback_value;
|
||||
rtfsl_finode_get(pcurrent_entry_file, sector, index);
|
||||
pdirectory_file->file_pointer += 32;
|
||||
callback_value=pCallback(pcurrent_entry_file, puser_data);
|
||||
if (callback_value != 0)
|
||||
return callback_value;
|
||||
}
|
||||
start_index=0;
|
||||
}
|
||||
#if (!RTFSL_INCLUDE_SUBDIRECTORIES)
|
||||
break;
|
||||
#else
|
||||
if (pdirectory_file->rtfsl_file_flags & TRTFSFILE_SECTOR_REGION)
|
||||
break;
|
||||
|
||||
else
|
||||
{
|
||||
if (pcurrent_entry_file->rtfsl_direntry_type==RTFSL_ENTRY_TYPE_EOF)
|
||||
break;
|
||||
current_cluster_segment += 1;
|
||||
if (current_cluster_segment >= RTFSL_CFG_FILE_FRAG_BUFFER_SIZE)
|
||||
{
|
||||
int rval;
|
||||
rval = rtfsl_load_next_segment(pdirectory_file,0);
|
||||
if (rval<= 0)
|
||||
break;
|
||||
current_cluster_segment = 0;
|
||||
}
|
||||
if (!pdirectory_file->cluster_segment_array[current_cluster_segment][0])
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fatop_buff_get_frag(unsigned long current_cluster, unsigned long *pnext_cluster, unsigned long max_length)
|
||||
{
|
||||
unsigned long next_cluster,sector,fat12accumulator,last_sector;
|
||||
unsigned long n_contig;
|
||||
unsigned char *sector_buffer;
|
||||
int Fat12ReadState,buffernumber;
|
||||
int byte_offset_in_buffer,bytes_remaining,bytes_per;
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT)
|
||||
int towrite=3;
|
||||
unsigned long writing;
|
||||
unsigned long value;
|
||||
#endif
|
||||
|
||||
n_contig = 1;
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT)
|
||||
writing=current_cluster&RTFSL_MASK_COMMAND;
|
||||
current_cluster=current_cluster&~RTFSL_MASK_COMMAND;
|
||||
value = *pnext_cluster;
|
||||
if (writing==RTFSL_ALLOC_CLUSTER)
|
||||
n_contig=0;
|
||||
#if (RTFSL_INCLUDE_FAT32)
|
||||
rtfsl.current_dr.flags|=RTFSL_FAT_CHANGED_FLAG; /* We have to flush the infosec */
|
||||
#endif
|
||||
#if (RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
if (writing==RTFSL_WRITE_CLUSTER && rtfsl.rtfsl_current_failsafe_context)
|
||||
{
|
||||
return rtfslfs_cluster_map(current_cluster, value);
|
||||
}
|
||||
#endif
|
||||
if (writing!=RTFSL_WRITE_CLUSTER)
|
||||
#endif
|
||||
*pnext_cluster = 0x0;
|
||||
|
||||
Fat12ReadState = 0;
|
||||
fat12accumulator=0;
|
||||
bytes_per=rtfsl.current_dr.fasize/2;
|
||||
#if (RTFSL_INCLUDE_FAT12)
|
||||
if (rtfsl.current_dr.fasize == 3)
|
||||
{
|
||||
unsigned long bytenumber;
|
||||
bytenumber = (current_cluster * 3)/2;
|
||||
sector = bytenumber/rtfsl.current_dr.bytespsector;
|
||||
byte_offset_in_buffer = bytenumber & (rtfsl.current_dr.bytespsector-1);
|
||||
Fat12ReadState=(current_cluster % 2);
|
||||
/*
|
||||
Fat12ReadState==0 - Good to go
|
||||
FatReadstate==1 - Goto FatReadstate3
|
||||
FatReadstate==3 - Start first pass ignoring accumulator and goto state 2
|
||||
FatReadstate==2 - Decrement byte offset and go to state 3 on read state 2 on write
|
||||
*/
|
||||
if (Fat12ReadState==2)
|
||||
{
|
||||
if (bytenumber)
|
||||
bytenumber-=1;
|
||||
else
|
||||
{
|
||||
sector-=1;
|
||||
bytenumber=rtfsl.current_dr.bytespsector-1;
|
||||
}
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT)
|
||||
if (writing==RTFSL_WRITE_CLUSTER)
|
||||
Fat12ReadState=2;
|
||||
else
|
||||
#endif
|
||||
Fat12ReadState=3;
|
||||
}
|
||||
else if (Fat12ReadState==1)
|
||||
#if (0 && RTFSL_INCLUDE_WRITE_SUPPORT)
|
||||
if (writing==RTFSL_WRITE_CLUSTER)
|
||||
; // Fat12ReadState=1;
|
||||
else
|
||||
#endif
|
||||
Fat12ReadState=3;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
sector = current_cluster / (rtfsl.current_dr.bytespsector/bytes_per);
|
||||
byte_offset_in_buffer = (current_cluster & ((rtfsl.current_dr.bytespsector/bytes_per)-1)) * bytes_per;
|
||||
}
|
||||
sector = sector + rtfsl.current_dr.secreserved;
|
||||
last_sector = sector+rtfsl.current_dr.secpfat-1;
|
||||
bytes_remaining = rtfsl.current_dr.bytespsector-byte_offset_in_buffer;
|
||||
buffernumber=rtfsl_read_sector_buffer(rtfsl.current_dr.partition_base+sector);
|
||||
if (buffernumber<0)
|
||||
return buffernumber;
|
||||
sector_buffer = rtfsl_buffer_address(buffernumber);
|
||||
while(n_contig <= max_length)
|
||||
{
|
||||
while (bytes_remaining)
|
||||
{
|
||||
next_cluster=0;
|
||||
if (rtfsl.current_dr.fasize>3)
|
||||
{
|
||||
if (bytes_per==2)
|
||||
{
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT)
|
||||
if (writing==RTFSL_WRITE_CLUSTER)
|
||||
{
|
||||
fr_USHORT(sector_buffer+byte_offset_in_buffer,(unsigned short)value);
|
||||
break;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
next_cluster = (unsigned long)to_USHORT(sector_buffer+byte_offset_in_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT)
|
||||
if (writing==RTFSL_WRITE_CLUSTER)
|
||||
{
|
||||
fr_ULONG(sector_buffer+byte_offset_in_buffer,value);
|
||||
rtfsl_mark_sector_buffer(buffernumber);
|
||||
break;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
next_cluster = (unsigned long)to_ULONG(sector_buffer+byte_offset_in_buffer);
|
||||
}
|
||||
bytes_remaining-=bytes_per;
|
||||
byte_offset_in_buffer+=bytes_per;
|
||||
}
|
||||
#if (RTFSL_INCLUDE_FAT12)
|
||||
else // if (rtfsl.current_dr.fasize == 3)
|
||||
{
|
||||
unsigned char *p,b;
|
||||
bytes_remaining-=1;
|
||||
p=(sector_buffer+byte_offset_in_buffer);
|
||||
b = *p;
|
||||
byte_offset_in_buffer+=1;
|
||||
|
||||
if (Fat12ReadState==0)
|
||||
{
|
||||
Fat12ReadState=1;
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT)
|
||||
if (writing==RTFSL_WRITE_CLUSTER)
|
||||
{
|
||||
*p = (unsigned char )value&0xff;
|
||||
towrite-=2;
|
||||
if (!towrite)
|
||||
break;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
fat12accumulator = b;
|
||||
continue;
|
||||
}
|
||||
else if (Fat12ReadState==1)
|
||||
{
|
||||
Fat12ReadState=2;
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT)
|
||||
if (writing==RTFSL_WRITE_CLUSTER)
|
||||
{
|
||||
*p &= 0xf0;
|
||||
*p |= (unsigned char)(value>>8)&0xf; // next_clusterv[hinibble];
|
||||
if (!--towrite)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
next_cluster = b&0x0f;
|
||||
next_cluster <<= 8;
|
||||
next_cluster |= fat12accumulator;
|
||||
fat12accumulator = (b&0xf0)>>4;
|
||||
}
|
||||
else if (Fat12ReadState==2)
|
||||
{
|
||||
Fat12ReadState=0;
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT)
|
||||
if (writing==RTFSL_WRITE_CLUSTER)
|
||||
{
|
||||
*p = (unsigned char)(value>>4)&0xff; // b = v>>4; next_clusterv[hinibble];
|
||||
towrite-=2;
|
||||
if (!towrite)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
next_cluster = b<<4;
|
||||
next_cluster |= fat12accumulator;
|
||||
}
|
||||
else if (Fat12ReadState==3)
|
||||
{
|
||||
Fat12ReadState=2;
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT)
|
||||
if (writing==RTFSL_WRITE_CLUSTER)
|
||||
{
|
||||
*p &= 0x0f;
|
||||
*p |= (unsigned char)(value&0x0f)<<4;
|
||||
if (!--towrite)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
fat12accumulator = (b&0xf0)>>4; /* hi byte of b to accumulator lo byte of value*/
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if (RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
/* If failsafe is enabled give it a chance to override the cluster number or return the same value, there is no failure condition */
|
||||
if (rtfsl.rtfsl_current_failsafe_context)
|
||||
{
|
||||
unsigned long mapped_cluster;
|
||||
mapped_cluster = rtfslfs_cluster_remap(current_cluster, next_cluster);
|
||||
/* If we are allocating do not report zero valued clusters in the journal file as free or we could overwrite blocks in an uncommitted delete */
|
||||
if (mapped_cluster != next_cluster)
|
||||
{
|
||||
if (mapped_cluster==RTFSL_JOURNALDELETED_CLUSTER)
|
||||
{
|
||||
if (writing==RTFSL_ALLOC_CLUSTER) /* If we are allocating force a nonmatch on next_cluster so we skip the cluster */
|
||||
next_cluster=rtfsl.current_dr.end_cluster_marker;
|
||||
else
|
||||
next_cluster=0;
|
||||
}
|
||||
else
|
||||
next_cluster=mapped_cluster;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT)
|
||||
if (writing==RTFSL_ALLOC_CLUSTER)
|
||||
{
|
||||
if (next_cluster==0)
|
||||
{
|
||||
*pnext_cluster = current_cluster;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (current_cluster==rtfsl.current_dr.maxfindex)
|
||||
{
|
||||
*pnext_cluster = 0;
|
||||
return 0;
|
||||
}
|
||||
current_cluster += 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (n_contig < max_length && next_cluster==(current_cluster+1))
|
||||
{
|
||||
n_contig += 1;
|
||||
current_cluster=next_cluster;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (next_cluster < 2 || next_cluster >= rtfsl.current_dr.end_cluster_marker)
|
||||
{
|
||||
*pnext_cluster = 0;
|
||||
|
||||
}
|
||||
else
|
||||
*pnext_cluster = next_cluster;
|
||||
return (n_contig);
|
||||
}
|
||||
}
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT)
|
||||
if (writing==RTFSL_WRITE_CLUSTER)
|
||||
{
|
||||
int rval;
|
||||
rval=rtfsl_flush_sector_buffer(buffernumber,1);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
if (rtfsl.current_dr.fasize !=3||towrite==0)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (sector >= last_sector)
|
||||
{
|
||||
*pnext_cluster = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
sector += 1;
|
||||
{
|
||||
int rval=rtfsl_read_sector_buffer(rtfsl.current_dr.partition_base+sector);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
sector_buffer = rtfsl_buffer_address(rval);
|
||||
}
|
||||
byte_offset_in_buffer = 0;
|
||||
bytes_remaining = rtfsl.current_dr.bytespsector;
|
||||
}
|
||||
}
|
||||
return n_contig;
|
||||
}
|
563
rtfsliteshell.c
Normal file
563
rtfsliteshell.c
Normal file
@ -0,0 +1,563 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
#include "rtfslitetests.h"
|
||||
#include "stdlib.h"
|
||||
#include "stdio.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define rtp_term_gets gets
|
||||
|
||||
// File load
|
||||
void BootProgressReport(int percent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
char lite_term_buffer[40];
|
||||
int lite_shell_running=0;
|
||||
int lite_shell_help=0;
|
||||
struct _command_list {
|
||||
char *cmd;
|
||||
int (*proc)( int argc, char **argv);
|
||||
char *helpstr;
|
||||
};
|
||||
static int dortfslite_help(int argc,char **argv);
|
||||
static int dortfslite_exit(int argc,char **argv);
|
||||
static int dortfslite_mount(int argc,char **argv);
|
||||
static int dortfslite_lflush(int argc,char **argv);
|
||||
static int dortfslite_dir(int argc,char **argv);
|
||||
static int dortfslite_delete(int argc,char **argv);
|
||||
static int dortfslite_rename(int argc,char **argv);
|
||||
static int dortfslite_chdir(int argc,char **argv);
|
||||
static int dortfslite_mkdir(int argc,char **argv);
|
||||
static int dortfslite_rmdir(int argc,char **argv);
|
||||
static int dortfslite_fill(int argc,char **argv);
|
||||
static int dortfslite_append(int argc,char **argv);
|
||||
static int dortfslite_check(int argc,char **argv);
|
||||
static int dortfslite_randread(int argc,char **argv);
|
||||
static int dortfslite_randwrite(int argc,char **argv);
|
||||
static int dortfslite_filldisk(int argc,char **argv);
|
||||
static int dortfslite_fsstart(int argc,char **argv);
|
||||
static int dortfslite_fsstop(int argc,char **argv);
|
||||
static int dortfslite_fssync(int argc,char **argv);
|
||||
static int dortfslite_fsflush(int argc,char **argv);
|
||||
static int dortfslite_fsrestore(int argc,char **argv);
|
||||
static int dortfslite_load(int argc,char **argv);
|
||||
|
||||
static const struct _command_list command_list[] = {
|
||||
{ "HELP", dortfslite_help, "HELP"},
|
||||
{ "LOAD", dortfslite_load, "LOAD FILENAME"},
|
||||
{ "LMOUNT", dortfslite_mount, "LMOUNT - re-mount rtfs lite drive"},
|
||||
{ "LEXIT", dortfslite_exit, "LEXIT - Exit Lite mode refreshes device mount for rtfs"},
|
||||
{ "LFLUSH", dortfslite_lflush, "LFLUSH - Flush rtfs lite buffers"},
|
||||
{ "DIR", dortfslite_dir, "DIR"},
|
||||
{ "RENAME", dortfslite_rename, "RENAME oldname newname"},
|
||||
{ "DELETE", dortfslite_delete, "DELETE filename"},
|
||||
{ "CHDIR", dortfslite_chdir, "CHDIR path"},
|
||||
{ "MKDIR", dortfslite_mkdir, "MKDIR dirname 0|1 (1 = fragment)"},
|
||||
{ "RMDIR", dortfslite_rmdir, "RMDIR dirname"},
|
||||
{ "FILLPAT", dortfslite_fill, "FILLPAT filename nlongs 0|1 (1=fragment)"},
|
||||
{ "APPENDPAT", dortfslite_append, "APPENDPAT filename nlongs 0|1 (1=fragment)"},
|
||||
{ "READPAT", dortfslite_check, "READPAT filename"},
|
||||
{ "RANDREAD", dortfslite_randread, "RANDREAD filename"},
|
||||
{ "RANDWRITE", dortfslite_randwrite,"RANDWRITE filename"},
|
||||
{ "FILLDISK", dortfslite_filldisk,"FILLDISK filenamebase"},
|
||||
|
||||
{ "FSSTART", dortfslite_fsstart, "FSSTART Start Journaling"},
|
||||
{ "FSSTOP", dortfslite_fsstop, "FSSTOP Stop Journaling"},
|
||||
{ "FSSYNC", dortfslite_fssync, "FSSYNC Sync volume, keep journaling"},
|
||||
{ "FSFLUSH", dortfslite_fsflush, "FSFLUSH Flush journal keep journaling"},
|
||||
{ "FSRESTORE", dortfslite_fsrestore,"FSRESTORE Retore the volume from the journal"},
|
||||
{0,0,0}
|
||||
};
|
||||
|
||||
static void GetUserInput(void);
|
||||
static char *gnext(char *p);
|
||||
static void prompt(void);
|
||||
static void prompt(void);
|
||||
static unsigned char * Convert83tortfslite83(char *to, char *from);
|
||||
|
||||
void rtfslite_shell(void)
|
||||
{
|
||||
lite_shell_running=1;
|
||||
lite_shell_help = 1;
|
||||
if (rtfsl_diskopen()!=0)
|
||||
{
|
||||
PRINTF("Lite disk mount failed can not continue\n");
|
||||
return;
|
||||
}
|
||||
while (lite_shell_running)
|
||||
prompt();
|
||||
}
|
||||
|
||||
|
||||
static int check_args(int argc,int shouldbe);
|
||||
static void check_return(int rval,int shouldbe);
|
||||
|
||||
static int dortfslite_help(int argc,char **argv)
|
||||
{
|
||||
lite_shell_help=1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define LOAD_ADDRESS 0xa0100000
|
||||
#define START_ADDRESS 0xa014d8bc /* iar_start_address */
|
||||
#define STACK_ADDRESS 0xa01937d0 /* cstack limit */
|
||||
typedef void (* JUMPTO)(void);
|
||||
unsigned long rtp_strtoul (
|
||||
const char * str, /** String to be converted. */
|
||||
char ** delimiter, /** Character that stops the convertion. */
|
||||
int base /** Base of return value. */
|
||||
);
|
||||
|
||||
static int get_load_address(unsigned char *filename, unsigned long *loadaddr, unsigned long *stackaddr, unsigned long *startaddr)
|
||||
{
|
||||
int fd,rval;
|
||||
struct rtfsl_statstructure statstruct;
|
||||
char readbuffer [36];
|
||||
*loadaddr= 0xa0100000;
|
||||
*stackaddr=0xa01937d0;
|
||||
*startaddr=0xa014d8bc;
|
||||
fd = rtfsl_open((unsigned char*)filename);
|
||||
if (fd>=0)
|
||||
{
|
||||
rval=rtfsl_read(fd, readbuffer, 36);
|
||||
if (rval < 36)
|
||||
{
|
||||
PRINTF("Read Metadata failed\n");
|
||||
return -1;
|
||||
}
|
||||
/* [0123456789AB][0123456789AB][0123456789AB] 10 digits plus CR LF */
|
||||
readbuffer[10]=0;
|
||||
readbuffer[22]=0;
|
||||
readbuffer[34]=0;
|
||||
|
||||
// *loadaddr=rtp_strtoul(&readbuffer[0], 0, 16);
|
||||
// *stackaddr=rtp_strtoul(&readbuffer[12], 0, 16);
|
||||
// *startaddr=rtp_strtoul(&readbuffer[24], 0, 16);
|
||||
rtfsl_close(fd);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINTF("Meta Data Open failed\n");
|
||||
}
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static JUMPTO go_main;
|
||||
static unsigned long loadaddr, stackaddr, startaddr;
|
||||
int rtfslite_loadfilefromdisk(char *filenambase);
|
||||
static int dortfslite_load(int argc,char **argv)
|
||||
{
|
||||
return rtfslite_loadfilefromdisk(*argv);
|
||||
}
|
||||
extern void TouchScrClose(void);
|
||||
int rtfslite_loadfilefromdisk(char *filenambase)
|
||||
{
|
||||
int rval;
|
||||
char buffer[32];
|
||||
char filename[32];
|
||||
char binfilename[32];
|
||||
char addrfilename[32];
|
||||
loadaddr = LOAD_ADDRESS;
|
||||
|
||||
strcpy(binfilename,filenambase);
|
||||
strcat(binfilename,".BIN");
|
||||
strcpy(addrfilename,filenambase);
|
||||
strcat(addrfilename,".TXT");
|
||||
|
||||
if (get_load_address(Convert83tortfslite83(filename, addrfilename), &loadaddr, &stackaddr, &startaddr)==0)
|
||||
{
|
||||
// PRINTF("Got load addr %s\n", rtp_ultoa (loadaddr, buffer,16));
|
||||
// PRINTF("Got stack addr %s\n", rtp_ultoa (stackaddr, buffer,16));
|
||||
// PRINTF("Got run addr %s\n", rtp_ultoa (startaddr, buffer,16));
|
||||
|
||||
go_main = (JUMPTO) startaddr;
|
||||
Convert83tortfslite83(filename,binfilename);
|
||||
PRINTF("loading file: :%s: \n", filename);
|
||||
rval = rtfsl_load_file(filename, (unsigned long) loadaddr);
|
||||
if (rval==0)
|
||||
{
|
||||
// PRINTF("load file returned %d \n", rval);
|
||||
// TouchScrClose(); /* Disable interrupts before jumping off */
|
||||
// __set_SP(stackaddr);
|
||||
go_main();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int dortfslite_mount(int argc,char **argv)
|
||||
{
|
||||
int rval;
|
||||
rval=rtfsl_diskopen();
|
||||
check_return(rval,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int dortfslite_exit(int argc,char **argv)
|
||||
{
|
||||
lite_shell_running=0;
|
||||
return 0;
|
||||
}
|
||||
static int dortfslite_lflush(int argc,char **argv)
|
||||
{
|
||||
rtfsl_flush_all_buffers();
|
||||
return 0;
|
||||
}
|
||||
static int dortfslite_dir(int argc,char **argv)
|
||||
{
|
||||
struct rtfsl_dstat dstat;
|
||||
if (rtfsl_gfirst(&dstat, 0)==1)
|
||||
{
|
||||
do {
|
||||
if ((dstat.fattribute&(AVOLUME|ADIRENT))==0)
|
||||
{
|
||||
PRINTF("Got file : %s size: %ld \n",dstat.fnameandext,dstat.fsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINTF("Got entry: %s \n",dstat.fnameandext);
|
||||
}
|
||||
} while (rtfsl_gnext(&dstat)==1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int dortfslite_delete(int argc,char **argv)
|
||||
{
|
||||
char filename[12];
|
||||
int rval;
|
||||
if (check_args(argc,1)==0)
|
||||
{
|
||||
rval=rtfsl_delete(Convert83tortfslite83(filename, *argv));
|
||||
check_return(rval,0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int dortfslite_rename(int argc,char **argv)
|
||||
{
|
||||
unsigned char filename[12],tofilename[12];
|
||||
int rval;
|
||||
if (check_args(argc,2)==0)
|
||||
{
|
||||
Convert83tortfslite83((char *)filename, *argv++);
|
||||
Convert83tortfslite83((char *)tofilename, *argv);
|
||||
rval=rtfsl_rename(filename,tofilename);
|
||||
check_return(rval,0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char *shellpathnamearray[8];
|
||||
char shellpathnamestore[8][12];
|
||||
|
||||
static int dortfslite_chdir(int argc,char **argv)
|
||||
{
|
||||
char *p,*pnext;
|
||||
int depth = 0;
|
||||
if (argc==0)
|
||||
{
|
||||
rtfsl_setpath(0);
|
||||
return 0;
|
||||
}
|
||||
p= *argv;
|
||||
while (p)
|
||||
{
|
||||
pnext = strstr(p, "\\");
|
||||
if (pnext)
|
||||
*pnext =0;
|
||||
Convert83tortfslite83(shellpathnamestore[depth],p);
|
||||
shellpathnamearray[depth]=(unsigned char *)shellpathnamestore[depth];
|
||||
shellpathnamearray[depth+1]=0;
|
||||
depth+=1;
|
||||
if (pnext)
|
||||
p=pnext+1;
|
||||
else
|
||||
p=0;
|
||||
}
|
||||
rtfsl_setpath(shellpathnamearray);
|
||||
return 0;
|
||||
}
|
||||
static int dortfslite_mkdir(int argc,char **argv)
|
||||
{
|
||||
char filename[12];
|
||||
int rval;
|
||||
rval=rtfsl_mkdir(Convert83tortfslite83(filename, *argv));
|
||||
check_return(rval,0);
|
||||
return 0;
|
||||
}
|
||||
static int dortfslite_rmdir(int argc,char **argv)
|
||||
{
|
||||
char filename[12];
|
||||
int rval;
|
||||
rval=rtfsl_rmdir(Convert83tortfslite83(filename, *argv));
|
||||
check_return(rval,0);
|
||||
return 0;
|
||||
}
|
||||
static int dortfslite_fill(int argc,char **argv)
|
||||
{
|
||||
char filename[12];
|
||||
int nlongs;
|
||||
int gap;
|
||||
int rval;
|
||||
|
||||
if (check_args(argc,3)==0)
|
||||
{
|
||||
Convert83tortfslite83(filename, *argv++);
|
||||
nlongs = atol(*argv++);
|
||||
gap = atol(*argv++);
|
||||
rval=rtfsltest_file_sequential_write((unsigned char *)filename, 1, gap, nlongs, 0);
|
||||
check_return(rval,0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dortfslite_filldisk(int argc,char **argv)
|
||||
{
|
||||
char filename[12];
|
||||
int rval;
|
||||
|
||||
if (check_args(argc,1)==0)
|
||||
{
|
||||
Convert83tortfslite83(filename, *argv++);
|
||||
rval=rtfsltest_file_fill_drive((unsigned char *)filename);
|
||||
check_return(rval,RTFSL_ERROR_DISK_FULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dortfslite_append(int argc,char **argv)
|
||||
{
|
||||
char filename[12];
|
||||
int nlongs;
|
||||
int gap;
|
||||
int rval;
|
||||
|
||||
if (check_args(argc,3)==0)
|
||||
{
|
||||
Convert83tortfslite83(filename, *argv++);
|
||||
nlongs = atol(*argv++);
|
||||
gap = atol(*argv++);
|
||||
rval=rtfsltest_file_sequential_write((unsigned char *)filename, 1, gap, nlongs, 1);
|
||||
check_return(rval,0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int dortfslite_check(int argc,char **argv)
|
||||
{
|
||||
char filename[12];
|
||||
int rval;
|
||||
if (check_args(argc,1)==0)
|
||||
{
|
||||
Convert83tortfslite83(filename, *argv++);
|
||||
rval=rtfsltest_file_sequential_read((unsigned char *)filename);
|
||||
check_return(rval,0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int dortfslite_randread(int argc,char **argv)
|
||||
{
|
||||
char filename[12];
|
||||
int rval;
|
||||
if (check_args(argc,1)==0)
|
||||
{
|
||||
Convert83tortfslite83(filename, *argv++);
|
||||
rval=rtfsltest_file_random_read((unsigned char *)filename);
|
||||
check_return(rval,0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int dortfslite_randwrite(int argc,char **argv)
|
||||
{
|
||||
char filename[12];
|
||||
int rval;
|
||||
if (check_args(argc,1)==0)
|
||||
{
|
||||
Convert83tortfslite83(filename, *argv++);
|
||||
rval=rtfsltest_file_random_write((unsigned char *)filename);
|
||||
check_return(rval,0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dortfslite_fsstart(int argc,char **argv)
|
||||
{
|
||||
int rval;
|
||||
rval=rtfslfs_start();
|
||||
check_return(rval,0);
|
||||
return 0;
|
||||
}
|
||||
static int dortfslite_fsstop(int argc,char **argv)
|
||||
{
|
||||
int rval;
|
||||
rval=rtfsl_diskopen();
|
||||
check_return(rval,0);
|
||||
return 0;
|
||||
}
|
||||
static int dortfslite_fssync(int argc,char **argv)
|
||||
{
|
||||
int rval;
|
||||
rval=rtfslfs_sync();
|
||||
check_return(rval,0);
|
||||
return 0;
|
||||
}
|
||||
static int dortfslite_fsflush(int argc,char **argv)
|
||||
{
|
||||
int rval;
|
||||
rval=rtfslfs_flush();
|
||||
check_return(rval,0);
|
||||
return 0;
|
||||
}
|
||||
static int dortfslite_fsrestore(int argc,char **argv)
|
||||
{
|
||||
int rval;
|
||||
rval=rtfslfs_restore();
|
||||
check_return(rval,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *err_strings[] = {
|
||||
"RTFSL_ERROR_NONE",
|
||||
"RTFSL_ERROR_ARGS",
|
||||
"RTFSL_ERROR_CONSISTENCY",
|
||||
"RTFSL_ERROR_DIR_FULL",
|
||||
"RTFSL_ERROR_DISK_FULL",
|
||||
"RTFSL_ERROR_FDALLOC",
|
||||
"RTFSL_ERROR_FORMAT",
|
||||
"RTFSL_ERROR_JOURNAL_FULL",
|
||||
"RTFSL_ERROR_JOURNAL_NONE",
|
||||
"RTFSL_ERROR_NOTFOUND",
|
||||
"RTFSL_ERROR_PATH",
|
||||
"RTFSL_ERROR_EXIST",
|
||||
"RTFSL_ERROR_ENOTEMPTY",
|
||||
"RTFSL_ERROR_TEST"};
|
||||
static void check_return(int rval,int shouldbe)
|
||||
{
|
||||
if (rval!=shouldbe)
|
||||
{
|
||||
if (rval < 0)
|
||||
{
|
||||
PRINTF("Returned: %s ", err_strings[-rval]);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINTF("Returned: %d ", rval);
|
||||
}
|
||||
PRINTF(", should be %d\n", shouldbe);
|
||||
}
|
||||
}
|
||||
|
||||
static int check_args(int argc,int shouldbe)
|
||||
{
|
||||
if (argc!=shouldbe)
|
||||
{
|
||||
PRINTF("Please pass %d arguments\n", shouldbe);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ================================ */
|
||||
static void GetUserInput()
|
||||
{
|
||||
rtp_term_gets(lite_term_buffer);
|
||||
}
|
||||
|
||||
static char *gnext(char *p) /*__fn__*/
|
||||
{
|
||||
while (*p==' ') p++; /* GET RID OF LEADING SPACES */
|
||||
while (*p)
|
||||
{
|
||||
if (*p==' ')
|
||||
{
|
||||
*p=0;
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
while (*p==' ') p++; /* GET RID OF Trailing SPACES */
|
||||
if (*p==0)
|
||||
return(0);
|
||||
return (p);
|
||||
}
|
||||
/* ******************************************************************** */
|
||||
/* get next command; process history log */
|
||||
static void prompt(void)
|
||||
{
|
||||
int i;
|
||||
char *cmd,*p;
|
||||
char *args[4];
|
||||
int argc=0;
|
||||
|
||||
if (lite_shell_help)
|
||||
{
|
||||
for (i=0; command_list[i].cmd;i++)
|
||||
{
|
||||
PRINTF("%s\n",command_list[i].helpstr);
|
||||
}
|
||||
lite_shell_help=0;
|
||||
}
|
||||
argc = 0;
|
||||
/* "CMD>" */
|
||||
PRINTF("CMD>");
|
||||
GetUserInput();
|
||||
|
||||
p = cmd = &lite_term_buffer[0];
|
||||
p = gnext(p);
|
||||
/* Keep grabbing tokens until there are none left */
|
||||
while (p)
|
||||
{
|
||||
args[argc++] = p;
|
||||
p = gnext(p);
|
||||
}
|
||||
|
||||
for (i=0; command_list[i].cmd;i++)
|
||||
{
|
||||
if (strcmp(command_list[i].cmd, cmd)==0)
|
||||
{
|
||||
if (command_list[i].proc)
|
||||
command_list[i].proc(argc,args);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static unsigned char * Convert83tortfslite83(char *to, char *from)
|
||||
{
|
||||
int i;
|
||||
char *r=to;
|
||||
for (i =0; i < 8; i++)
|
||||
{
|
||||
if (*from==0||*from=='.')
|
||||
*to++=' ';
|
||||
else
|
||||
*to++=(char)toupper(*from++);
|
||||
}
|
||||
if (*from=='.')
|
||||
from++;
|
||||
for (i =0; i < 3; i++)
|
||||
{
|
||||
if (*from==0)
|
||||
*to++=' ';
|
||||
else
|
||||
*to++=(char)toupper(*from++);
|
||||
}
|
||||
*to=0;
|
||||
return (unsigned char *)r;
|
||||
}
|
24
rtfslitetests.h
Normal file
24
rtfslitetests.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
|
||||
extern unsigned char test_buffer[RTFSL_CFG_MAXBLOCKSIZE];
|
||||
int ut_fill_directory(int leave_n_free);
|
||||
void ut_unfill_directory(unsigned char *name);
|
||||
int ut_release_fragments(int file_fraglen, int gap_fraglen, int numfrags, unsigned long *fragrecord/*[numfrags]*/);
|
||||
int ut_create_fragments(int file_fraglen, int gap_fraglen, int numfrags, unsigned long *fragrecord/*[numfrags]*/);
|
||||
|
||||
int rtfsltest_file_sequential_write(unsigned char*filename, int file_fraglen, int gap_fraglen, int numlongs, int test_append);
|
||||
int rtfsltest_file_fill_drive(unsigned char*filename);
|
||||
int rtfsltest_file_sequential_read(unsigned char*filename);
|
||||
int rtfsltest_file_random_read(unsigned char*filename);
|
||||
int rtfsltest_file_random_write(unsigned char*filename);
|
||||
|
||||
#include <stdio.h>
|
||||
#define PRINTF printf
|
65
rtfslmkdir.c
Normal file
65
rtfslmkdir.c
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
|
||||
|
||||
int rtfsl_mkdir(unsigned char *name) /*__apifn__*/
|
||||
{
|
||||
struct rtfsl_dosinode dotentries[3];
|
||||
int fd,rval;
|
||||
|
||||
rval=rtfsl_create(name,0);
|
||||
if (rval==0)
|
||||
{
|
||||
rval= rtfsl_open(name);
|
||||
if (rval >= 0)
|
||||
{
|
||||
fd=rval;
|
||||
rval = rtfsl_write(fd,0,rtfsl.current_dr.bytespcluster);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
rtfsl_lseek(fd, 0, PSEEK_SET);
|
||||
rval=rtfsl_clzero(rtfsl.rtfsl_files[fd].cluster_segment_array[0][0]);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
ANSImemcpy(&dotentries[0],&rtfsl.rtfsl_files[fd].dos_inode,sizeof(rtfsl.rtfsl_files[fd].dos_inode));
|
||||
ANSImemcpy(&dotentries[1],&rtfsl.rtfsl_files[fd].dos_inode,sizeof(rtfsl.rtfsl_files[fd].dos_inode));
|
||||
dotentries[0].fattribute=ADIRENT;
|
||||
dotentries[1].fattribute=ADIRENT;
|
||||
ANSImemcpy(&dotentries[0].fname,dotname,11);
|
||||
ANSImemcpy(&dotentries[1].fname,dotdotname,11);
|
||||
memset(&dotentries[2].fname,0,11);
|
||||
dotentries[1].fsize = 0;
|
||||
dotentries[0].fsize = 0;
|
||||
#if (RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
if (rtfsl.rtfsl_current_failsafe_context)
|
||||
rtfsl.rtfsl_current_failsafe_context->flags |= RTFSLFS_WRITE_DIRENTRY;
|
||||
#endif
|
||||
|
||||
|
||||
/* Instructs the write operation to poulate "." with "self" and ".." with parent */
|
||||
rtfsl.rtfsl_files[fd].rtfsl_file_flags|=TRTFSFILE_ISMKDIR;
|
||||
rval = rtfsl_write(fd, (unsigned char*)dotentries,96);
|
||||
rtfsl.rtfsl_files[fd].rtfsl_file_flags&=~TRTFSFILE_ISMKDIR;
|
||||
#if (RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
if (rtfsl.rtfsl_current_failsafe_context)
|
||||
rtfsl.rtfsl_current_failsafe_context->flags &= ~RTFSLFS_WRITE_DIRENTRY;
|
||||
#endif
|
||||
if (rval > 0)
|
||||
{
|
||||
rtfsl.rtfsl_files[fd].dos_inode.fattribute=ADIRENT;
|
||||
rtfsl.rtfsl_files[fd].dos_inode.fsize=0;
|
||||
rval=rtfsl_flush(fd);
|
||||
}
|
||||
rtfsl.rtfsl_files[fd].rtfsl_file_flags=0; /* Deallocates the file */
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
85
rtfslopenpath.c
Normal file
85
rtfslopenpath.c
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
struct rtfsl_open_path_structure
|
||||
{
|
||||
int current_index;
|
||||
unsigned char **pathlist;
|
||||
unsigned char *pathentry;
|
||||
};
|
||||
|
||||
static int open_path_callback(struct rtfsl_file const *pcurrent_entry_file, void *puser_data)
|
||||
{
|
||||
if (pcurrent_entry_file->rtfsl_direntry_type==RTFSL_ENTRY_TYPE_DIRECTORY || pcurrent_entry_file->rtfsl_direntry_type==RTFSL_ENTRY_TYPE_FILE)
|
||||
{
|
||||
struct rtfsl_open_path_structure *open_path_structure = (struct rtfsl_open_path_structure *) puser_data;
|
||||
unsigned char *p=open_path_structure->pathentry;
|
||||
if (!p)
|
||||
p=open_path_structure->pathlist[open_path_structure->current_index];
|
||||
if (p&&ANSImemcmp(pcurrent_entry_file->dos_inode.fname,p,11)==0)
|
||||
{
|
||||
open_path_structure->current_index+=1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0; /* Continue */
|
||||
}
|
||||
|
||||
int rtfsl_open_path(unsigned char **pathlist,unsigned char *pentryname, struct rtfsl_file *directory_file, struct rtfsl_file *ptarget_file)
|
||||
{
|
||||
struct rtfsl_open_path_structure open_path_structure;
|
||||
int rval;
|
||||
open_path_structure.current_index=0;
|
||||
open_path_structure.pathlist=pathlist;
|
||||
open_path_structure.pathentry=0;
|
||||
ANSImemset(directory_file,0,sizeof(*directory_file));
|
||||
rval=rtfsl_root_finode_open(directory_file);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
#if(RTFSL_INCLUDE_SUBDIRECTORIES)
|
||||
while (pathlist && pathlist[open_path_structure.current_index])
|
||||
{
|
||||
ANSImemset(ptarget_file,0,sizeof(*ptarget_file));
|
||||
if (directory_file->rtfsl_direntry_type!=RTFSL_ENTRY_TYPE_DIRECTORY)
|
||||
return RTFSL_ERROR_PATH;
|
||||
rval = rtfsl_enumerate_directory(directory_file,ptarget_file, open_path_callback,(void *) &open_path_structure);
|
||||
if (rval < 0)
|
||||
return rval;
|
||||
if (rval==1)
|
||||
{
|
||||
ANSImemcpy(directory_file,ptarget_file,sizeof(*ptarget_file));
|
||||
rval=rtfsl_finode_open(directory_file);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
if (!pathlist[open_path_structure.current_index])
|
||||
break;
|
||||
}
|
||||
else
|
||||
return RTFSL_ERROR_PATH;
|
||||
}
|
||||
#endif
|
||||
if (!pentryname)
|
||||
{
|
||||
ANSImemcpy(ptarget_file,directory_file,sizeof(*ptarget_file));
|
||||
rval=0;
|
||||
}
|
||||
else if (directory_file->rtfsl_direntry_type==RTFSL_ENTRY_TYPE_DIRECTORY)
|
||||
{
|
||||
open_path_structure.pathentry=pentryname;
|
||||
rval=RTFSL_ERROR_NOTFOUND;
|
||||
if (rtfsl_enumerate_directory(directory_file,ptarget_file, open_path_callback,(void *) &open_path_structure)==1)
|
||||
{
|
||||
rval=rtfsl_finode_open(ptarget_file);
|
||||
}
|
||||
}
|
||||
else
|
||||
rval=RTFSL_ERROR_PATH;
|
||||
return rval;
|
||||
}
|
38
rtfslrename.c
Normal file
38
rtfslrename.c
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
|
||||
|
||||
|
||||
int rtfsl_rename(unsigned char *name, unsigned char *newname)
|
||||
{
|
||||
struct rtfsl_file scratch_dir_file;
|
||||
int fd,rval;
|
||||
fd = rtfsl_alloc_fd();
|
||||
if (fd>=0)
|
||||
{
|
||||
rval=rtfsl_open_path(rtfsl.current_dr.pathnamearray,newname,&scratch_dir_file, &rtfsl.rtfsl_files[fd]);
|
||||
if (rval==0)
|
||||
rval=RTFSL_ERROR_EXIST;
|
||||
else
|
||||
{
|
||||
rval=rtfsl_open_path(rtfsl.current_dr.pathnamearray,name,&scratch_dir_file, &rtfsl.rtfsl_files[fd]);
|
||||
if (rval==0)
|
||||
{
|
||||
ANSImemcpy(rtfsl.rtfsl_files[fd].dos_inode.fname,newname,11);
|
||||
rval=rtfsl_flush(fd);
|
||||
}
|
||||
}
|
||||
rtfsl.rtfsl_files[fd].rtfsl_file_flags=0; /* Deallocates the file */
|
||||
}
|
||||
else
|
||||
rval=fd;
|
||||
return rval;
|
||||
}
|
51
rtfslrmdir.c
Normal file
51
rtfslrmdir.c
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
|
||||
|
||||
|
||||
struct rtfsl_rmdir_structure
|
||||
{
|
||||
unsigned long file_pointer;
|
||||
};
|
||||
static int rmdir_callback(struct rtfsl_file const *pcurrent_entry_file, void *puser_data)
|
||||
{
|
||||
struct rtfsl_rmdir_structure *prmdir_structure=(struct rtfsl_rmdir_structure *) puser_data;
|
||||
|
||||
if (prmdir_structure->file_pointer>=64 && (pcurrent_entry_file->rtfsl_direntry_type&RTFSL_ENTRY_AVAILABLE)==0)
|
||||
{
|
||||
return RTFSL_ERROR_ENOTEMPTY;
|
||||
}
|
||||
prmdir_structure->file_pointer+=32;
|
||||
return 0; /* Continue */
|
||||
}
|
||||
|
||||
int rtfsl_rmdir(unsigned char *name) /*__apifn__*/
|
||||
{
|
||||
int fd,rval;
|
||||
struct rtfsl_rmdir_structure rmdir_structure;
|
||||
struct rtfsl_file new_directory_file;
|
||||
|
||||
fd= rtfsl_dir_open(name);
|
||||
if (fd>=0)
|
||||
{
|
||||
rmdir_structure.file_pointer=0;
|
||||
/* returns RTFSL_ERROR_ENOTEMPTY if the directory contains any files or subdirectories */
|
||||
rval = rtfsl_enumerate_directory(&rtfsl.rtfsl_files[fd],&new_directory_file, rmdir_callback,(void *) &rmdir_structure);
|
||||
if(rval>=0)
|
||||
{
|
||||
rtfsl.rtfsl_files[fd].rtfsl_file_flags=0; /* Deallocates the file */
|
||||
rval=_rtfsl_delete(name,ADIRENT);
|
||||
}
|
||||
}
|
||||
else
|
||||
rval=fd;
|
||||
return rval;
|
||||
}
|
200
rtfslsystem.c
Normal file
200
rtfslsystem.c
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
int raw_dev_fd;
|
||||
|
||||
int rtfsl_open_disk(char *raw_dev_name)
|
||||
{
|
||||
raw_dev_fd = open(raw_dev_name,O_RDWR);
|
||||
return raw_dev_fd;
|
||||
}
|
||||
static int rtfsl_dev_seek(unsigned long sector)
|
||||
{
|
||||
unsigned long hi, lo;
|
||||
unsigned long long lhi, llo, result,llbytes;
|
||||
|
||||
llbytes = (unsigned long long) sector;
|
||||
llbytes *= 512;
|
||||
|
||||
lhi = llbytes >> 32;
|
||||
llo = llbytes & 0xffffffff;
|
||||
lo = (unsigned long) llo;
|
||||
hi = (unsigned long) lhi;
|
||||
|
||||
if (lseek64(raw_dev_fd, llbytes, SEEK_SET)!= llbytes)
|
||||
return(-1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
//#include "rtfs.h"
|
||||
#ifdef RTFS_MAJOR_VERSION
|
||||
DDRIVE *rtfsl_p_drive;
|
||||
#endif
|
||||
|
||||
#if (INCLUDE_SDCARD)
|
||||
int SDCARD_blkmedia_io(void *devhandle, void *pdrive, unsigned long sector, void *buffer, unsigned long count, int reading);
|
||||
#endif
|
||||
|
||||
int rtfsl_read_sectors(unsigned long sector, int count, unsigned char *buffer) /*__apifn__*/
|
||||
{
|
||||
#ifdef __linux__
|
||||
unsigned long nbytes, nread;
|
||||
if (rtfsl_dev_seek(sector)==0)
|
||||
{
|
||||
nbytes = (unsigned long)count;
|
||||
nbytes *= 512;
|
||||
|
||||
if ((nread = read(raw_dev_fd,buffer,nbytes)) == nbytes)
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
#endif
|
||||
#ifdef RTFS_MAJOR_VERSION
|
||||
return raw_devio_xfer(rtfsl_p_drive, (sector), buffer,1, TRUE, TRUE)?0:-1000;
|
||||
#endif
|
||||
#if (INCLUDE_SDCARD)
|
||||
return SDCARD_blkmedia_io( (void *) 0, (void *) 0, sector, buffer, count, 1);
|
||||
#endif
|
||||
return -1; // RTFSL_ERROR_IO_ERROR;
|
||||
}
|
||||
int rtfsl_write_sectors(unsigned long sector, int count, unsigned char *buffer) /*__apifn__*/
|
||||
{
|
||||
#ifdef __linux__
|
||||
unsigned long nbytes, nwr;
|
||||
if (rtfsl_dev_seek(sector)==0)
|
||||
{
|
||||
nbytes = (unsigned long)count;
|
||||
nbytes *= 512;
|
||||
|
||||
if ((nwr = write(raw_dev_fd,buffer,nbytes)) == nbytes)
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
#endif
|
||||
#ifdef RTFS_MAJOR_VERSION
|
||||
return raw_devio_xfer(rtfsl_p_drive, (sector), buffer,1, TRUE, FALSE)?0:-1000;
|
||||
#endif
|
||||
#if (INCLUDE_SDCARD)
|
||||
return SDCARD_blkmedia_io( (void *) 0, (void *) 0, sector, buffer, count, 0);
|
||||
#endif
|
||||
return -1; // RTFSL_ERROR_IO_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
When the system needs to date stamp a file it will call this routine
|
||||
to get the current time and date. YOU must modify the shipped routine
|
||||
to support your hardware's time and date routines.
|
||||
*/
|
||||
|
||||
void rtfsl_get_system_date(unsigned short *time, unsigned short *date) /*__apifn__*/
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
/* Windows runtime provides rotuines specifically for this purpose */
|
||||
SYSTEMTIME systemtime;
|
||||
FILETIME filetime;
|
||||
|
||||
GetLocalTime(&systemtime);
|
||||
SystemTimeToFileTime(&systemtime, &filetime);
|
||||
FileTimeToDosDateTime(&filetime, date, time);
|
||||
#else
|
||||
|
||||
#define USE_ANSI_TIME 0 /* Enable if your runtime environment supports ansi time functions */
|
||||
#if (USE_ANSI_TIME)
|
||||
{ /* Use ansi time functions. */
|
||||
struct tm *timeptr;
|
||||
time_t timer;
|
||||
unsigned short year; /* relative to 1980 */
|
||||
unsigned short month; /* 1 - 12 */
|
||||
unsigned short day; /* 1 - 31 */
|
||||
unsigned short hour;
|
||||
unsigned short minute;
|
||||
unsigned short sec; /* Note: seconds are 2 second/per. ie 3 == 6 seconds */
|
||||
|
||||
time(&timer);
|
||||
timeptr = localtime(&timer);
|
||||
|
||||
hour = (unsigned short) timeptr->tm_hour;
|
||||
minute = (unsigned short) timeptr->tm_min;
|
||||
sec = (unsigned short) (timeptr->tm_sec/2);
|
||||
/* Date comes back relative to 1900 (eg 93). The pc wants it relative to
|
||||
1980. so subtract 80 */
|
||||
year = (unsigned short) (timeptr->tm_year-80);
|
||||
month = (unsigned short) (timeptr->tm_mon+1);
|
||||
day = (unsigned short) timeptr->tm_mday;
|
||||
*time = (unsigned short) ( (hour << 11) | (minute << 5) | sec);
|
||||
*date = (unsigned short) ( (year << 9) | (month << 5) | day);
|
||||
}
|
||||
#else /* In not windows and not using ansi time functions use hardwired values. */
|
||||
/* Modify this code if you have a clock calendar chip and can retrieve the values from that device instead */
|
||||
#define hour 19 /* 7:37:28 PM */
|
||||
#define minute 37
|
||||
#define sec 14
|
||||
/* 3-28-2008 */
|
||||
#define year 18 /* relative to 1980 */
|
||||
#define month 3 /* 1 - 12 */
|
||||
#define day 28 /* 1 - 31 */
|
||||
*time = (unsigned short) ( (hour << 11) | (minute << 5) | sec);
|
||||
*date = (unsigned short) ( (year << 9) | (month << 5) | day);
|
||||
#endif
|
||||
|
||||
#endif /* #ifdef WINDOWS #else */
|
||||
}
|
||||
|
||||
|
||||
/* Convert a 32 bit intel item to a portable 32 bit */
|
||||
unsigned long to_ULONG (unsigned char *from) /*__fn__*/
|
||||
{
|
||||
unsigned long res;
|
||||
unsigned long t;
|
||||
t = ((unsigned long) *(from + 3)) & 0xff;
|
||||
res = (t << 24);
|
||||
t = ((unsigned long) *(from + 2)) & 0xff;
|
||||
res |= (t << 16);
|
||||
t = ((unsigned long) *(from + 1)) & 0xff;
|
||||
res |= (t << 8);
|
||||
t = ((unsigned long) *from) & 0xff;
|
||||
res |= t;
|
||||
return(res);
|
||||
}
|
||||
|
||||
/* Convert a 16 bit intel item to a portable 16 bit */
|
||||
unsigned short to_USHORT (unsigned char *from) /*__fn__*/
|
||||
{
|
||||
unsigned short nres;
|
||||
unsigned short t;
|
||||
t = (unsigned short) (((unsigned short) *(from + 1)) & 0xff);
|
||||
nres = (unsigned short) (t << 8);
|
||||
t = (unsigned short) (((unsigned short) *from) & 0xff);
|
||||
nres |= t;
|
||||
return(nres);
|
||||
}
|
||||
|
||||
/* Convert a portable 16 bit to a 16 bit intel item */
|
||||
void fr_USHORT (unsigned char *to, unsigned short from) /*__fn__*/
|
||||
{
|
||||
*to = (unsigned char) (from & 0x00ff);
|
||||
*(to + 1) = (unsigned char) ((from >> 8) & 0x00ff);
|
||||
}
|
||||
|
||||
/* Convert a portable 32 bit to a 32 bit intel item */
|
||||
void fr_ULONG (unsigned char *to, unsigned long from) /*__fn__*/
|
||||
{
|
||||
*to = (unsigned char) (from & 0xff);
|
||||
*(to + 1) = (unsigned char) ((from >> 8) & 0xff);
|
||||
*(to + 2) = (unsigned char) ((from >> 16) & 0xff);
|
||||
*(to + 3) = (unsigned char) ((from >> 24) & 0xff);
|
||||
}
|
96
rtfstlitefileload.c
Normal file
96
rtfstlitefileload.c
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
|
||||
|
||||
struct rtfst_load_structure {
|
||||
unsigned char *bootfile_name;
|
||||
unsigned long load_count;
|
||||
unsigned char *load_address;
|
||||
};
|
||||
|
||||
void BootProgressReport(int percent);
|
||||
static unsigned long file_load_callback (struct rtfsl_file const *pfile, unsigned long start_sector, unsigned long nbytes, void *puser_data)
|
||||
{
|
||||
struct rtfst_load_structure *pload_structure = (struct rtfst_load_structure *) puser_data;
|
||||
unsigned long sector,nbytes_left,bytes_read;
|
||||
unsigned char *load_address;
|
||||
int rval,bytes_to_skip,percent_reported;
|
||||
int n_sectors;
|
||||
int n_bytes;
|
||||
static int done_so_far=0;;
|
||||
|
||||
load_address = pload_structure->load_address + pfile->file_pointer;
|
||||
pload_structure->load_count += nbytes;
|
||||
bytes_read=0;
|
||||
percent_reported = 0;
|
||||
#define BYTES_TO_SKIP (320*240*8) /* 2 frame buffers worth */
|
||||
//#define BYTES_TO_SKIP 0
|
||||
if (done_so_far==0)
|
||||
bytes_to_skip=BYTES_TO_SKIP;
|
||||
else
|
||||
bytes_to_skip=0;
|
||||
n_sectors=1;
|
||||
n_bytes = rtfsl.current_dr.bytespsector;
|
||||
for(sector=start_sector,nbytes_left=nbytes;nbytes_left;sector+=n_sectors,load_address+=n_bytes)
|
||||
{
|
||||
int per_cent = ((nbytes-nbytes_left)*100)/nbytes;
|
||||
done_so_far += bytes_read;
|
||||
if (per_cent >= (percent_reported+10))
|
||||
{
|
||||
BootProgressReport(per_cent);
|
||||
percent_reported = per_cent;
|
||||
}
|
||||
if (bytes_read <= bytes_to_skip)
|
||||
{
|
||||
n_sectors=1;
|
||||
n_bytes = rtfsl.current_dr.bytespsector;
|
||||
rval=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
#define DEFAULT_SIZE_SECTORS 32
|
||||
n_sectors = DEFAULT_SIZE_SECTORS;
|
||||
n_bytes = n_sectors*rtfsl.current_dr.bytespsector;
|
||||
if (n_bytes > nbytes_left)
|
||||
{
|
||||
n_bytes=nbytes_left;
|
||||
n_sectors=(n_bytes+rtfsl.current_dr.bytespsector-1)/rtfsl.current_dr.bytespsector;
|
||||
if (!n_sectors)
|
||||
break;
|
||||
}
|
||||
rval=rtfsl_read_sectors(rtfsl.current_dr.partition_base+sector, n_sectors, load_address);
|
||||
}
|
||||
bytes_read += n_bytes;
|
||||
|
||||
if (rval<0)
|
||||
return rval;
|
||||
if (nbytes_left < rtfsl.current_dr.bytespsector)
|
||||
nbytes_left = 0;
|
||||
else
|
||||
nbytes_left-=n_bytes;
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
int rtfsl_load_file(unsigned char *filename, unsigned long load_address) /*__apifn__*/
|
||||
{
|
||||
struct rtfsl_file root_file,current_entry_file;
|
||||
struct rtfst_load_structure loadstruct;
|
||||
int rval;
|
||||
ANSImemset(&loadstruct,0,sizeof(loadstruct));
|
||||
loadstruct.bootfile_name = filename;
|
||||
loadstruct.load_address=(unsigned char *)load_address;
|
||||
|
||||
rval=rtfsl_open_path(rtfsl.current_dr.pathnamearray,filename,&root_file, ¤t_entry_file);
|
||||
if (rval== 0)
|
||||
rval=rtfsl_enumerate_file(¤t_entry_file,file_load_callback, (void *) &loadstruct);
|
||||
return rval;
|
||||
}
|
322
rtfstlitetestfileio.c
Normal file
322
rtfstlitetestfileio.c
Normal file
@ -0,0 +1,322 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
#include "rtfslitetests.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
#define MAXTESTFRAGS 128
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT)
|
||||
int rtfsltest_file_fill_drive(unsigned char*filename)
|
||||
{
|
||||
int rval;
|
||||
unsigned char filename_indexed[12];
|
||||
char index = 'A';
|
||||
int pos=8;
|
||||
strcpy((char*)filename_indexed,(char*)filename);
|
||||
for(;;)
|
||||
{
|
||||
filename_indexed[pos] = index;
|
||||
if (index == 'Z')
|
||||
{
|
||||
pos += 1;
|
||||
index = 'A';
|
||||
}
|
||||
index++;
|
||||
|
||||
rval=rtfsl_create(filename_indexed,0);
|
||||
if (rval==0)
|
||||
{
|
||||
int fd;
|
||||
unsigned long i;
|
||||
fd = rtfsl_open(filename_indexed);
|
||||
if(fd<0)
|
||||
{
|
||||
rval=fd;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=0;i<1024*1024*1024;i+=1024*1024)
|
||||
{
|
||||
if ((i % 1024*1024*4)==0)
|
||||
{
|
||||
PRINTF("Fill : %8.8ld\r", i);
|
||||
}
|
||||
rval=rtfsl_write(fd,0,1024*1024);
|
||||
if (rval!=1024*1024)
|
||||
{
|
||||
for(;i<1024*1024*1024;i+=512)
|
||||
{
|
||||
PRINTF("Fill : %8.8ld\r", i);
|
||||
rval=rtfsl_write(fd,0,512);
|
||||
if (rval!=512)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
rtfsl_flush(fd);
|
||||
rtfsl_close(fd);
|
||||
}
|
||||
}
|
||||
if (rval!=512)
|
||||
break;
|
||||
}
|
||||
rtfsl_flush_all_buffers();
|
||||
|
||||
return rval;
|
||||
}
|
||||
int rtfsltest_file_sequential_write(unsigned char*filename, int file_fraglen, int gap_fraglen, int numlongs, int test_append)
|
||||
{
|
||||
int rval,numfrags;
|
||||
struct rtfsl_statstructure statstruct;
|
||||
unsigned long fragrecord[MAXTESTFRAGS];
|
||||
|
||||
numfrags=((numlongs*4)+rtfsl.current_dr.bytespcluster-1)/rtfsl.current_dr.bytespcluster;
|
||||
rval=rtfsl_create(filename,0);
|
||||
if (rval==0)
|
||||
{
|
||||
int fd;
|
||||
unsigned long i;
|
||||
if (gap_fraglen)
|
||||
{
|
||||
rval=ut_create_fragments(file_fraglen, gap_fraglen, numfrags, fragrecord);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
}
|
||||
fd = rtfsl_open(filename);
|
||||
if(fd<0)
|
||||
rval=fd;
|
||||
else
|
||||
for(i=0;i<(unsigned long)numlongs;i++)
|
||||
{
|
||||
rval=rtfsl_write(fd, (unsigned char*)&i,4);
|
||||
if (rval!= 4)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (test_append && (i&0x3ff)==0)
|
||||
{
|
||||
rtfsl_flush(fd);
|
||||
rtfsl_close(fd);
|
||||
fd = rtfsl_open(filename);
|
||||
if (fd<0)
|
||||
rval=fd;
|
||||
else
|
||||
rval=(int)rtfsl_lseek(fd,0,PSEEK_END);
|
||||
if (rval< 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(rval>=0)
|
||||
{
|
||||
rtfsl_fstat(fd,&statstruct);
|
||||
if (statstruct.st_size!=(unsigned long)numlongs*4)
|
||||
rval=RTFSL_ERROR_TEST;
|
||||
else
|
||||
rval=0;
|
||||
}
|
||||
if(rval>=0)
|
||||
rval=rtfsl_flush(fd);
|
||||
rtfsl_close(fd);
|
||||
if (gap_fraglen)
|
||||
{
|
||||
rval=ut_release_fragments(file_fraglen, gap_fraglen, numfrags, fragrecord);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
#endif
|
||||
int rtfsltest_file_sequential_read(unsigned char*filename)
|
||||
{
|
||||
int fd,rval;
|
||||
struct rtfsl_statstructure statstruct;
|
||||
|
||||
|
||||
fd = rtfsl_open((unsigned char*)filename);
|
||||
if (fd>=0)
|
||||
{
|
||||
unsigned long i,j;
|
||||
rtfsl_fstat(fd,&statstruct);
|
||||
for(i=0;i<(unsigned long)statstruct.st_size/4;i++)
|
||||
{
|
||||
rval=rtfsl_read(fd, (unsigned char*)&j,4);
|
||||
if (rval!= 4)
|
||||
{
|
||||
PRINTF("Seq: Read Failed at offset == %lu \n",i*4);\
|
||||
return rval;
|
||||
}
|
||||
if (j != i)
|
||||
{
|
||||
PRINTF("Seq: Compare falied at offset == %lu \n",i);
|
||||
return RTFSL_ERROR_TEST;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int rtfsltest_file_random_read(unsigned char*filename)
|
||||
{
|
||||
struct rtfsl_statstructure statstruct;
|
||||
int fd;
|
||||
unsigned long seekoffset;
|
||||
unsigned long r;
|
||||
|
||||
fd = rtfsl_open(filename);
|
||||
if(fd<0)
|
||||
return fd;
|
||||
rtfsl_fstat(fd,&statstruct);
|
||||
PRINTF("Seek read test. Takes a long time to complete \n");
|
||||
for (seekoffset=statstruct.st_size-1;seekoffset>0;seekoffset--)
|
||||
{
|
||||
rtfsl_lseek(fd,0,PSEEK_SET);
|
||||
rtfsl_read(fd,test_buffer,4);
|
||||
rtfsl_lseek(fd,(seekoffset/4)*4,PSEEK_SET);
|
||||
rtfsl_read(fd,(unsigned char *)&r,4);
|
||||
if (r!= seekoffset/4)
|
||||
{
|
||||
PRINTF("\nreade seek test compare error at unsigned long offset %lu\n",seekoffset/4);
|
||||
return RTFSL_ERROR_TEST;
|
||||
}
|
||||
}
|
||||
rtfsl_close(fd);
|
||||
return 0;
|
||||
}
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT)
|
||||
int rtfsltest_file_random_write(unsigned char*filename)
|
||||
{
|
||||
struct rtfsl_statstructure statstruct;
|
||||
int fd;
|
||||
unsigned long seekoffset;
|
||||
unsigned long l,r;
|
||||
unsigned char *pl = (unsigned char *)&l;
|
||||
|
||||
fd = rtfsl_open(filename);
|
||||
if(fd<0)
|
||||
return fd;
|
||||
rtfsl_fstat(fd,&statstruct);
|
||||
PRINTF("Seek write test. Takes a long time to complete \n");
|
||||
for (seekoffset=statstruct.st_size-1;seekoffset>0;seekoffset--)
|
||||
{
|
||||
if ((seekoffset & 0xf) == 0)
|
||||
{
|
||||
PRINTF("seek write test pass %8.8lu\r", seekoffset);
|
||||
}
|
||||
/* Read from the beginning of file to be sure we are seeking */
|
||||
rtfsl_lseek(fd,0,PSEEK_SET);
|
||||
rtfsl_read(fd,test_buffer,4);
|
||||
/* Write one byte of the current unsigned long flipped */
|
||||
rtfsl_lseek(fd,seekoffset,PSEEK_SET);
|
||||
l=(seekoffset/4);
|
||||
pl = (unsigned char *)&l;
|
||||
{
|
||||
*(pl+(seekoffset&0x3)) = ~*(pl+(seekoffset&0x3));
|
||||
rtfsl_write(fd,pl+(seekoffset&0x3),1);
|
||||
}
|
||||
/* Read from the beginning of file to be sure we are seeking */
|
||||
rtfsl_lseek(fd,0,PSEEK_SET);
|
||||
rtfsl_read(fd,test_buffer,4);
|
||||
/* Read the byte and make sure it's what we wrote */
|
||||
rtfsl_lseek(fd,seekoffset,PSEEK_SET);
|
||||
rtfsl_read(fd,test_buffer,1);
|
||||
if (test_buffer[0]!=*(pl+(seekoffset&0x3)))
|
||||
{
|
||||
PRINTF("\nWrite seek test compare error at byte offset %lu\n",seekoffset);
|
||||
return RTFSL_ERROR_TEST;
|
||||
}
|
||||
/* toggle it again and write it back */
|
||||
rtfsl_lseek(fd,seekoffset,PSEEK_SET);
|
||||
*(pl+(seekoffset&0x3)) = ~*(pl+(seekoffset&0x3));
|
||||
rtfsl_write(fd,pl+(seekoffset&0x3),1);
|
||||
|
||||
/* Read from the beginning of file to be sure we are seeking */
|
||||
rtfsl_lseek(fd,0,PSEEK_SET);
|
||||
rtfsl_read(fd,test_buffer,4);
|
||||
rtfsl_lseek(fd,(seekoffset/4)*4,PSEEK_SET);
|
||||
rtfsl_read(fd,(unsigned char *)&r,4);
|
||||
if (r!= seekoffset/4)
|
||||
{
|
||||
PRINTF("\nWrite seek test compare error at unsigned long offset %lu\n",seekoffset/4);
|
||||
return RTFSL_ERROR_TEST;
|
||||
}
|
||||
}
|
||||
rtfsl_flush(fd);
|
||||
rtfsl_close(fd);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (0)
|
||||
|
||||
#if (DOBOOTFILEEST)
|
||||
{
|
||||
int fd;
|
||||
void * load_address = malloc(1000000);
|
||||
rtfsl_load_file(&tdrive,(unsigned char *)BOOTFILENAME, (unsigned long) load_address);
|
||||
#if (DOFILIOREADAPITEST)
|
||||
fd=rtfsl_open((byte*)BOOTFILENAME);
|
||||
if (fd>=0)
|
||||
{
|
||||
int nread;
|
||||
unsigned long total=0;
|
||||
unsigned char *loadimage=(unsigned char *)load_address;
|
||||
rtfsl_fstat(fd,&statstruct);
|
||||
do
|
||||
{
|
||||
nread=rtfsl_read(fd,test_buffer,tdrive.bytespsector);
|
||||
if (nread>0)
|
||||
{
|
||||
total+=nread;
|
||||
if (ANSImemcmp(test_buffer, loadimage, nread)!=0)
|
||||
{
|
||||
PRINTF("Compare failed\n");
|
||||
}
|
||||
loadimage += nread;
|
||||
}
|
||||
} while (nread > 0);
|
||||
if (statstruct.st_size!=total)
|
||||
{
|
||||
PRINTF("filesize == %lu total read == %lu\n",statstruct.st_size,total);
|
||||
}
|
||||
for (seekoffset=1;seekoffset<7;seekoffset++)
|
||||
{
|
||||
for (seekpointer=0; seekpointer<statstruct.st_size;seekpointer += seekoffset)
|
||||
{
|
||||
loadimage=(unsigned char *)load_address;
|
||||
if ((seekpointer & 0x3ff) == 0)
|
||||
{
|
||||
PRINTF("seek test pass %lu pointer: %8.8lu\r", seekoffset, seekpointer);
|
||||
}
|
||||
rtfsl_lseek(fd,0,PSEEK_SET);
|
||||
rtfsl_lseek(fd,seekpointer,PSEEK_SET);
|
||||
rtfsl_read(fd,test_buffer,1);
|
||||
if (test_buffer[0] != *(loadimage+seekpointer))
|
||||
{
|
||||
PRINTF("\nSeek test compare error at %lu\n",seekpointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
PRINTF("load-sequential read-seek-read test completed %lu bytes read and verified\n",statstruct.st_size);
|
||||
}
|
||||
#endif // #if (DOFILIOREADAPITEST)
|
||||
free(load_address);
|
||||
}
|
||||
#endif
|
||||
#if (DOFAILSAFEFLUSHTEST&&RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
rtfslfs_flush();
|
||||
#endif
|
||||
}
|
||||
#endif
|
460
rtfstlitetests.c
Normal file
460
rtfstlitetests.c
Normal file
@ -0,0 +1,460 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
#include "rtfslitetests.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
|
||||
/* Callback instructions */
|
||||
#define ROOT_SCAN_TEST_PRINT_FILE_NAMES 1
|
||||
#define ROOT_SCAN_TEST_BOOTFILETEST 2
|
||||
|
||||
#define BOOTFILENAME "BOOTFILEBIN"
|
||||
#define RENAMEDFILENAME "RENAMEDFILE"
|
||||
extern int writing;
|
||||
static unsigned char *path[4] = {(unsigned char*)"RTFSL ",0,0,0};
|
||||
/*
|
||||
Failsafe test scenarios
|
||||
// Create a directory in the journal but not on the medium rtfs reports no directory exists
|
||||
#define DOFAILSAFEOPENTEST 1
|
||||
#define DOFAILSAFERESTORETEST 0
|
||||
#define DOMKDIRTEST 1
|
||||
#define DORMDIRTEST 0
|
||||
#define DOFAILSAFEFLUSHTEST 0
|
||||
// Restore from the journal. Rtfs reports the directory exists
|
||||
#define DOFAILSAFEOPENTEST 1
|
||||
#define DOFAILSAFERESTORETEST 1
|
||||
#define DOMKDIRTEST 0
|
||||
#define DORMDIRTEST 0
|
||||
#define DOFAILSAFEFLUSHTEST 0
|
||||
// Remove the director and flush the journal. Rtfs still reports the directory exists
|
||||
#define DOFAILSAFEOPENTEST 1
|
||||
#define DOFAILSAFERESTORETEST 1
|
||||
#define DOMKDIRTEST 0
|
||||
#define DORMDIRTEST 0
|
||||
#define DOFAILSAFEFLUSHTEST 1
|
||||
// Restore from the journal. Rtfs reports the directory does not
|
||||
#define DOFAILSAFEOPENTEST 1
|
||||
#define DOFAILSAFERESTORETEST 1
|
||||
#define DOMKDIRTEST 0
|
||||
#define DORMDIRTEST 0
|
||||
#define DOFAILSAFEFLUSHTEST 0
|
||||
|
||||
// Write to the journal file and perform the file read and write tests. There is no record of the fiole in RTFS
|
||||
#define DOFAILSAFEOPENTEST 1
|
||||
#define DOFAILSAFERESTORETEST 0
|
||||
#define DOMKDIRTEST 0
|
||||
#define DORMDIRTEST 0
|
||||
#define DOFILEWRITETEST 1
|
||||
#define DOBOOTFILEEST 1
|
||||
#define DOFILIOREADAPITEST 1
|
||||
#define DOFAILSAFEFLUSHTEST 1
|
||||
|
||||
// Restore from the journal file RTFS sees the file
|
||||
#define DOFAILSAFEOPENTEST 1
|
||||
#define DOFAILSAFERESTORETEST 1
|
||||
|
||||
// Delete the to the journal file. The file is still seen in Rtfs
|
||||
#define DOFAILSAFEOPENTEST 1
|
||||
#define DOFAILSAFERESTORETEST 0
|
||||
#define DOMKDIRTEST 0
|
||||
#define DORMDIRTEST 0
|
||||
#define DOFILEWRITETEST 0
|
||||
#define DOFILEDELETETEST 1
|
||||
#define DOBOOTFILEEST 0
|
||||
#define DOFILIOREADAPITEST 0
|
||||
#define DOFAILSAFEFLUSHTEST 1
|
||||
|
||||
|
||||
// Restore from the journal file RTFS no longer sees the file
|
||||
#define DOFAILSAFEOPENTEST 1
|
||||
#define DOFAILSAFERESTORETEST 1
|
||||
|
||||
*/
|
||||
|
||||
/* Compile tiome options for test selection */
|
||||
#define DOFATSCANTEST 0
|
||||
#define DOROOTSCANTEST 1
|
||||
#define DOROOTGFIRSTSCANTEST 1
|
||||
|
||||
#define DOFAILSAFEFLUSHTEST 0
|
||||
#define DOFAILSAFEOPENTEST 1
|
||||
#define DOFAILSAFESYNCTEST 1
|
||||
#define DOFAILSAFERESTORETEST 1
|
||||
|
||||
#define DOMKDIRTEST 1
|
||||
#define DORMDIRTEST 0
|
||||
|
||||
#define DIRECTORY_FRAGMENT_LENGTH 1 /* One for every other cluster fragmentation but may be larger */
|
||||
#define DIRECTORY_GAP_FRAGMENT_LENGTH 0 /* Zero for no fragments, or the gap between file fragments */
|
||||
|
||||
|
||||
#define WRITETESTNLONGS 10240
|
||||
#define DOFILEWRITETEST 1
|
||||
#define DOSEQUENTIALREADTEST 1
|
||||
#define DOFILERANDOMWRITETEST 0
|
||||
#define FILE_FRAGMENT_LENGTH 1 /* One for every other cluster fragmentation but may be larger */
|
||||
#define FILE_GAP_FRAGMENT_LENGTH 0 /* Zero for no fragments, or the gap between file fragments */
|
||||
#define DOAPPENDTEST 1 /* If 1 the sequential write test closes and seeks to the end every 1000th write */
|
||||
#define DORENAMETEST 1
|
||||
#define DOFILEDELETETEST 0
|
||||
|
||||
#if (DORMDIRTEST&&DOFILEDELETETEST)
|
||||
#error Tests are mutually exclusive
|
||||
#endif
|
||||
#define DOBOOTFILEEST 0
|
||||
#define DOFILIOREADAPITEST 0
|
||||
#define DOFILERANDOMREADTEST 0
|
||||
|
||||
|
||||
#define DOSETPATHTEST 1
|
||||
#define DOMULTICHAINSUBDIRECTORYTEST 0 /* Requires DOSETPATH */
|
||||
#if (RTFSL_INCLUDE_LOAD_ONLY)
|
||||
|
||||
#undef DOFATSCANTEST
|
||||
#undef DOROOTSCANTEST
|
||||
#undef DOROOTGFIRSTSCANTEST
|
||||
#undef DOFAILSAFEFLUSHTEST
|
||||
#undef DOFAILSAFEOPENTEST
|
||||
#undef DOFAILSAFESYNCTEST
|
||||
#undef DOFAILSAFERESTORETEST
|
||||
|
||||
#define DOFATSCANTEST 0
|
||||
#define DOROOTSCANTEST 0
|
||||
#define DOROOTGFIRSTSCANTEST 0
|
||||
#define DOFAILSAFEFLUSHTEST 0
|
||||
#define DOFAILSAFEOPENTEST 0
|
||||
#define DOFAILSAFESYNCTEST 0
|
||||
#define DOFAILSAFERESTORETEST 0
|
||||
|
||||
#undef DOMKDIRTEST
|
||||
#undef DORMDIRTEST
|
||||
#define DOMKDIRTEST 0
|
||||
#define DORMDIRTEST 0
|
||||
|
||||
|
||||
#undef DOFILEWRITETEST
|
||||
#undef DOFILERANDOMWRITETEST
|
||||
#undef DOAPPENDTEST
|
||||
#undef DORENAMETEST
|
||||
#undef DOFILEDELETETEST
|
||||
|
||||
#undef DOSEQUENTIALREADTEST
|
||||
#define DOSEQUENTIALREADTEST 0
|
||||
#define DOFILEWRITETEST 0
|
||||
#define DOFILERANDOMWRITETEST 0
|
||||
#define DOAPPENDTEST 0
|
||||
#define DORENAMETEST 0
|
||||
#define DOFILEDELETETEST 0
|
||||
|
||||
|
||||
#undef DOBOOTFILEEST
|
||||
#undef DOFILIOREADAPITEST
|
||||
#undef DOFILERANDOMREADTEST
|
||||
|
||||
#define DOBOOTFILEEST 1
|
||||
#define DOFILIOREADAPITEST 0
|
||||
#define DOFILERANDOMREADTEST 0
|
||||
|
||||
#undef DOSETPATHTEST
|
||||
#define DOSETPATHTEST 0
|
||||
#undef DOMULTICHAINSUBDIRECTORYTEST
|
||||
#define DOMULTICHAINSUBDIRECTORYTEST 0
|
||||
#endif
|
||||
|
||||
//HEREHERE
|
||||
//.. Test putting next index and bytes free into failsafe buffer so it re-loads
|
||||
//.. Create failsafe load and failsafe sync functions
|
||||
//.. Failsafe representation of info sector update
|
||||
//.. Put checksum of all journalled entities into failsafe file for catching changes outside.
|
||||
//.. Update of multiple fat copies
|
||||
//.. Update of FAT32 info sector fields.
|
||||
//.. done test directory extend
|
||||
//.. test directory extend with fragments
|
||||
//.. done test file append (seek to end and write)
|
||||
//..
|
||||
|
||||
unsigned char test_buffer[RTFSL_CFG_MAXBLOCKSIZE];
|
||||
|
||||
#if (DOFAILSAFETEST&&RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
int rtfslfs_test(void);
|
||||
#endif
|
||||
int rootscan_test_callback(struct rtfsl_file const *pcurrent_entry_file, void *puser_data)
|
||||
{
|
||||
if (puser_data==(void *)ROOT_SCAN_TEST_PRINT_FILE_NAMES)
|
||||
{
|
||||
if (pcurrent_entry_file->rtfsl_direntry_type==RTFSL_ENTRY_TYPE_FILE)
|
||||
{
|
||||
PRINTF("Found file %8.8s.%3.3s\n",pcurrent_entry_file->dos_inode.fname,pcurrent_entry_file->dos_inode.fext);
|
||||
return 2;
|
||||
}
|
||||
else if (pcurrent_entry_file->rtfsl_direntry_type==RTFSL_ENTRY_TYPE_EOF)
|
||||
return 1;
|
||||
else if (pcurrent_entry_file->rtfsl_direntry_type==RTFSL_ENTRY_TYPE_LFN)
|
||||
;
|
||||
else if (pcurrent_entry_file->rtfsl_direntry_type==RTFSL_ENTRY_TYPE_VOLUME)
|
||||
;
|
||||
else if (pcurrent_entry_file->rtfsl_direntry_type==RTFSL_ENTRY_TYPE_DIRECTORY)
|
||||
{
|
||||
PRINTF("Found dir %8.8s.%3.3s\n",pcurrent_entry_file->dos_inode.fname,pcurrent_entry_file->dos_inode.fext);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return 0; /* Continue */
|
||||
}
|
||||
void test_rtfsl_lite(void)
|
||||
{
|
||||
unsigned long fragrecord[32];
|
||||
struct rtfsl_statstructure statstruct;
|
||||
int rval;
|
||||
struct rtfsl_file root_file;
|
||||
rtfsl_diskopen();
|
||||
|
||||
#if (DOFAILSAFEOPENTEST&&RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
rtfsl.rtfsl_current_failsafe_context=&rtfsl.rtfsl_failsafe_context;
|
||||
ANSImemset(rtfsl.rtfsl_current_failsafe_context,0,sizeof(*rtfsl.rtfsl_current_failsafe_context));
|
||||
rtfsl.rtfsl_current_failsafe_context->journal_buffer=rtfsl.rtfslfs_sector_buffer;
|
||||
rtfsl.rtfsl_current_failsafe_context->journal_buffer_size=RTFSL_CFG_FSBUFFERSIZEBYTES;
|
||||
rtfslfs_start();
|
||||
#endif
|
||||
|
||||
#if (DOFAILSAFERESTORETEST&&RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
rtfslfs_restore();
|
||||
rtfsl_setpath(0);
|
||||
rtfsl_mkdir((unsigned char*)"AFTERRESTORE");
|
||||
return;
|
||||
#endif
|
||||
#if (DOFATSCANTEST)
|
||||
{
|
||||
unsigned long maxfindex;
|
||||
unsigned long cluster, next_cluster;
|
||||
long rval;
|
||||
#ifdef RTFSL_MAJOR_VERSION
|
||||
maxfindex=pdr->drive_info.maxfindex;
|
||||
#else
|
||||
maxfindex=pdr->maxfindex;
|
||||
#endif
|
||||
|
||||
for (cluster=2;cluster< maxfindex;cluster++)
|
||||
{
|
||||
next_cluster=cluster+1;
|
||||
rval=fatop_buff_get_frag(&tdrive, cluster|RTFSL_WRITE_CLUSTER, &next_cluster, 1);
|
||||
next_cluster=0;
|
||||
rval=fatop_buff_get_frag(&tdrive, cluster, &next_cluster, 1);
|
||||
if (next_cluster != cluster+1)
|
||||
{
|
||||
PRINTF("error: Cluster %ld: should be %X but returned %X\n", cluster, cluster+1,next_cluster);
|
||||
}
|
||||
}
|
||||
{
|
||||
unsigned long cluster_segment_array[32][2];
|
||||
unsigned long chain_length_clusters,start_next_segment;
|
||||
int i,num_segments;
|
||||
|
||||
num_segments = rtfsl_load_cluster_chain(&tdrive, 2, &chain_length_clusters, &start_next_segment, cluster_segment_array, 32);
|
||||
|
||||
PRINTF(" = %d\n", num_segments);
|
||||
for (i = 0; i < num_segments; i++)
|
||||
{
|
||||
PRINTF("%d: (%ld) - (%ld) \n", i, cluster_segment_array[i][0],cluster_segment_array[i][1]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT&&RTFSL_INCLUDE_SUBDIRECTORIES&&DOSETPATHTEST)
|
||||
{
|
||||
if (rtfsl_mkdir(path[0])<0)
|
||||
{
|
||||
PRINTF("First mkdir failed-assuming path exists\n");
|
||||
}
|
||||
path[1]=0; /* Set default path one layer deep */
|
||||
rtfsl_setpath(path);
|
||||
/* Set up a scenario so the directory entries we create are fragmented - make 4 fragments but test only uses 2 */
|
||||
#if (DIRECTORY_GAP_FRAGMENT_LENGTH&&DOMKDIRTEST)
|
||||
ut_create_fragments(DIRECTORY_FRAGMENT_LENGTH, DIRECTORY_GAP_FRAGMENT_LENGTH, 4, fragrecord/*[numfrags]*/);
|
||||
#endif
|
||||
if (rtfsl_mkdir(path[0])<0)
|
||||
{
|
||||
PRINTF("Second mkdir failed-assuming path exists\n");
|
||||
}
|
||||
path[1]=path[0]; /* Path should be two deep now */
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT&&DOMKDIRTEST&&RTFSL_INCLUDE_SUBDIRECTORIES&&DOSETPATHTEST&&DOMULTICHAINSUBDIRECTORYTEST)
|
||||
ut_fill_directory(0);
|
||||
#endif
|
||||
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT&&RTFSL_INCLUDE_SUBDIRECTORIES&&DOMKDIRTEST)
|
||||
if (rtfsl_mkdir((unsigned char*)"MKDIR MDX")<0)
|
||||
{
|
||||
PRINTF("mkdir test failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT&&DOMKDIRTEST&&DIRECTORY_GAP_FRAGMENT_LENGTH&&RTFSL_INCLUDE_SUBDIRECTORIES&&DOSETPATHTEST&&DOMULTICHAINSUBDIRECTORYTEST)
|
||||
/* Release the clusters we allocate so the directory entries we create were fragmented */
|
||||
ut_release_fragments(DIRECTORY_FRAGMENT_LENGTH, DIRECTORY_GAP_FRAGMENT_LENGTH, 4, fragrecord/*[numfrags]*/);
|
||||
#endif
|
||||
|
||||
#if (DOROOTSCANTEST)
|
||||
{
|
||||
struct rtfsl_file current_entry_file;
|
||||
if (rtfsl_root_finode_open(&root_file) == 0)
|
||||
{
|
||||
int r;
|
||||
do {
|
||||
PRINTF("Calling enum dir \n");
|
||||
r=rtfsl_enumerate_directory(&root_file,¤t_entry_file,rootscan_test_callback,(void *) ROOT_SCAN_TEST_PRINT_FILE_NAMES);
|
||||
} while (r==2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if (DOROOTGFIRSTSCANTEST)
|
||||
if (rtfsl_root_finode_open(&root_file) == 0)
|
||||
{
|
||||
struct rtfsl_dstat dstat;
|
||||
if (rtfsl_gfirst(&dstat, 0)==1)
|
||||
{
|
||||
do {
|
||||
if ((dstat.fattribute&(AVOLUME|ADIRENT))==0)
|
||||
{
|
||||
PRINTF("Got file : %s size: %ld \n",dstat.fnameandext,dstat.fsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINTF("Got entry: %s \n",dstat.fnameandext);
|
||||
}
|
||||
} while (rtfsl_gnext(&dstat)==1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT&&DOFILEWRITETEST)
|
||||
rval=rtfsltest_file_sequential_write((unsigned char *)BOOTFILENAME, FILE_FRAGMENT_LENGTH, FILE_GAP_FRAGMENT_LENGTH, WRITETESTNLONGS, DOAPPENDTEST);
|
||||
if (rval<0)
|
||||
return;
|
||||
#endif
|
||||
#if (DOSEQUENTIALREADTEST)
|
||||
rval=rtfsltest_file_sequential_read((unsigned char *)BOOTFILENAME);
|
||||
if (rval<0)
|
||||
return;
|
||||
#endif
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT&&DOFILEWRITETEST&&DOFILERANDOMWRITETEST)
|
||||
rval=rtfsltest_file_random_write((unsigned char *)BOOTFILENAME);
|
||||
if (rval<0)
|
||||
return;
|
||||
#endif
|
||||
PRINTF("File sequential write-seek-write-seek-read test completed\n");
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT&&DOFILEWRITETEST&&DORENAMETEST)
|
||||
if (rtfsl_rename((unsigned char *)BOOTFILENAME, (unsigned char *)BOOTFILENAME)!=RTFSL_ERROR_EXIST)
|
||||
{
|
||||
PRINTF("Rename should have failed but did not\n");
|
||||
}
|
||||
rtfsl_rename((unsigned char *)BOOTFILENAME, (unsigned char *)RENAMEDFILENAME);
|
||||
#endif
|
||||
#if (DOBOOTFILEEST)
|
||||
{
|
||||
int fd;
|
||||
void * load_address = malloc(1000000);
|
||||
rtfsl_load_file((unsigned char *)BOOTFILENAME, (unsigned long) load_address);
|
||||
#if (DOFILIOREADAPITEST)
|
||||
fd=rtfsl_open((unsigned char*)BOOTFILENAME);
|
||||
if (fd>=0)
|
||||
{
|
||||
int nread;
|
||||
unsigned long total=0;
|
||||
unsigned char *loadimage=(unsigned char *)load_address;
|
||||
rtfsl_fstat(fd,&statstruct);
|
||||
do
|
||||
{
|
||||
nread=rtfsl_read(fd,test_buffer,rtfsl.current_dr.bytespsector);
|
||||
if (nread>0)
|
||||
{
|
||||
total+=nread;
|
||||
if (ANSImemcmp(test_buffer, loadimage, nread)!=0)
|
||||
{
|
||||
PRINTF("Compare failed\n");
|
||||
}
|
||||
loadimage += nread;
|
||||
}
|
||||
} while (nread > 0);
|
||||
if (statstruct.st_size!=total)
|
||||
{
|
||||
PRINTF("filesize == %d total read == %ld\n",statstruct.st_size,total);
|
||||
}
|
||||
#if (DOFILERANDOMREADTEST)
|
||||
{
|
||||
unsigned long seekoffset,seekpointer;
|
||||
for (seekoffset=1;seekoffset<7;seekoffset++)
|
||||
{
|
||||
for (seekpointer=0; seekpointer<statstruct.st_size;seekpointer += seekoffset)
|
||||
{
|
||||
loadimage=(unsigned char *)load_address;
|
||||
if ((seekpointer & 0x3ff) == 0)
|
||||
{
|
||||
PRINTF("seek test pass %d pointer: %8.8ld\r", seekoffset, seekpointer);
|
||||
}
|
||||
rtfsl_lseek(fd,0,PSEEK_SET);
|
||||
rtfsl_lseek(fd,seekpointer,PSEEK_SET);
|
||||
rtfsl_read(fd,test_buffer,1);
|
||||
if (test_buffer[0] != *(loadimage+seekpointer))
|
||||
{
|
||||
PRINTF("\nSeek test compare error at %ld\n",seekpointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
PRINTF("load-sequential read-seek-read test completed %ld bytes read and verified\n",statstruct.st_size);
|
||||
}
|
||||
#endif // #if (DOFILIOREADAPITEST)
|
||||
free(load_address);
|
||||
}
|
||||
#endif
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT&&DORMDIRTEST&&RTFSL_INCLUDE_SUBDIRECTORIES&&DOSETPATHTEST)
|
||||
/* Remove the current working directory */
|
||||
path[1]=0; /* Set default path one layer deep */
|
||||
rtfsl_setpath(path);
|
||||
if (rtfsl_rmdir((unsigned char*)path[0])==0)
|
||||
{
|
||||
PRINTF("rmdir succeeded but it should have failed\n");
|
||||
}
|
||||
path[1]=path[0]; /* Set default path 2 deep */
|
||||
rtfsl_setpath(path);
|
||||
ut_unfill_directory(0);
|
||||
path[1]=0; /* Set default path one layer deep */
|
||||
rtfsl_setpath(path);
|
||||
if (rtfsl_rmdir((unsigned char*)path[0])!=0)
|
||||
{
|
||||
PRINTF("rmdir failed even after cleaning directory\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if (DOFAILSAFESYNCTEST&&DOFAILSAFEFLUSHTEST)
|
||||
#error Mutually exclusive
|
||||
#endif
|
||||
#if (RTFSL_INCLUDE_WRITE_SUPPORT&&RTFSL_INCLUDE_SUBDIRECTORIES&&DOFILEDELETETEST)
|
||||
rtfsl_delete((unsigned char *)BOOTFILENAME);
|
||||
#endif
|
||||
#if (DOFAILSAFEFLUSHTEST&&RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
rtfslfs_flush();
|
||||
#endif
|
||||
#if (DOFAILSAFESYNCTEST&&RTFSL_INCLUDE_FAILSAFE_SUPPORT)
|
||||
rtfslfs_sync();
|
||||
rtfsl_setpath(0);
|
||||
rtfsl_mkdir((unsigned char*)"AFTERSYNC ");
|
||||
rtfslfs_flush();
|
||||
PRINTF("Restore and you will see the \\AFTERSYNC directorty \n");
|
||||
#endif
|
||||
|
||||
}
|
183
rtfstlitetestutils.c
Normal file
183
rtfstlitetestutils.c
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* EBS - RTFS (Real Time File Manager)
|
||||
*
|
||||
* Copyright EBS Inc. 1987-2012
|
||||
* All rights reserved.
|
||||
* This code may not be redistributed in source or linkable object form
|
||||
* without the consent of its author.
|
||||
*/
|
||||
|
||||
#include "rtfslite.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
|
||||
struct ut_fill_structure {
|
||||
int last_index_pointer;
|
||||
int first_free_pointer;
|
||||
int eof_pointer;
|
||||
};
|
||||
|
||||
static int ut_fill_callback(struct rtfsl_file const *pcurrent_entry_file, void *puser_data)
|
||||
{
|
||||
struct ut_fill_structure *fill_structure= (struct ut_fill_structure *) puser_data;
|
||||
{
|
||||
if ((pcurrent_entry_file->rtfsl_direntry_type&RTFSL_ENTRY_AVAILABLE)!=0)
|
||||
{
|
||||
if (fill_structure->first_free_pointer==-1)
|
||||
fill_structure->first_free_pointer=fill_structure->last_index_pointer;
|
||||
if (fill_structure->eof_pointer==-1&&(pcurrent_entry_file->rtfsl_direntry_type&RTFSL_ENTRY_TYPE_EOF))
|
||||
fill_structure->eof_pointer=fill_structure->last_index_pointer;
|
||||
}
|
||||
}
|
||||
fill_structure->last_index_pointer++;
|
||||
return 0; /* Continue */
|
||||
}
|
||||
|
||||
int ut_fill_directory(int leave_n_free)
|
||||
{
|
||||
char name[12];
|
||||
int n_left;
|
||||
ANSImemcpy(name,"TESTNAMEEXT",11);
|
||||
char c='A';
|
||||
int index = 0;
|
||||
int fcount;
|
||||
|
||||
|
||||
fcount = (rtfsl.current_dr.bytespcluster/32);
|
||||
{
|
||||
int fd;
|
||||
int rval;
|
||||
struct ut_fill_structure fill_structure;
|
||||
struct rtfsl_file new_directory_file;
|
||||
|
||||
fill_structure.first_free_pointer =-1;
|
||||
fill_structure.eof_pointer=-1;
|
||||
fill_structure.last_index_pointer=0;
|
||||
fd = rtfsl_alloc_fd();
|
||||
if (fd<0)
|
||||
return fd;
|
||||
rval = rtfsl_open_path(rtfsl.current_dr.pathnamearray,0, &new_directory_file, &rtfsl.rtfsl_files[fd]);
|
||||
if (rval==0)
|
||||
{
|
||||
rval = rtfsl_enumerate_directory(&rtfsl.rtfsl_files[fd],&new_directory_file, ut_fill_callback,(void *) &fill_structure);
|
||||
if(rval<0)
|
||||
return rval;
|
||||
fcount = fill_structure.eof_pointer;
|
||||
if (fill_structure.eof_pointer!=fill_structure.first_free_pointer)
|
||||
return RTFSL_ERROR_TEST; // Warning fill directory will be inaccurate
|
||||
}
|
||||
rtfsl.rtfsl_files[fd].rtfsl_file_flags=0;
|
||||
}
|
||||
n_left = (rtfsl.current_dr.bytespcluster/32)-fcount;
|
||||
while (n_left > leave_n_free)
|
||||
{
|
||||
int rval;
|
||||
name[index]=c;
|
||||
c+=1;
|
||||
if (c >'Z')
|
||||
{
|
||||
c='A';
|
||||
index+=1;
|
||||
}
|
||||
rval=rtfsl_create((unsigned char*)name,0);
|
||||
if (rval<0)
|
||||
return rval;
|
||||
n_left--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unconditional delete all files and subdirectories in the folder.
|
||||
Does not descend. If subdirectories contain information lost clusters will result */
|
||||
void ut_unfill_directory(unsigned char *name)
|
||||
{
|
||||
struct rtfsl_dstat dstat;
|
||||
while (rtfsl_gfirst(&dstat, name)==1)
|
||||
{
|
||||
if ( (rtfsl_gnext(&dstat)==1) && /* ".." */
|
||||
(rtfsl_gnext(&dstat)==1)
|
||||
)
|
||||
_rtfsl_delete(dstat.fnameandext, dstat.fattribute&ADIRENT);
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int ut_release_fragments(int file_fraglen, int gap_fraglen, int numfrags, unsigned long *fragrecord/*[numfrags]*/)
|
||||
{
|
||||
int fragnum,rval;
|
||||
unsigned long cluster,value;
|
||||
value=0;
|
||||
for(fragnum=0; fragnum < numfrags; fragnum++)
|
||||
{
|
||||
for (cluster=*(fragrecord+fragnum); cluster < *(fragrecord+fragnum)+gap_fraglen;cluster++)
|
||||
{
|
||||
/* Use write call to free up gap_fraglen clusters */
|
||||
rval=fatop_buff_get_frag(cluster|RTFSL_WRITE_CLUSTER, &value, 1);
|
||||
if (rval < 0)
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ut_create_fragments(int file_fraglen, int gap_fraglen, int numfrags, unsigned long *fragrecord/*[numfrags]*/)
|
||||
{
|
||||
unsigned long new_start_hint,start_hint,next_cluster,current_cluster,cluster,value;
|
||||
int rval,fragnum,len;
|
||||
if (gap_fraglen==0)
|
||||
return 0;
|
||||
/* */
|
||||
start_hint=2;
|
||||
new_start_hint=0;
|
||||
for(fragnum=0; fragnum < numfrags; fragnum++)
|
||||
{
|
||||
/* Use allocate call to get file_fraglen contiguous clusters, but do not write to the clusters */
|
||||
len=0;
|
||||
current_cluster=0;
|
||||
while (len<file_fraglen)
|
||||
{
|
||||
rval=fatop_buff_get_frag(start_hint|RTFSL_ALLOC_CLUSTER, &next_cluster, 1);
|
||||
if (rval<=0)
|
||||
return rval;
|
||||
start_hint=next_cluster+1;
|
||||
if (current_cluster==0||((current_cluster+1)!=next_cluster))
|
||||
{
|
||||
current_cluster=next_cluster;
|
||||
len=1;
|
||||
}
|
||||
else
|
||||
len += 1;
|
||||
}
|
||||
if (new_start_hint==0)
|
||||
new_start_hint=current_cluster;
|
||||
len=0;
|
||||
current_cluster=0;
|
||||
while (len<gap_fraglen)
|
||||
{
|
||||
rval=fatop_buff_get_frag(start_hint|RTFSL_ALLOC_CLUSTER, &next_cluster, file_fraglen);
|
||||
if (rval<=0)
|
||||
return rval;
|
||||
if (current_cluster==0||((current_cluster+1)!=next_cluster))
|
||||
{
|
||||
current_cluster=next_cluster;
|
||||
len=1;
|
||||
}
|
||||
else
|
||||
len += 1;
|
||||
start_hint=next_cluster+1;
|
||||
}
|
||||
*(fragrecord+fragnum)=current_cluster;
|
||||
/* Use write call to allocate gap_fraglen clusters */
|
||||
value = rtfsl.current_dr.end_cluster_marker|0xf;
|
||||
for (cluster=*(fragrecord+fragnum); cluster < *(fragrecord+fragnum)+gap_fraglen;cluster++)
|
||||
{
|
||||
rval=fatop_buff_get_frag(cluster|RTFSL_WRITE_CLUSTER, &value, 1);
|
||||
if (rval < 0)
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
/* Set next_alloc to the start of our fragment chain so when we allocate we'll start where we wanted to */
|
||||
rtfsl.current_dr.next_alloc=new_start_hint;
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user