URL
https://opencores.org/ocsvn/plasma/plasma/trunk
Subversion Repositories plasma
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 397 to Rev 398
- ↔ Reverse comparison
Rev 397 → Rev 398
/plasma/trunk/kernel/filesys.c
1,767 → 1,749
/*-------------------------------------------------------------------- |
* TITLE: Plasma File System |
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
* DATE CREATED: 4/26/07 |
* FILENAME: filesys.c |
* PROJECT: Plasma CPU core |
* COPYRIGHT: Software placed into the public domain by the author. |
* Software 'as is' without warranty. Author liable for nothing. |
* DESCRIPTION: |
* Plasma File System. Supports RAM, flash, and disk file systems. |
* Possible call tree: |
* OS_fclose() |
* FileFindRecursive() //find the existing file |
* FileOpen() //open root file system |
* FileFind() //find the next level of directory |
* OS_fread() //read the directory file |
* BlockRead() //read blocks of directory |
* MediaBlockRead() //low level read |
* FileOpen() //open next directory |
* OS_fwrite() //write file entry into directory |
* BlockRead() //flush changes to directory |
*--------------------------------------------------------------------*/ |
#ifdef WIN32 |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#define _LIBC |
#endif |
#include "rtos.h" |
|
#define FLASH_SIZE 1024*1024*16 |
#define FLASH_SECTOR_SIZE 1024*128 |
#define FLASH_BLOCK_SIZE 512 |
#define FLASH_LN2_SIZE 9 //2^FLASH_LN2_SIZE == FLASH_BLOCK_SIZE |
#define FLASH_OFFSET FLASH_SECTOR_SIZE //offset to start of flash file system |
|
#define BLOCK_SIZE 512 |
#define FILE_NAME_SIZE 40 |
#define FULL_NAME_SIZE 128 |
#define BLOCK_MALLOC 0x0 |
#define BLOCK_EOF 0xffffffff |
|
typedef enum { |
FILE_MEDIA_RAM, |
FILE_MEDIA_FLASH, |
FILE_MEDIA_DISK |
} OS_MediaType_e; |
|
typedef struct OS_FileEntry_s { |
char name[FILE_NAME_SIZE]; |
uint32 blockIndex; //first block of file |
uint32 modifiedTime; |
uint32 length; |
uint8 isDirectory; |
uint8 attributes; |
uint8 valid; |
uint8 mediaType; |
uint16 blockSize; //Normally BLOCK_SIZE |
} OS_FileEntry_t; |
|
typedef struct OS_Block_s { |
uint32 next; |
uint8 data[4]; |
} OS_Block_t; |
|
struct OS_FILE_s { |
OS_FileEntry_t fileEntry; //written to directory upon OS_fclose() |
uint8 fileModified; |
uint8 blockModified; |
uint32 blockIndex; //index of block |
uint32 blockOffset; //byte offset into block |
uint32 fileOffset; //byte offset into file |
char fullname[FULL_NAME_SIZE]; //includes full path |
OS_Block_t *block; |
OS_Block_t *blockLocal; //local copy for flash or disk file system |
}; |
|
static OS_FileEntry_t rootFileEntry; |
static OS_Mutex_t *mutexFilesys; |
|
// Public prototypes |
#ifndef _FILESYS_ |
typedef struct OS_FILE_s OS_FILE; |
#endif |
OS_FILE *OS_fopen(char *name, char *mode); |
void OS_fclose(OS_FILE *file); |
int OS_fread(void *buffer, int size, int count, OS_FILE *file); |
int OS_fwrite(void *buffer, int size, int count, OS_FILE *file); |
int OS_fseek(OS_FILE *file, int offset, int mode); |
int OS_fmkdir(char *name); |
int OS_fdir(OS_FILE *dir, char name[64]); |
void OS_fdelete(char *name); |
|
|
/***************** Media Functions Start ***********************/ |
#ifdef INCLUDE_FLASH |
#define FLASH_BLOCKS FLASH_SIZE/FLASH_BLOCK_SIZE |
#define FLASH_START (FLASH_OFFSET+FLASH_BLOCKS/8*2)/FLASH_BLOCK_SIZE |
static unsigned char FlashBlockEmpty[FLASH_BLOCKS/8]; |
static unsigned char FlashBlockUsed[FLASH_BLOCKS/8]; |
static int FlashBlock; |
|
//Free unused flash blocks |
static int MediaBlockCleanup(void) |
{ |
int i, sector, block, count=0; |
unsigned char *buf; |
|
printf("FlashCleanup\n"); |
buf = (unsigned char*)malloc(FLASH_SECTOR_SIZE); |
if(buf == NULL) |
return 0; |
for(sector = FLASH_OFFSET / FLASH_SECTOR_SIZE; sector < FLASH_SIZE / FLASH_SECTOR_SIZE; ++sector) |
{ |
FlashRead((uint16*)buf, FLASH_SECTOR_SIZE*sector, FLASH_SECTOR_SIZE); |
if(sector == FLASH_OFFSET / FLASH_SECTOR_SIZE) |
{ |
for(i = 0; i < FLASH_BLOCKS/8; ++i) |
FlashBlockEmpty[i] |= ~FlashBlockUsed[i]; |
memcpy(buf, FlashBlockEmpty, sizeof(FlashBlockEmpty)); |
memset(FlashBlockUsed, 0xff, sizeof(FlashBlockUsed)); |
memset(buf+sizeof(FlashBlockEmpty), 0xff, sizeof(FlashBlockUsed)); |
} |
//Erase empty blocks |
for(block = 0; block < FLASH_SECTOR_SIZE / FLASH_BLOCK_SIZE; ++block) |
{ |
i = sector * FLASH_SECTOR_SIZE / FLASH_BLOCK_SIZE + block; |
if(i < FLASH_BLOCKS/8 && (FlashBlockEmpty[i >> 3] & (1 << (i & 7)))) |
{ |
memset(buf + FLASH_BLOCK_SIZE*block, 0xff, FLASH_BLOCK_SIZE); |
++count; |
} |
} |
FlashErase(FLASH_SECTOR_SIZE * sector); |
FlashWrite((uint16*)buf, FLASH_SECTOR_SIZE * sector, FLASH_SECTOR_SIZE); |
} |
free(buf); |
return count; |
} |
|
|
int MediaBlockInit(void) |
{ |
FlashRead((uint16*)FlashBlockEmpty, FLASH_OFFSET, sizeof(FlashBlockEmpty)); |
FlashRead((uint16*)FlashBlockUsed, FLASH_OFFSET+sizeof(FlashBlockEmpty), |
sizeof(FlashBlockUsed)); |
FlashBlock = FLASH_START; |
return FlashBlockEmpty[FlashBlock >> 3] & (1 << (FlashBlock & 7)); |
} |
#endif |
|
|
static uint32 MediaBlockMalloc(OS_FILE *file) |
{ |
int i, j; |
(void)i; (void)j; |
|
if(file->fileEntry.mediaType == FILE_MEDIA_RAM) |
return (uint32)malloc(file->fileEntry.blockSize); |
#ifdef INCLUDE_FLASH |
//Find empty flash block |
for(i = FlashBlock; i < FLASH_BLOCKS; ++i) |
{ |
if(FlashBlockEmpty[i >> 3] & (1 << (i & 7))) |
{ |
FlashBlock = i + 1; |
FlashBlockEmpty[i >> 3] &= ~(1 << (i & 7)); |
j = i >> 3; |
j &= ~1; |
FlashWrite((uint16*)(FlashBlockEmpty + j), FLASH_OFFSET + j, 2); |
return i; |
} |
} |
|
i = MediaBlockCleanup(); |
if(i == 0) |
return 0; |
FlashBlock = FLASH_START; |
return MediaBlockMalloc(file); |
#else |
return 0; |
#endif |
} |
|
|
static void MediaBlockFree(OS_FILE *file, uint32 blockIndex) |
{ |
if(file->fileEntry.mediaType == FILE_MEDIA_RAM) |
free((void*)blockIndex); |
#ifdef INCLUDE_FLASH |
else |
{ |
int i=blockIndex, j; |
FlashBlockUsed[i >> 3] &= ~(1 << (i & 7)); |
j = i >> 3; |
j &= ~1; |
FlashWrite((uint16*)(FlashBlockUsed + j), FLASH_OFFSET + sizeof(FlashBlockEmpty) + j, 2); |
} |
#endif |
} |
|
|
static void MediaBlockRead(OS_FILE *file, uint32 blockIndex) |
{ |
if(file->fileEntry.mediaType == FILE_MEDIA_RAM) |
file->block = (OS_Block_t*)blockIndex; |
#ifdef INCLUDE_FLASH |
else |
{ |
if(file->blockLocal == NULL) |
file->blockLocal = (OS_Block_t*)malloc(FLASH_BLOCK_SIZE); |
file->block = file->blockLocal; |
FlashRead((uint16*)file->block, blockIndex << FLASH_LN2_SIZE, FLASH_BLOCK_SIZE); |
} |
#endif |
} |
|
|
static void MediaBlockWrite(OS_FILE *file, uint32 blockIndex) |
{ |
(void)file; |
(void)blockIndex; |
#ifdef INCLUDE_FLASH |
if(file->fileEntry.mediaType != FILE_MEDIA_RAM) |
FlashWrite((uint16*)file->block, blockIndex << FLASH_LN2_SIZE, FLASH_BLOCK_SIZE); |
#endif |
} |
|
/***************** Media Functions End *************************/ |
|
// Get the next block and write the old block if it was modified |
static void BlockRead(OS_FILE *file, uint32 blockIndex) |
{ |
uint32 blockIndexSave = blockIndex; |
|
OS_MutexPend(mutexFilesys); |
if(blockIndex == BLOCK_MALLOC) |
{ |
// Get a new block |
blockIndex = MediaBlockMalloc(file); |
if(blockIndex == 0) |
blockIndex = BLOCK_EOF; |
if(file->block) |
{ |
// Set next pointer in previous block |
file->block->next = blockIndex; |
file->blockModified = 1; |
} |
} |
if(file->block && file->blockModified) |
{ |
// Write block back to flash or disk |
MediaBlockWrite(file, file->blockIndex); |
file->blockModified = 0; |
} |
if(blockIndex == BLOCK_EOF) |
{ |
OS_MutexPost(mutexFilesys); |
return; |
} |
file->blockIndex = blockIndex; |
file->blockOffset = 0; |
MediaBlockRead(file, blockIndex); |
if(blockIndexSave == BLOCK_MALLOC) |
{ |
memset(file->block, 0xff, file->fileEntry.blockSize); |
file->blockModified = 1; |
} |
OS_MutexPost(mutexFilesys); |
} |
|
|
int OS_fread(void *buffer, int size, int count, OS_FILE *file) |
{ |
int items, bytes; |
uint8 *buf = (uint8*)buffer; |
|
for(items = 0; items < count; ++items) |
{ |
for(bytes = 0; bytes < size; ++bytes) |
{ |
if(file->fileOffset >= file->fileEntry.length && |
file->fileEntry.isDirectory == 0) |
return items; |
if(file->blockOffset >= file->fileEntry.blockSize - sizeof(uint32)) |
{ |
if(file->block->next == BLOCK_EOF) |
return items; |
BlockRead(file, file->block->next); |
} |
*buf++ = file->block->data[file->blockOffset++]; |
++file->fileOffset; |
} |
} |
return items; |
} |
|
|
int OS_fwrite(void *buffer, int size, int count, OS_FILE *file) |
{ |
int items, bytes; |
uint8 *buf = (uint8*)buffer; |
|
OS_MutexPend(mutexFilesys); |
file->blockModified = 1; |
for(items = 0; items < count; ++items) |
{ |
for(bytes = 0; bytes < size; ++bytes) |
{ |
if(file->blockOffset >= file->fileEntry.blockSize - sizeof(uint32)) |
{ |
if(file->block->next == BLOCK_EOF) |
file->block->next = BLOCK_MALLOC; |
BlockRead(file, file->block->next); |
if(file->blockIndex == BLOCK_EOF) |
{ |
count = 0; |
--items; |
break; |
} |
file->blockModified = 1; |
} |
file->block->data[file->blockOffset++] = *buf++; |
++file->fileOffset; |
} |
} |
file->blockModified = 1; |
file->fileModified = 1; |
if(file->fileOffset > file->fileEntry.length) |
file->fileEntry.length = file->fileOffset; |
OS_MutexPost(mutexFilesys); |
return items; |
} |
|
|
int OS_fseek(OS_FILE *file, int offset, int mode) |
{ |
if(mode == 1) //SEEK_CUR |
offset += file->fileOffset; |
else if(mode == 2) //SEEK_END |
offset += file->fileEntry.length; |
file->fileOffset = offset; |
BlockRead(file, file->fileEntry.blockIndex); |
while(offset > (int)file->fileEntry.blockSize - (int)sizeof(uint32)) |
{ |
BlockRead(file, file->block->next); |
offset -= file->fileEntry.blockSize - (int)sizeof(uint32); |
} |
file->blockOffset = offset; |
return 0; |
} |
|
|
static int FileOpen(OS_FILE *file, char *name, OS_FileEntry_t *fileEntry) |
{ |
memset(file, 0, sizeof(OS_FILE)); |
if(fileEntry == NULL) |
{ |
// Open root file |
memcpy(&file->fileEntry, &rootFileEntry, sizeof(OS_FileEntry_t)); |
} |
else if(fileEntry->valid == 1) |
{ |
// Open existing file |
memcpy(&file->fileEntry, fileEntry, sizeof(OS_FileEntry_t)); |
} |
else |
{ |
// Initialize new file |
file->fileModified = 1; |
file->blockModified = 1; |
memset(&file->fileEntry, 0, sizeof(OS_FileEntry_t)); |
file->fileEntry.isDirectory = 0; |
file->fileEntry.length = 0; |
strncpy(file->fileEntry.name, name, FILE_NAME_SIZE-1); |
file->fileEntry.blockIndex = 0; |
file->fileEntry.valid = 1; |
file->fileEntry.blockSize = fileEntry->blockSize; |
file->fileEntry.mediaType = fileEntry->mediaType; |
} |
BlockRead(file, file->fileEntry.blockIndex); //Get first block |
file->fileEntry.blockIndex = file->blockIndex; |
file->fileOffset = 0; |
if(file->blockIndex == BLOCK_EOF) |
return -1; |
return 0; |
} |
|
|
static int FileFind(OS_FILE *directory, char *name, OS_FileEntry_t *fileEntry) |
{ |
int count, rc = -1; |
uint32 blockIndex, blockOffset; |
uint32 blockIndexEmpty=BLOCK_EOF, blockOffsetEmpty=0; |
|
// Loop through files in directory |
for(;;) |
{ |
blockIndex = directory->blockIndex; |
blockOffset = directory->blockOffset; |
count = OS_fread(fileEntry, sizeof(OS_FileEntry_t), 1, directory); |
if(count == 0 || fileEntry->blockIndex == BLOCK_EOF) |
break; |
if(fileEntry->valid == 1 && strcmp(fileEntry->name, name) == 0) |
{ |
rc = 0; //Found the file in the directory |
break; |
} |
if(fileEntry->valid != 1 && blockIndexEmpty == BLOCK_EOF) |
{ |
blockIndexEmpty = blockIndex; |
blockOffsetEmpty = blockOffset; |
} |
} |
if(rc == 0 || directory->fileEntry.mediaType == FILE_MEDIA_FLASH || |
blockIndexEmpty == BLOCK_EOF) |
{ |
// Backup to start of fileEntry or last entry in directory |
if(directory->blockIndex != blockIndex) |
BlockRead(directory, blockIndex); |
directory->blockOffset = blockOffset; |
} |
else |
{ |
// Backup to empty slot |
if(directory->blockIndex != blockIndexEmpty) |
BlockRead(directory, blockIndexEmpty); |
directory->blockOffset = blockOffsetEmpty; |
} |
return rc; |
} |
|
|
static int FileFindRecursive(OS_FILE *directory, char *name, |
OS_FileEntry_t *fileEntry, char *filename) |
{ |
int rc, length; |
|
rc = FileOpen(directory, NULL, NULL); //Open root directory |
for(;;) |
{ |
if(name[0] == '/') |
++name; |
for(length = 0; length < FILE_NAME_SIZE; ++length) |
{ |
if(name[length] == 0 || name[length] == '/') |
break; |
filename[length] = name[length]; |
} |
filename[length] = 0; |
rc = FileFind(directory, filename, fileEntry); //Find file |
if(rc) |
{ |
// File not found |
fileEntry->mediaType = directory->fileEntry.mediaType; |
fileEntry->blockSize = directory->fileEntry.blockSize; |
fileEntry->valid = 0; |
if(strstr(name, "/") == NULL) |
return rc; |
else |
return -2; //can't find parent directory |
} |
name += length; |
if(name[0]) |
rc = FileOpen(directory, filename, fileEntry); //Open subdir |
else |
break; |
} |
return rc; |
} |
|
|
OS_FILE *OS_fopen(char *name, char *mode) |
{ |
OS_FILE *file; |
OS_FileEntry_t fileEntry; |
OS_FILE dir; |
char filename[FILE_NAME_SIZE]; //Name without directories |
int rc; |
|
if(rootFileEntry.blockIndex == 0) |
{ |
// Mount file system |
mutexFilesys = OS_MutexCreate("filesys"); |
memset(&dir, 0, sizeof(OS_FILE)); |
dir.fileEntry.blockSize = BLOCK_SIZE; |
//dir.fileEntry.mediaType = FILE_MEDIA_FLASH; //Test flash |
BlockRead(&dir, BLOCK_MALLOC); |
strcpy(rootFileEntry.name, "/"); |
rootFileEntry.mediaType = dir.fileEntry.mediaType; |
rootFileEntry.blockIndex = dir.blockIndex; |
rootFileEntry.blockSize = dir.fileEntry.blockSize; |
rootFileEntry.isDirectory = 1; |
BlockRead(&dir, BLOCK_EOF); //Flush data |
#ifdef INCLUDE_FLASH |
file = OS_fopen("flash", "w+"); |
if(file == NULL) |
return NULL; |
file->fileEntry.isDirectory = 1; |
file->fileEntry.mediaType = FILE_MEDIA_FLASH; |
file->fileEntry.blockSize = FLASH_BLOCK_SIZE; |
file->blockLocal = file->block; |
file->block = NULL; |
rc = MediaBlockInit(); |
if(rc == 1) |
BlockRead(file, BLOCK_MALLOC); |
else |
BlockRead(file, FLASH_START); |
file->fileEntry.blockIndex = file->blockIndex; |
OS_fclose(file); |
#endif |
} |
|
file = (OS_FILE*)malloc(sizeof(OS_FILE)); |
if(file == NULL) |
return NULL; |
OS_MutexPend(mutexFilesys); |
if(name[0] == 0 || strcmp(name, "/") == 0) |
{ |
FileOpen(file, NULL, NULL); |
OS_MutexPost(mutexFilesys); |
return file; |
} |
if(mode[0] == 'w') |
{ |
//Don't over write a directory |
fileEntry.isDirectory = 0; |
rc = FileFindRecursive(&dir, name, &fileEntry, filename); |
if(dir.blockLocal) |
free(dir.blockLocal); |
if(rc == 0) |
{ |
if(fileEntry.isDirectory) |
{ |
free(file); |
return NULL; |
} |
OS_fdelete(name); |
} |
} |
rc = FileFindRecursive(&dir, name, &fileEntry, filename); |
if(dir.blockLocal) |
free(dir.blockLocal); |
if(rc == -2 || (rc && mode[0] == 'r')) |
{ |
free(file); |
OS_MutexPost(mutexFilesys); |
return NULL; |
} |
if(rc) |
fileEntry.valid = 0; |
rc = FileOpen(file, filename, &fileEntry); //Open file |
file->fullname[0] = 0; |
/*-------------------------------------------------------------------- |
* TITLE: Plasma File System |
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
* DATE CREATED: 4/26/07 |
* FILENAME: filesys.c |
* PROJECT: Plasma CPU core |
* COPYRIGHT: Software placed into the public domain by the author. |
* Software 'as is' without warranty. Author liable for nothing. |
* DESCRIPTION: |
* Plasma File System. Supports RAM, flash, and disk file systems. |
* Possible call tree: |
* OS_fclose() |
* FileFindRecursive() //find the existing file |
* FileOpen() //open root file system |
* FileFind() //find the next level of directory |
* OS_fread() //read the directory file |
* BlockRead() //read blocks of directory |
* MediaBlockRead() //low level read |
* FileOpen() //open next directory |
* OS_fwrite() //write file entry into directory |
* BlockRead() //flush changes to directory |
*--------------------------------------------------------------------*/ |
#include "rtos.h" |
|
#define FLASH_SIZE 1024*1024*16 |
#define FLASH_SECTOR_SIZE 1024*128 |
#define FLASH_BLOCK_SIZE 512 |
#define FLASH_LN2_SIZE 9 //2^FLASH_LN2_SIZE == FLASH_BLOCK_SIZE |
#define FLASH_OFFSET FLASH_SECTOR_SIZE //offset to start of flash file system |
|
#define BLOCK_SIZE 512 |
#define FILE_NAME_SIZE 40 |
#define FULL_NAME_SIZE 128 |
#define BLOCK_MALLOC 0x0 |
#define BLOCK_EOF 0xffffffff |
|
typedef enum { |
FILE_MEDIA_RAM, |
FILE_MEDIA_FLASH, |
FILE_MEDIA_DISK |
} OS_MediaType_e; |
|
typedef struct OS_FileEntry_s { |
char name[FILE_NAME_SIZE]; |
uint32 blockIndex; //first block of file |
uint32 modifiedTime; |
uint32 length; |
uint8 isDirectory; |
uint8 attributes; |
uint8 valid; |
uint8 mediaType; |
uint16 blockSize; //Normally BLOCK_SIZE |
uint8 pad1, pad2; |
} OS_FileEntry_t; |
|
typedef struct OS_Block_s { |
uint32 next; |
uint8 data[BLOCK_SIZE - sizeof(uint32)]; |
} OS_Block_t; |
|
struct OS_FILE_s { |
OS_FileEntry_t fileEntry; //written to directory upon OS_fclose() |
uint8 fileModified; |
uint8 blockModified; |
uint8 pad1, pad2; |
uint32 blockIndex; //index of block |
uint32 blockOffset; //byte offset into block |
uint32 fileOffset; //byte offset into file |
char fullname[FULL_NAME_SIZE]; //includes full path |
OS_Block_t *block; |
OS_Block_t blockLocal; //local copy for flash or disk file system |
}; |
|
static OS_FileEntry_t rootFileEntry; |
static OS_Mutex_t *mutexFilesys; |
|
// Public prototypes |
#ifndef _FILESYS_ |
typedef struct OS_FILE_s OS_FILE; |
#endif |
OS_FILE *OS_fopen(char *name, char *mode); |
void OS_fclose(OS_FILE *file); |
int OS_fread(void *buffer, int size, int count, OS_FILE *file); |
int OS_fwrite(void *buffer, int size, int count, OS_FILE *file); |
int OS_fseek(OS_FILE *file, int offset, int mode); |
int OS_fmkdir(char *name); |
int OS_fdir(OS_FILE *dir, char name[64]); |
void OS_fdelete(char *name); |
|
|
/***************** Media Functions Start ***********************/ |
#ifdef INCLUDE_FLASH |
#define FLASH_BLOCKS FLASH_SIZE/FLASH_BLOCK_SIZE |
#define FLASH_START (FLASH_OFFSET+FLASH_BLOCKS/8*2)/FLASH_BLOCK_SIZE |
static unsigned char FlashBlockEmpty[FLASH_BLOCKS/8]; |
static unsigned char FlashBlockUsed[FLASH_BLOCKS/8]; |
static int FlashBlock; |
|
//Free unused flash blocks |
static int MediaBlockCleanup(void) |
{ |
int i, sector, block, count=0; |
unsigned char *buf; |
|
printf("FlashCleanup\n"); |
buf = (unsigned char*)malloc(FLASH_SECTOR_SIZE); |
if(buf == NULL) |
return 0; |
for(sector = FLASH_OFFSET / FLASH_SECTOR_SIZE; sector < FLASH_SIZE / FLASH_SECTOR_SIZE; ++sector) |
{ |
FlashRead((uint16*)buf, FLASH_SECTOR_SIZE*sector, FLASH_SECTOR_SIZE); |
if(sector == FLASH_OFFSET / FLASH_SECTOR_SIZE) |
{ |
for(i = 0; i < FLASH_BLOCKS/8; ++i) |
FlashBlockEmpty[i] |= ~FlashBlockUsed[i]; |
memcpy(buf, FlashBlockEmpty, sizeof(FlashBlockEmpty)); |
memset(FlashBlockUsed, 0xff, sizeof(FlashBlockUsed)); |
memset(buf+sizeof(FlashBlockEmpty), 0xff, sizeof(FlashBlockUsed)); |
} |
//Erase empty blocks |
for(block = 0; block < FLASH_SECTOR_SIZE / FLASH_BLOCK_SIZE; ++block) |
{ |
i = sector * FLASH_SECTOR_SIZE / FLASH_BLOCK_SIZE + block; |
if(i < FLASH_BLOCKS/8 && (FlashBlockEmpty[i >> 3] & (1 << (i & 7)))) |
{ |
memset(buf + FLASH_BLOCK_SIZE*block, 0xff, FLASH_BLOCK_SIZE); |
++count; |
} |
} |
FlashErase(FLASH_SECTOR_SIZE * sector); |
FlashWrite((uint16*)buf, FLASH_SECTOR_SIZE * sector, FLASH_SECTOR_SIZE); |
} |
free(buf); |
return count; |
} |
|
|
int MediaBlockInit(void) |
{ |
FlashRead((uint16*)FlashBlockEmpty, FLASH_OFFSET, sizeof(FlashBlockEmpty)); |
FlashRead((uint16*)FlashBlockUsed, FLASH_OFFSET+sizeof(FlashBlockEmpty), |
sizeof(FlashBlockUsed)); |
FlashBlock = FLASH_START; |
return FlashBlockEmpty[FlashBlock >> 3] & (1 << (FlashBlock & 7)); |
} |
#endif |
|
|
static uint32 MediaBlockMalloc(OS_FILE *file) |
{ |
int i, j; |
(void)i; (void)j; |
|
if(file->fileEntry.mediaType == FILE_MEDIA_RAM) |
return (uint32)malloc(file->fileEntry.blockSize); |
#ifdef INCLUDE_FLASH |
//Find empty flash block |
for(i = FlashBlock; i < FLASH_BLOCKS; ++i) |
{ |
if(FlashBlockEmpty[i >> 3] & (1 << (i & 7))) |
{ |
FlashBlock = i + 1; |
FlashBlockEmpty[i >> 3] &= ~(1 << (i & 7)); |
j = i >> 3; |
j &= ~1; |
FlashWrite((uint16*)(FlashBlockEmpty + j), FLASH_OFFSET + j, 2); |
return i; |
} |
} |
|
i = MediaBlockCleanup(); |
if(i == 0) |
return 0; |
FlashBlock = FLASH_START; |
return MediaBlockMalloc(file); |
#else |
return 0; |
#endif |
} |
|
|
static void MediaBlockFree(OS_FILE *file, uint32 blockIndex) |
{ |
if(file->fileEntry.mediaType == FILE_MEDIA_RAM) |
free((void*)blockIndex); |
#ifdef INCLUDE_FLASH |
else |
{ |
int i=blockIndex, j; |
FlashBlockUsed[i >> 3] &= ~(1 << (i & 7)); |
j = i >> 3; |
j &= ~1; |
FlashWrite((uint16*)(FlashBlockUsed + j), FLASH_OFFSET + sizeof(FlashBlockEmpty) + j, 2); |
} |
#endif |
} |
|
|
static void MediaBlockRead(OS_FILE *file, uint32 blockIndex) |
{ |
if(file->fileEntry.mediaType == FILE_MEDIA_RAM) |
file->block = (OS_Block_t*)blockIndex; |
#ifdef INCLUDE_FLASH |
else |
{ |
file->block = &file->blockLocal; |
FlashRead((uint16*)file->block, blockIndex << FLASH_LN2_SIZE, FLASH_BLOCK_SIZE); |
} |
#endif |
} |
|
|
static void MediaBlockWrite(OS_FILE *file, uint32 blockIndex) |
{ |
(void)file; |
(void)blockIndex; |
#ifdef INCLUDE_FLASH |
if(file->fileEntry.mediaType != FILE_MEDIA_RAM) |
FlashWrite((uint16*)file->block, blockIndex << FLASH_LN2_SIZE, FLASH_BLOCK_SIZE); |
#endif |
} |
|
/***************** Media Functions End *************************/ |
|
// Get the next block and write the old block if it was modified |
static void BlockRead(OS_FILE *file, uint32 blockIndex) |
{ |
uint32 blockIndexSave = blockIndex; |
|
OS_MutexPend(mutexFilesys); |
if(blockIndex == BLOCK_MALLOC) |
{ |
// Get a new block |
blockIndex = MediaBlockMalloc(file); |
if(blockIndex == 0) |
blockIndex = BLOCK_EOF; |
if(file->block) |
{ |
// Set next pointer in previous block |
file->block->next = blockIndex; |
file->blockModified = 1; |
} |
} |
if(file->block && file->blockModified) |
{ |
// Write block back to flash or disk |
MediaBlockWrite(file, file->blockIndex); |
file->blockModified = 0; |
} |
if(blockIndex == BLOCK_EOF) |
{ |
OS_MutexPost(mutexFilesys); |
return; |
} |
file->blockIndex = blockIndex; |
file->blockOffset = 0; |
MediaBlockRead(file, blockIndex); |
if(blockIndexSave == BLOCK_MALLOC) |
{ |
memset(file->block, 0xff, file->fileEntry.blockSize); |
file->blockModified = 1; |
} |
OS_MutexPost(mutexFilesys); |
} |
|
|
int OS_fread(void *buffer, int size, int count, OS_FILE *file) |
{ |
int items, bytes; |
uint8 *buf = (uint8*)buffer; |
|
for(items = 0; items < count; ++items) |
{ |
for(bytes = 0; bytes < size; ++bytes) |
{ |
if(file->fileOffset >= file->fileEntry.length && |
file->fileEntry.isDirectory == 0) |
return items; |
if(file->blockOffset >= file->fileEntry.blockSize - sizeof(uint32)) |
{ |
if(file->block->next == BLOCK_EOF) |
return items; |
BlockRead(file, file->block->next); |
} |
*buf++ = file->block->data[file->blockOffset++]; |
++file->fileOffset; |
} |
} |
return items; |
} |
|
|
int OS_fwrite(void *buffer, int size, int count, OS_FILE *file) |
{ |
int items, bytes; |
uint8 *buf = (uint8*)buffer; |
|
OS_MutexPend(mutexFilesys); |
file->blockModified = 1; |
for(items = 0; items < count; ++items) |
{ |
for(bytes = 0; bytes < size; ++bytes) |
{ |
if(file->blockOffset >= file->fileEntry.blockSize - sizeof(uint32)) |
{ |
if(file->block->next == BLOCK_EOF) |
file->block->next = BLOCK_MALLOC; |
BlockRead(file, file->block->next); |
if(file->blockIndex == BLOCK_EOF) |
{ |
count = 0; |
--items; |
break; |
} |
file->blockModified = 1; |
} |
file->block->data[file->blockOffset++] = *buf++; |
++file->fileOffset; |
} |
} |
file->blockModified = 1; |
file->fileModified = 1; |
if(file->fileOffset > file->fileEntry.length) |
file->fileEntry.length = file->fileOffset; |
OS_MutexPost(mutexFilesys); |
return items; |
} |
|
|
int OS_fseek(OS_FILE *file, int offset, int mode) |
{ |
if(mode == 1) //SEEK_CUR |
offset += file->fileOffset; |
else if(mode == 2) //SEEK_END |
offset += file->fileEntry.length; |
file->fileOffset = offset; |
BlockRead(file, file->fileEntry.blockIndex); |
while(offset > (int)file->fileEntry.blockSize - (int)sizeof(uint32)) |
{ |
BlockRead(file, file->block->next); |
offset -= file->fileEntry.blockSize - (int)sizeof(uint32); |
} |
file->blockOffset = offset; |
return 0; |
} |
|
|
static int FileOpen(OS_FILE *file, char *name, OS_FileEntry_t *fileEntry) |
{ |
memset(file, 0, sizeof(OS_FILE)); |
if(fileEntry == NULL) |
{ |
// Open root file |
memcpy(&file->fileEntry, &rootFileEntry, sizeof(OS_FileEntry_t)); |
} |
else if(fileEntry->valid == 1) |
{ |
// Open existing file |
memcpy(&file->fileEntry, fileEntry, sizeof(OS_FileEntry_t)); |
} |
else |
{ |
// Initialize new file |
file->fileModified = 1; |
file->blockModified = 1; |
memset(&file->fileEntry, 0, sizeof(OS_FileEntry_t)); |
file->fileEntry.isDirectory = 0; |
file->fileEntry.length = 0; |
strncpy(file->fileEntry.name, name, FILE_NAME_SIZE-1); |
file->fileEntry.blockIndex = 0; |
file->fileEntry.valid = 1; |
file->fileEntry.blockSize = fileEntry->blockSize; |
file->fileEntry.mediaType = fileEntry->mediaType; |
} |
BlockRead(file, file->fileEntry.blockIndex); //Get first block |
file->fileEntry.blockIndex = file->blockIndex; |
file->fileOffset = 0; |
if(file->blockIndex == BLOCK_EOF) |
return -1; |
return 0; |
} |
|
|
static int FileFind(OS_FILE *directory, char *name, OS_FileEntry_t *fileEntry) |
{ |
int count, rc = -1; |
uint32 blockIndex, blockOffset; |
uint32 blockIndexEmpty=BLOCK_EOF, blockOffsetEmpty=0; |
|
// Loop through files in directory |
for(;;) |
{ |
blockIndex = directory->blockIndex; |
blockOffset = directory->blockOffset; |
count = OS_fread(fileEntry, sizeof(OS_FileEntry_t), 1, directory); |
if(count == 0 || fileEntry->blockIndex == BLOCK_EOF) |
break; |
if(fileEntry->valid == 1 && strcmp(fileEntry->name, name) == 0) |
{ |
rc = 0; //Found the file in the directory |
break; |
} |
if(fileEntry->valid != 1 && blockIndexEmpty == BLOCK_EOF) |
{ |
blockIndexEmpty = blockIndex; |
blockOffsetEmpty = blockOffset; |
} |
} |
if(rc == 0 || directory->fileEntry.mediaType == FILE_MEDIA_FLASH || |
blockIndexEmpty == BLOCK_EOF) |
{ |
// Backup to start of fileEntry or last entry in directory |
if(directory->blockIndex != blockIndex) |
BlockRead(directory, blockIndex); |
directory->blockOffset = blockOffset; |
} |
else |
{ |
// Backup to empty slot |
if(directory->blockIndex != blockIndexEmpty) |
BlockRead(directory, blockIndexEmpty); |
directory->blockOffset = blockOffsetEmpty; |
} |
return rc; |
} |
|
|
static int FileFindRecursive(OS_FILE *directory, char *name, |
OS_FileEntry_t *fileEntry, char *filename) |
{ |
int rc, length; |
|
rc = FileOpen(directory, NULL, NULL); //Open root directory |
for(;;) |
{ |
if(name[0] == '/') |
++name; |
for(length = 0; length < FILE_NAME_SIZE; ++length) |
{ |
if(name[length] == 0 || name[length] == '/') |
break; |
filename[length] = name[length]; |
} |
filename[length] = 0; |
rc = FileFind(directory, filename, fileEntry); //Find file |
if(rc) |
{ |
// File not found |
fileEntry->mediaType = directory->fileEntry.mediaType; |
fileEntry->blockSize = directory->fileEntry.blockSize; |
fileEntry->valid = 0; |
if(strstr(name, "/") == NULL) |
return rc; |
else |
return -2; //can't find parent directory |
} |
name += length; |
if(name[0]) |
rc = FileOpen(directory, filename, fileEntry); //Open subdir |
else |
break; |
} |
return rc; |
} |
|
|
OS_FILE *OS_fopen(char *name, char *mode) |
{ |
OS_FILE *file; |
OS_FileEntry_t fileEntry; |
OS_FILE dir; |
char filename[FILE_NAME_SIZE]; //Name without directories |
int rc; |
|
//printf("OS_fopen(%s)\n", name); |
if(rootFileEntry.blockIndex == 0) |
{ |
// Mount file system |
mutexFilesys = OS_MutexCreate("filesys"); |
memset(&dir, 0, sizeof(OS_FILE)); |
dir.fileEntry.blockSize = BLOCK_SIZE; |
//dir.fileEntry.mediaType = FILE_MEDIA_FLASH; //Test flash |
BlockRead(&dir, BLOCK_MALLOC); |
strcpy(rootFileEntry.name, "/"); |
rootFileEntry.mediaType = dir.fileEntry.mediaType; |
rootFileEntry.blockIndex = dir.blockIndex; |
rootFileEntry.blockSize = dir.fileEntry.blockSize; |
rootFileEntry.isDirectory = 1; |
BlockRead(&dir, BLOCK_EOF); //Flush data |
#ifdef INCLUDE_FLASH |
file = OS_fopen("flash", "w+"); |
if(file == NULL) |
return NULL; |
file->fileEntry.isDirectory = 1; |
file->fileEntry.mediaType = FILE_MEDIA_FLASH; |
file->fileEntry.blockSize = FLASH_BLOCK_SIZE; |
file->block = NULL; |
rc = MediaBlockInit(); |
if(rc == 1) |
BlockRead(file, BLOCK_MALLOC); |
else |
BlockRead(file, FLASH_START); |
file->fileEntry.blockIndex = file->blockIndex; |
OS_fclose(file); |
#endif |
} |
|
file = (OS_FILE*)malloc(sizeof(OS_FILE)); |
if(file == NULL) |
return NULL; |
OS_MutexPend(mutexFilesys); |
if(name[0] == 0 || strcmp(name, "/") == 0) |
{ |
FileOpen(file, NULL, NULL); |
OS_MutexPost(mutexFilesys); |
return file; |
} |
if(mode[0] == 'w') |
{ |
//Don't over write a directory |
fileEntry.isDirectory = 0; |
rc = FileFindRecursive(&dir, name, &fileEntry, filename); |
if(rc == 0) |
{ |
if(fileEntry.isDirectory) |
{ |
free(file); |
return NULL; |
} |
OS_fdelete(name); |
} |
} |
rc = FileFindRecursive(&dir, name, &fileEntry, filename); |
if(rc == -2 || (rc && mode[0] == 'r')) |
{ |
free(file); |
OS_MutexPost(mutexFilesys); |
return NULL; |
} |
if(rc) |
fileEntry.valid = 0; |
rc = FileOpen(file, filename, &fileEntry); //Open file |
file->fullname[0] = 0; |
strncat(file->fullname, name, FULL_NAME_SIZE); |
OS_MutexPost(mutexFilesys); |
OS_MutexPost(mutexFilesys); |
if(mode[0] == 'a') |
OS_fseek(file, 0, 2); //goto end of file |
return file; |
} |
|
|
void OS_fclose(OS_FILE *file) |
{ |
OS_FileEntry_t fileEntry; |
OS_FILE dir; |
char filename[FILE_NAME_SIZE]; |
int rc; |
|
if(file->fileModified) |
{ |
// Write file->fileEntry into parent directory |
OS_MutexPend(mutexFilesys); |
BlockRead(file, BLOCK_EOF); |
rc = FileFindRecursive(&dir, file->fullname, &fileEntry, filename); |
if(file->fileEntry.mediaType == FILE_MEDIA_FLASH && rc == 0) |
{ |
// Invalidate old entry and add new entry at the end |
fileEntry.valid = 0; |
OS_fwrite(&fileEntry, sizeof(OS_FileEntry_t), 1, &dir); |
FileFind(&dir, "endoffile", &fileEntry); |
} |
OS_fwrite(&file->fileEntry, sizeof(OS_FileEntry_t), 1, &dir); |
BlockRead(&dir, BLOCK_EOF); //flush data |
if(dir.blockLocal) |
free(dir.blockLocal); |
OS_MutexPost(mutexFilesys); |
} |
if(file->blockLocal) |
free(file->blockLocal); |
free(file); |
} |
|
|
int OS_fmkdir(char *name) |
{ |
OS_FILE *file; |
file = OS_fopen(name, "w+"); |
if(file == NULL) |
return -1; |
file->fileEntry.isDirectory = 1; |
OS_fclose(file); |
return 0; |
} |
|
|
void OS_fdelete(char *name) |
{ |
OS_FILE dir, file; |
OS_FileEntry_t fileEntry; |
int rc; |
uint32 blockIndex; |
char filename[FILE_NAME_SIZE]; //Name without directories |
|
OS_MutexPend(mutexFilesys); |
rc = FileFindRecursive(&dir, name, &fileEntry, filename); |
if(rc == 0) |
{ |
FileOpen(&file, NULL, &fileEntry); |
for(blockIndex = file.blockIndex; file.block->next != BLOCK_EOF; blockIndex = file.blockIndex) |
{ |
BlockRead(&file, file.block->next); |
MediaBlockFree(&file, blockIndex); |
} |
MediaBlockFree(&file, blockIndex); |
fileEntry.valid = 0; |
OS_fwrite((char*)&fileEntry, sizeof(OS_FileEntry_t), 1, &dir); |
BlockRead(&dir, BLOCK_EOF); |
if(file.blockLocal) |
free(file.blockLocal); |
} |
if(dir.blockLocal) |
free(dir.blockLocal); |
OS_MutexPost(mutexFilesys); |
} |
|
|
int OS_flength(char *entry) |
{ |
OS_FileEntry_t *entry2=(OS_FileEntry_t*)entry; |
return entry2->length; |
} |
|
|
int OS_fdir(OS_FILE *dir, char name[64]) |
{ |
OS_FileEntry_t *fileEntry = (OS_FileEntry_t*)name; |
int count; |
for(;;) |
{ |
count = OS_fread(fileEntry, sizeof(OS_FileEntry_t), 1, dir); |
if(count == 0 || fileEntry->blockIndex == BLOCK_EOF) |
return -1; |
if(fileEntry->valid == 1) |
break; |
} |
return 0; |
} |
|
/*************************************************/ |
#define TEST_FILES |
#ifdef TEST_FILES |
int DirRecursive(char *name) |
{ |
OS_FileEntry_t fileEntry; |
OS_FILE *dir; |
char fullname[FULL_NAME_SIZE]; |
int rc; |
|
dir = OS_fopen(name, "r"); |
for(;;) |
{ |
rc = OS_fdir(dir, (char*)&fileEntry); |
if(rc) |
break; |
printf("%s %d\n", fileEntry.name, fileEntry.length); |
if(fileEntry.isDirectory) |
{ |
if(strcmp(name, "/") == 0) |
sprintf(fullname, "/%s", fileEntry.name); |
else |
sprintf(fullname, "%s/%s", name, fileEntry.name); |
DirRecursive(fullname); |
} |
} |
OS_fclose(dir); |
return 0; |
} |
|
int OS_ftest(void) |
{ |
OS_FILE *file; |
char *buf; |
int count; |
int i, j; |
|
buf = (char*)malloc(5000); |
memset(buf, 0, 5000); |
for(count = 0; count < 4000; ++count) |
buf[count] = (char)('A' + (count % 26)); |
OS_fmkdir("dir"); |
OS_fmkdir("/dir/subdir"); |
file = OS_fopen("/dir/subdir/test.txt", "w"); |
count = OS_fwrite(buf, 1, 4000, file); |
OS_fclose(file); |
memset(buf, 0, 5000); |
file = OS_fopen("/dir/subdir/test.txt", "r"); |
count = OS_fread(buf, 1, 5000, file); |
OS_fclose(file); |
printf("(%s)\n", buf); |
|
DirRecursive("/"); |
|
for(i = 0; i < 5; ++i) |
{ |
sprintf(buf, "/dir%d", i); |
OS_fmkdir(buf); |
for(j = 0; j < 5; ++j) |
{ |
sprintf(buf, "/dir%d/file%d%d", i, i, j); |
file = OS_fopen(buf, "w"); |
sprintf(buf, "i=%d j=%d", i, j); |
OS_fwrite(buf, 1, 8, file); |
OS_fclose(file); |
} |
} |
|
OS_fdelete("/dir1/file12"); |
DirRecursive("/"); |
file = OS_fopen("/baddir/myfile.txt", "w"); |
if(file) |
printf("ERROR!\n"); |
|
for(i = 0; i < 5; ++i) |
{ |
for(j = 0; j < 5; ++j) |
{ |
sprintf(buf, "/dir%d/file%d%d", i, i, j); |
file = OS_fopen(buf, "r"); |
if(file) |
{ |
count = OS_fread(buf, 1, 500, file); |
printf("i=%d j=%d count=%d (%s)\n", i, j, count, buf); |
OS_fclose(file); |
} |
} |
} |
|
OS_fdelete("/dir/subdir/test.txt"); |
OS_fdelete("/dir/subdir"); |
OS_fdelete("/dir"); |
for(i = 0; i < 5; ++i) |
{ |
for(j = 0; j < 5; ++j) |
{ |
sprintf(buf, "/dir%d/file%d%d", i, i, j); |
OS_fdelete(buf); |
} |
sprintf(buf, "/dir%d", i); |
OS_fdelete(buf); |
} |
|
DirRecursive("/"); |
|
free(buf); |
return 0; |
} |
#endif //TEST_FILES |
return file; |
} |
|
|
void OS_fclose(OS_FILE *file) |
{ |
OS_FileEntry_t fileEntry; |
OS_FILE dir; |
char filename[FILE_NAME_SIZE]; |
int rc; |
|
if(file->fileModified) |
{ |
// Write file->fileEntry into parent directory |
OS_MutexPend(mutexFilesys); |
BlockRead(file, BLOCK_EOF); |
rc = FileFindRecursive(&dir, file->fullname, &fileEntry, filename); |
if(file->fileEntry.mediaType == FILE_MEDIA_FLASH && rc == 0) |
{ |
// Invalidate old entry and add new entry at the end |
fileEntry.valid = 0; |
OS_fwrite(&fileEntry, sizeof(OS_FileEntry_t), 1, &dir); |
FileFind(&dir, "endoffile", &fileEntry); |
} |
OS_fwrite(&file->fileEntry, sizeof(OS_FileEntry_t), 1, &dir); |
BlockRead(&dir, BLOCK_EOF); //flush data |
OS_MutexPost(mutexFilesys); |
} |
free(file); |
} |
|
|
int OS_fmkdir(char *name) |
{ |
OS_FILE *file; |
file = OS_fopen(name, "w+"); |
if(file == NULL) |
return -1; |
file->fileEntry.isDirectory = 1; |
OS_fclose(file); |
return 0; |
} |
|
|
void OS_fdelete(char *name) |
{ |
OS_FILE dir, file; |
OS_FileEntry_t fileEntry; |
int rc; |
uint32 blockIndex; |
char filename[FILE_NAME_SIZE]; //Name without directories |
|
OS_MutexPend(mutexFilesys); |
rc = FileFindRecursive(&dir, name, &fileEntry, filename); |
if(rc == 0) |
{ |
FileOpen(&file, NULL, &fileEntry); |
for(blockIndex = file.blockIndex; file.block->next != BLOCK_EOF; blockIndex = file.blockIndex) |
{ |
BlockRead(&file, file.block->next); |
MediaBlockFree(&file, blockIndex); |
} |
MediaBlockFree(&file, blockIndex); |
fileEntry.valid = 0; |
OS_fwrite((char*)&fileEntry, sizeof(OS_FileEntry_t), 1, &dir); |
BlockRead(&dir, BLOCK_EOF); |
} |
OS_MutexPost(mutexFilesys); |
} |
|
|
int OS_flength(char *entry) |
{ |
OS_FileEntry_t *entry2=(OS_FileEntry_t*)entry; |
return entry2->length; |
} |
|
|
int OS_fdir(OS_FILE *dir, char name[64]) |
{ |
OS_FileEntry_t *fileEntry = (OS_FileEntry_t*)name; |
int count; |
for(;;) |
{ |
count = OS_fread(fileEntry, sizeof(OS_FileEntry_t), 1, dir); |
if(count == 0 || fileEntry->blockIndex == BLOCK_EOF) |
return -1; |
if(fileEntry->valid == 1) |
break; |
} |
return 0; |
} |
|
/*************************************************/ |
#define TEST_FILES |
#ifdef TEST_FILES |
int DirRecursive(char *name) |
{ |
OS_FileEntry_t fileEntry; |
OS_FILE *dir; |
char fullname[FULL_NAME_SIZE]; |
int rc; |
|
dir = OS_fopen(name, "r"); |
for(;;) |
{ |
rc = OS_fdir(dir, (char*)&fileEntry); |
if(rc) |
break; |
printf("%s %d\n", fileEntry.name, fileEntry.length); |
if(fileEntry.isDirectory) |
{ |
if(strcmp(name, "/") == 0) |
sprintf(fullname, "/%s", fileEntry.name); |
else |
sprintf(fullname, "%s/%s", name, fileEntry.name); |
DirRecursive(fullname); |
} |
} |
OS_fclose(dir); |
return 0; |
} |
|
int OS_ftest(void) |
{ |
OS_FILE *file; |
char *buf; |
int count; |
int i, j; |
|
buf = (char*)malloc(5000); |
memset(buf, 0, 5000); |
for(count = 0; count < 4000; ++count) |
buf[count] = (char)('A' + (count % 26)); |
OS_fmkdir("dir"); |
OS_fmkdir("/dir/subdir"); |
file = OS_fopen("/dir/subdir/test.txt", "w"); |
count = OS_fwrite(buf, 1, 4000, file); |
OS_fclose(file); |
memset(buf, 0, 5000); |
file = OS_fopen("/dir/subdir/test.txt", "r"); |
count = OS_fread(buf, 1, 5000, file); |
OS_fclose(file); |
printf("(%s)\n", buf); |
|
DirRecursive("/"); |
|
for(i = 0; i < 5; ++i) |
{ |
sprintf(buf, "/dir%d", i); |
OS_fmkdir(buf); |
for(j = 0; j < 5; ++j) |
{ |
sprintf(buf, "/dir%d/file%d%d", i, i, j); |
file = OS_fopen(buf, "w"); |
sprintf(buf, "i=%d j=%d", i, j); |
OS_fwrite(buf, 1, 8, file); |
OS_fclose(file); |
} |
} |
|
OS_fdelete("/dir1/file12"); |
DirRecursive("/"); |
file = OS_fopen("/baddir/myfile.txt", "w"); |
if(file) |
printf("ERROR!\n"); |
|
for(i = 0; i < 5; ++i) |
{ |
for(j = 0; j < 5; ++j) |
{ |
sprintf(buf, "/dir%d/file%d%d", i, i, j); |
file = OS_fopen(buf, "r"); |
if(file) |
{ |
count = OS_fread(buf, 1, 500, file); |
printf("i=%d j=%d count=%d (%s)\n", i, j, count, buf); |
OS_fclose(file); |
} |
} |
} |
|
OS_fdelete("/dir/subdir/test.txt"); |
OS_fdelete("/dir/subdir"); |
OS_fdelete("/dir"); |
for(i = 0; i < 5; ++i) |
{ |
for(j = 0; j < 5; ++j) |
{ |
sprintf(buf, "/dir%d/file%d%d", i, i, j); |
OS_fdelete(buf); |
} |
sprintf(buf, "/dir%d", i); |
OS_fdelete(buf); |
} |
|
DirRecursive("/"); |
|
free(buf); |
return 0; |
} |
#endif //TEST_FILES |