repo2/firmware/fat/pff_file.c @ 461
46 | markw | #include "pff_file.h"
|
|
#include "pff.h"
|
|||
#include "utils.h"
|
|||
#include "diskio.h"
|
|||
#include "simplefile.h"
|
|||
55 | markw | //#include "printf.h"
|
|
46 | markw | ||
struct SimpleFile * openfile;
|
|||
void * dir_cache;
|
|||
int dir_cache_size;
|
|||
FATFS fatfs;
|
|||
DIR dir;
|
|||
FILINFO filinfo;
|
|||
49 | markw | int write_pending;
|
|
100 | markw | #define translateStatus(res) (res == FR_OK ? SimpleFile_OK: SimpleFile_FAIL)
|
|
#define translateDStatus(res) (res == RES_OK ? SimpleFile_OK: SimpleFile_FAIL)
|
|||
/*
|
|||
46 | markw | enum SimpleFileStatus translateStatus(FRESULT res)
|
|
{
|
|||
return res == FR_OK ? SimpleFile_OK: SimpleFile_FAIL;
|
|||
}
|
|||
enum SimpleFileStatus translateDStatus(DSTATUS res)
|
|||
{
|
|||
return res == RES_OK ? SimpleFile_OK: SimpleFile_FAIL;
|
|||
100 | markw | }*/
|
|
46 | markw | ||
char const * file_of(char const * path)
|
|||
{
|
|||
char const * start = path + strlen(path);
|
|||
while (start!=path)
|
|||
{
|
|||
--start;
|
|||
if (*start == '/')
|
|||
{
|
|||
52 | markw | ++start;
|
|
46 | markw | break;
|
|
}
|
|||
}
|
|||
return start;
|
|||
}
|
|||
void dir_of(char * dir, char const * path)
|
|||
{
|
|||
char const * end = file_of(path);
|
|||
if (end != path)
|
|||
{
|
|||
int len = end-path;
|
|||
while (len--)
|
|||
{
|
|||
*dir++ = *path++;
|
|||
}
|
|||
64 | markw | --dir;
|
|
46 | markw | }
|
|
*dir = '\0';
|
|||
return;
|
|||
}
|
|||
char const * file_name(struct SimpleFile * file)
|
|||
{
|
|||
return file_of(&file->path[0]);
|
|||
}
|
|||
64 | markw | char const * file_path(struct SimpleFile * file)
|
|
{
|
|||
return &file->path[0];
|
|||
}
|
|||
52 | markw | void file_init(struct SimpleFile * file)
|
|
{
|
|||
file->path[0] = '\0';
|
|||
62 | markw | file->is_readonly = 1;
|
|
52 | markw | file->size = 0;
|
|
}
|
|||
46 | markw | void file_check_open(struct SimpleFile * file)
|
|
{
|
|||
if (openfile!=file)
|
|||
{
|
|||
49 | markw | file_write_flush();
|
|
46 | markw | pf_open(&file->path[0]);
|
|
openfile = file;
|
|||
}
|
|||
}
|
|||
enum SimpleFileStatus file_read(struct SimpleFile * file, void * buffer, int bytes, int * bytesread)
|
|||
{
|
|||
191 | markw | UINT bytesread_word;
|
|
46 | markw | FRESULT res;
|
|
49 | markw | file_write_flush();
|
|
46 | markw | file_check_open(file);
|
|
res = pf_read(buffer, bytes, &bytesread_word);
|
|||
*bytesread = bytesread_word;
|
|||
return translateStatus(res);
|
|||
}
|
|||
enum SimpleFileStatus file_write(struct SimpleFile * file, void * buffer, int bytes, int * byteswritten)
|
|||
{
|
|||
191 | markw | UINT byteswritten_word;
|
|
413 | markw | FRESULT res = FR_OK;
|
|
46 | markw | ||
55 | markw | //printf("went\n");
|
|
62 | markw | if (file->is_readonly) return SimpleFile_FAIL;
|
|
49 | markw | ||
46 | markw | file_check_open(file);
|
|
49 | markw | int rem = bytes;
|
|
while (rem>0)
|
|||
{
|
|||
int sector = fatfs.fptr>>9;
|
|||
int pos = fatfs.fptr&0x1ff;
|
|||
int bytes_this_cycle = rem;
|
|||
if (bytes_this_cycle>(512-pos))
|
|||
bytes_this_cycle = 512-pos;
|
|||
55 | markw | //printf("file_write:%d/%d - %d/%d\n",sector,pos,bytes_this_cycle,bytes);
|
|
49 | markw | ||
if (sector != write_pending)
|
|||
{
|
|||
file_write_flush();
|
|||
}
|
|||
if (write_pending <0)
|
|||
{
|
|||
// read the sector into our 512 byte buffer...
|
|||
pf_lseek(sector<<9);
|
|||
int fptr = fatfs.fptr;
|
|||
char temp_buffer[1];
|
|||
pf_read(&temp_buffer[0], 1, &byteswritten_word);
|
|||
55 | markw | //printf("Writing initial pos:%d\n",pos);
|
|
49 | markw | ||
// seek to the initial pos
|
|||
fatfs.fptr = fptr + pos;
|
|||
write_pending = sector;
|
|||
}
|
|||
res = disk_writep(buffer, pos, bytes_this_cycle);
|
|||
fatfs.fptr += bytes_this_cycle;
|
|||
rem-=bytes_this_cycle;
|
|||
buffer+=bytes_this_cycle;
|
|||
}
|
|||
*byteswritten = bytes;
|
|||
55 | markw | //printf("wend\n");
|
|
46 | markw | return translateStatus(res);
|
|
}
|
|||
49 | markw | enum SimpleFileStatus file_write_flush()
|
|
{
|
|||
if (write_pending >= 0)
|
|||
{
|
|||
55 | markw | //printf("wflush\n");
|
|
49 | markw | disk_writeflush();
|
|
write_pending = -1;
|
|||
}
|
|||
return SimpleFile_OK;
|
|||
}
|
|||
46 | markw | enum SimpleFileStatus file_seek(struct SimpleFile * file, int offsetFromStart)
|
|
{
|
|||
FRESULT res;
|
|||
49 | markw | int location = offsetFromStart>>9;
|
|
if (write_pending >=0 && write_pending != offsetFromStart)
|
|||
{
|
|||
55 | markw | //printf("flush on seek\n");
|
|
49 | markw | file_write_flush();
|
|
}
|
|||
46 | markw | file_check_open(file);
|
|
195 | markw | res = pf_lseek(offsetFromStart);
|
|
46 | markw | return translateStatus(res);
|
|
}
|
|||
int file_size(struct SimpleFile * file)
|
|||
{
|
|||
return file->size;
|
|||
}
|
|||
62 | markw | int file_readonly(struct SimpleFile * file)
|
|
{
|
|||
return file->is_readonly;
|
|||
}
|
|||
46 | markw | int file_struct_size()
|
|
{
|
|||
return sizeof(struct SimpleFile);
|
|||
}
|
|||
63 | markw | enum SimpleFileStatus file_open_name_in_dir(struct SimpleDirEntry * entry, char const * filename, struct SimpleFile * file)
|
|
46 | markw | {
|
|
49 | markw | file_write_flush();
|
|
46 | markw | while (entry)
|
|
{
|
|||
55 | markw | //printf("%s ",entry->filename_ptr);
|
|
if (0==stricmp(filename,entry->filename_ptr))
|
|||
46 | markw | {
|
|
return file_open_dir(entry, file);
|
|||
}
|
|||
entry = entry->next;
|
|||
}
|
|||
return SimpleFile_FAIL;
|
|||
}
|
|||
63 | markw | enum SimpleFileStatus file_open_name(char const * path, struct SimpleFile * file)
|
|
{
|
|||
char dirname[MAX_DIR_LENGTH];
|
|||
char const * filename = file_of(path);
|
|||
dir_of(&dirname[0], path);
|
|||
file_write_flush();
|
|||
//printf("filename:%s dirname:%s ", filename,&dirname[0]);
|
|||
struct SimpleDirEntry * entry = dir_entries(&dirname[0]);
|
|||
return file_open_name_in_dir(entry,filename, file);
|
|||
}
|
|||
46 | markw | enum SimpleFileStatus file_open_dir(struct SimpleDirEntry * dir, struct SimpleFile * file)
|
|
{
|
|||
FRESULT res;
|
|||
strcpy(&file->path[0],dir->path);
|
|||
62 | markw | file->is_readonly = dir->is_readonly;
|
|
46 | markw | file->size = dir->size;
|
|
49 | markw | file_write_flush();
|
|
46 | markw | res = pf_open(&file->path[0]);
|
|
openfile = file;
|
|||
return translateStatus(res);
|
|||
}
|
|||
enum SimpleFileStatus dir_init(void * mem, int space)
|
|||
{
|
|||
FRESULT fres;
|
|||
DSTATUS res;
|
|||
49 | markw | write_pending = -1;
|
|
55 | markw | //printf("dir_init\n");
|
|
46 | markw | ||
dir_cache = mem;
|
|||
dir_cache_size = space;
|
|||
55 | markw | //printf("disk_init go\n");
|
|
46 | markw | res = disk_initialize();
|
|
55 | markw | //printf("disk_init done\n");
|
|
46 | markw | if (res!=RES_OK) return translateDStatus(res);
|
|
55 | markw | //printf("pf_mount\n");
|
|
46 | markw | fres = pf_mount(&fatfs);
|
|
55 | markw | //printf("pf_mount done\n");
|
|
46 | markw | ||
return translateStatus(fres);
|
|||
}
|
|||
// Read entire dir into memory (i.e. give it a decent chunk of sdram)
|
|||
struct SimpleDirEntry * dir_entries(char const * dirPath)
|
|||
{
|
|||
49 | markw | return dir_entries_filtered(dirPath,0);
|
|
}
|
|||
52 | markw | int dircmp(struct SimpleDirEntry * a, struct SimpleDirEntry * b)
|
|
{
|
|||
if (a->is_subdir==b->is_subdir)
|
|||
return strcmp(a->lfn,b->lfn);
|
|||
else
|
|||
return a->is_subdir<b->is_subdir;
|
|||
}
|
|||
void sort_ll(struct SimpleDirEntry * h)
|
|||
{
|
|||
//struct SimpleDirEntry
|
|||
//{
|
|||
// char path[MAX_PATH_LENGTH];
|
|||
// char * filename_ptr;
|
|||
// int size;
|
|||
// int is_subdir;
|
|||
// struct SimpleDirEntry * next; // as linked list - want to allow sorting...
|
|||
//};
|
|||
struct SimpleDirEntry * p,*temp,*prev;
|
|||
int i,j,n,sorted=0;
|
|||
temp=h;
|
|||
prev=0;
|
|||
for(n=0;temp!=0;temp=temp->next) n++;
|
|||
for(i=0;i<n-1 && !sorted;i++){
|
|||
p=h;sorted=1;
|
|||
prev=0;
|
|||
for(j=0;j<n-(i+1);j++){
|
|||
// printf("p->issubdir:%d(%s) p->next->issubdir:%d(%s)",p->is_subdir,p->path,p->next->is_subdir,p->next->path);
|
|||
if(dircmp(p,p->next)>0) {
|
|||
// printf("SWITCH!\n");
|
|||
struct SimpleDirEntry * a = p;
|
|||
struct SimpleDirEntry * b = p->next;
|
|||
a->next=b->next;
|
|||
b->next=a;
|
|||
if (prev)
|
|||
prev->next=b;
|
|||
p=b;
|
|||
sorted=0;
|
|||
}
|
|||
prev=p;
|
|||
p=p->next;
|
|||
}
|
|||
}
|
|||
//temp=h;
|
|||
//for(n=0;temp!=0;temp=temp->next) printf("POST:%s\n",temp->path);
|
|||
}
|
|||
49 | markw | struct SimpleDirEntry * dir_entries_filtered(char const * dirPath,int(* filter)(struct SimpleDirEntry *))
|
|
{
|
|||
46 | markw | int room = dir_cache_size/sizeof(struct SimpleDirEntry);
|
|
49 | markw | file_write_flush();
|
|
55 | markw | //printf("opendir ");
|
|
46 | markw | if (FR_OK != pf_opendir(&dir,dirPath))
|
|
{
|
|||
55 | markw | //printf("FAIL ");
|
|
46 | markw | return 0;
|
|
}
|
|||
55 | markw | //printf("OK ");
|
|
46 | markw | ||
49 | markw | struct SimpleDirEntry * prev = (struct SimpleDirEntry *)dir_cache;
|
|
strcpy(prev->path,"..");
|
|||
52 | markw | strcpy(prev->lfn,"..");
|
|
49 | markw | prev->filename_ptr = prev->path;
|
|
prev->size = 0;
|
|||
prev->is_subdir = 1;
|
|||
62 | markw | prev->is_readonly = 1;
|
|
184 | markw | prev->next = 0;
|
|
49 | markw | --room;
|
|
52 | markw | //int count=0;
|
|
184 | markw | struct SimpleDirEntry * entry = prev + 1;
|
|
while (room && FR_OK == pf_readdir(&dir,&filinfo) && filinfo.fname[0]!='\0')
|
|||
46 | markw | {
|
|
char * ptr;
|
|||
if (filinfo.fattrib & AM_SYS)
|
|||
{
|
|||
continue;
|
|||
}
|
|||
if (filinfo.fattrib & AM_HID)
|
|||
{
|
|||
continue;
|
|||
}
|
|||
52 | markw | //printf("next %x %d ",entry,room);
|
|
46 | markw | ||
entry->is_subdir = (filinfo.fattrib & AM_DIR) ? 1 : 0;
|
|||
62 | markw | entry->is_readonly = (filinfo.fattrib & AM_RDO) ? 1 : 0;
|
|
46 | markw | ||
52 | markw | //printf("%s ",filinfo.fname);
|
|
46 | markw | ||
strcpy(&entry->path[0],dirPath);
|
|||
ptr = &entry->path[0];
|
|||
ptr += strlen(&entry->path[0]);
|
|||
*ptr++ = '/';
|
|||
entry->filename_ptr = ptr;
|
|||
strcpy(ptr,filinfo.fname);
|
|||
entry->size = filinfo.fsize;
|
|||
157 | markw | //printf("LFN:%s\n",&filinfo.lfname[0]);
|
|
52 | markw | strcpy(&entry->lfn[0],&filinfo.lfname[0]);
|
|
55 | markw | //int count;
|
|
//printf("%d %s %s\n",count++, filinfo.fname, filinfo.lfname);
|
|||
52 | markw | ||
49 | markw | ||
if (filter && !filter(entry))
|
|||
{
|
|||
184 | markw | continue;
|
|
49 | markw | }
|
|
184 | markw | entry->next = 0;
|
|
49 | markw | if (prev)
|
|
prev->next = entry;
|
|||
prev = entry;
|
|||
184 | markw | entry++;
|
|
room--;
|
|||
49 | markw | ||
52 | markw | //printf("n %d %d %x ",filinfo.fsize, entry->size, entry->next);
|
|
46 | markw | }
|
|
52 | markw | //printf("dir_entries done ");
|
|
46 | markw | ||
55 | markw | /*struct SimpleDirEntry * begin = (struct SimpleDirEntry *) dir_cache;
|
|
int count = 0;
|
|||
52 | markw | while (begin)
|
|
{
|
|||
printf("%d %s\n",count++, begin->path);
|
|||
begin = begin->next;
|
|||
}*/
|
|||
63 | markw | if (filter)
|
|
{
|
|||
sort_ll((struct SimpleDirEntry *) dir_cache);
|
|||
}
|
|||
46 | markw | return (struct SimpleDirEntry *) dir_cache;
|
|
}
|
|||
char const * dir_path(struct SimpleDirEntry * entry)
|
|||
{
|
|||
return &entry->path[0];
|
|||
}
|
|||
char const * dir_filename(struct SimpleDirEntry * entry)
|
|||
{
|
|||
52 | markw | //return entry->filename_ptr;
|
|
return &entry->lfn[0];
|
|||
46 | markw | }
|
|
int dir_filesize(struct SimpleDirEntry * entry)
|
|||
{
|
|||
return entry->size;
|
|||
}
|
|||
struct SimpleDirEntry * dir_next(struct SimpleDirEntry * entry)
|
|||
{
|
|||
return entry->next;
|
|||
}
|
|||
int dir_is_subdir(struct SimpleDirEntry * entry)
|
|||
{
|
|||
return entry->is_subdir;
|
|||
}
|
|||