You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1620 lines
47 KiB
1620 lines
47 KiB
/*
|
|
It is an open source software to implement FAT file system to
|
|
small embedded systems. This is a free software and is opened for education,
|
|
research and commercial developments under license policy of following trems.
|
|
|
|
(C) 2013 vinxru
|
|
(C) 2010, ChaN, all right reserved.
|
|
|
|
It is a free software and there is NO WARRANTY.
|
|
No restriction on use. You can use, modify and redistribute it for
|
|
personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.
|
|
Redistributions of source code must retain the above copyright notice.
|
|
|
|
Version 0.99 30-05-2013
|
|
|
|
P.S. goto allows you to save memory! Like other horrors bellow.
|
|
|
|
Program size: 3070 words (6140 bytes), 75% of FLASH at ATMega8 !!!
|
|
*/
|
|
|
|
/*
|
|
ß íå ñòàë äîáàâëÿòü êîíòðîëü íà ñïåöèàëüíûå èìåíà
|
|
CON,PRN,AUX,CLOCK$,NUL,COM1,COM2,COM3,COM4,LPT1,LPT2,LPT3
|
|
÷òî áû íå çàíèìàòü ìèêðîêîíòðîëëåð. Ôàéëû ñ òàêèìè èìåíàìè
|
|
îñòàâëÿþ íà ñîâåñòè ïðîãðàììèñòà.
|
|
*/
|
|
|
|
//#include <stdafx.h>
|
|
#include "fs.h"
|
|
#include "sd.h"
|
|
#include <string.h>
|
|
#include <avr/pgmspace.h>
|
|
#include "DS3231.h"
|
|
|
|
/* Âñïîìîãàòåëüíûå ôóíêöèè äëÿ ðàáîòû ñ âðåìåíåì */
|
|
|
|
static uint8_t fs_update_timestamp(void);
|
|
|
|
/**************************************************************************
|
|
* Óïàêîâêà âðåìåíè â ôîðìàò FAT *
|
|
* Âîçâðàùàåò 16-áèòíîå çíà÷åíèå: *
|
|
* áèòû 15-11: ÷àñû (0-23) *
|
|
* áèòû 10-5: ìèíóòû (0-59) *
|
|
* áèòû 4-0: ñåêóíäû / 2 (0-29) *
|
|
**************************************************************************/
|
|
static uint16_t fat_pack_time(void)
|
|
{
|
|
uint8_t hour = ds3231GetHour();
|
|
uint8_t min = ds3231GetMinute();
|
|
uint8_t sec = ds3231GetSecond();
|
|
|
|
/* Ïðîâåðêà è êîððåêöèÿ çíà÷åíèé */
|
|
if (hour > 23) hour = 0;
|
|
if (min > 59) min = 0;
|
|
if (sec > 59) sec = 0;
|
|
|
|
return (uint16_t)((hour << 11) | (min << 5) | (sec >> 1));
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Óïàêîâêà äàòû â ôîðìàò FAT *
|
|
* Âîçâðàùàåò 16-áèòíîå çíà÷åíèå: *
|
|
* áèòû 15-9: ãîä (îò 1980, 0-127) *
|
|
* áèòû 8-5: ìåñÿö (1-12) *
|
|
* áèòû 4-0: äåíü (1-31) *
|
|
**************************************************************************/
|
|
static uint16_t fat_pack_date(void)
|
|
{
|
|
uint8_t year = ds3231GetYear();
|
|
uint8_t month = (uint8_t)ds3231GetMonth();
|
|
uint8_t day = ds3231GetDate();
|
|
|
|
/* Ïðîâåðêà è êîððåêöèÿ çíà÷åíèé */
|
|
if (year > 99) year = 0; /* 2000-2099 */
|
|
if (month < 1 || month > 12) month = 1;
|
|
if (day < 1 || day > 31) day = 1;
|
|
|
|
/* Ãîä îò 1980: 2000 + year - 1980 = 20 + year */
|
|
uint16_t year_offset = 20 + year; /* Äëÿ 2024: 20 + 24 = 44 */
|
|
if (year_offset > 127) year_offset = 0;
|
|
|
|
return (uint16_t)((year_offset << 9) | (month << 5) | day);
|
|
}
|
|
|
|
uint8_t buf[512];
|
|
|
|
/* Äëÿ íàãëÿäíîñòè */
|
|
|
|
#define LD_uint16_t(ptr) (*(uint16_t*)(ptr))
|
|
#define LD_uint32_t(ptr) (*(uint32_t*)(ptr))
|
|
|
|
/* Çíà÷åíèÿ fs_type */
|
|
|
|
#define FS_FAT16 0
|
|
#define FS_FAT32 1
|
|
#define FS_ERROR 2
|
|
|
|
/* Ñïåöèàëüíûå çíà÷åíèÿ êëàñòåðîâ */
|
|
|
|
#define FREE_CLUSTER 0
|
|
#define LAST_CLUSTER 0x0FFFFFFF
|
|
|
|
/* Ñèñòåìíûå ïåðåìåííûå. Èíôîðìàöèÿ èç boot-ñåêòîðà */
|
|
|
|
|
|
|
|
uint8_t fs_type; /* FS_FAT16, FS_FAT32, FS_ERROR */
|
|
uint32_t fs_fatbase; /* Àäðåñ ïåðâîé FAT */
|
|
uint32_t fs_fatbase2; /* Àäðåñ âòîðîé FAT */
|
|
uint8_t fs_csize; /* Ðàçìåð êëàñòåðà â ñåêòîðàõ */
|
|
uint16_t fs_n_rootdir; /* Êîë-âî çàïèñåé â êîðíåâîì êàòàëîãå (òîëüêî FAT16) */
|
|
uint32_t fs_n_fatent; /* Êîë-âî êëàñòåðîâ */
|
|
uint32_t fs_dirbase; /* Êîðíåâîé êàòàëîã (ñåêòîð äëÿ FAT16, êëàñòåð äëÿ FAT32) */
|
|
uint32_t fs_database; /* Àäðåñ âòîðîãî êëàñòåðà */
|
|
|
|
/* Ñèñòåìíûå ïåðåìåííûå. Îñòàëüíîå */
|
|
|
|
uint8_t lastError; /* Ïîñëåäíÿÿ îøèáêà */
|
|
uint32_t fs_fatoptim; /* Ïåðâûé ñâîáîäíûé êëàñòåð */
|
|
uint32_t fs_tmp; /* Èñïîëüçóåþòñÿ äëÿ ðàçíûõ öåëåé */
|
|
uint16_t fs_wtotal; /* Èñïîëüçóåòñÿ ôóíêöèÿìè fs_write_start, fs_write_end*/
|
|
|
|
/* Îòêðûòûå ôàéëû/ïàïêè */
|
|
|
|
File fs_file;
|
|
|
|
#ifndef FS_DISABLE_SWAP
|
|
File fs_secondFile;
|
|
#endif
|
|
|
|
/* Ñòðóêòóðà boot-ñåêòîðà */
|
|
|
|
#define BPB_SecPerClus 13
|
|
#define BPB_RsvdSecCnt 14
|
|
#define BPB_NumFATs 16
|
|
#define BPB_RootEntCnt 17
|
|
#define BPB_TotSec16 19
|
|
#define BPB_FATSz16 22
|
|
#define BPB_TotSec32 32
|
|
#define BS_FilSysType 54
|
|
#define BPB_FATSz32 36
|
|
#define BPB_RootClus 44
|
|
#define BS_FilSysType32 82
|
|
#define MBR_Table 446
|
|
|
|
/**************************************************************************
|
|
* ×òåíèå ñåêòîðà â áóôåð *
|
|
**************************************************************************/
|
|
|
|
static uint8_t sd_readBuf(uint32_t sector)
|
|
{
|
|
return sd_read(buf, sector, 0, 512);
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Çàïèñü áóôåðà â ñåêòîð *
|
|
**************************************************************************/
|
|
|
|
static uint8_t sd_writeBuf(uint32_t sector)
|
|
{
|
|
return sd_write512(buf, sector);
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Èíèöèàëèçàöèÿ *
|
|
**************************************************************************/
|
|
|
|
uint8_t fs_init()
|
|
{
|
|
uint32_t bsect, fsize, tsect;
|
|
|
|
/* Ñáðàñûâàåì îïòèìèçàöèþ */
|
|
fs_fatoptim = 2;
|
|
|
|
/* Ïðåäîòâðàùàåì îøèáêè ïðîãðàììèñòà */
|
|
#ifndef FS_DISABLE_CHECK
|
|
fs_file.opened = OPENED_NONE;
|
|
#ifndef FS_DISABLE_SWAP
|
|
fs_secondFile.opened = OPENED_NONE;
|
|
#endif
|
|
fs_type = FS_ERROR;
|
|
#endif
|
|
|
|
/* Èíèöèàëèçàöèÿ íàêîïèòåëÿ */
|
|
//if(sd_init()) return 1;
|
|
|
|
/* Èùåì ôàéëîâóþ ñèñòåìó */
|
|
bsect = 0;
|
|
while(1)
|
|
{
|
|
if(sd_readBuf(bsect)) return 1;
|
|
if(LD_uint16_t(buf + 510) == 0xAA55)
|
|
{
|
|
if(LD_uint16_t(buf + BS_FilSysType ) == 0x4146) break;
|
|
if(LD_uint16_t(buf + BS_FilSysType32) == 0x4146) break;
|
|
/* Âîçìîæíî ýòî MBR */
|
|
if(bsect == 0 && buf[MBR_Table+4])
|
|
{
|
|
bsect = LD_uint32_t(buf + (MBR_Table + 8));
|
|
if(bsect != 0) continue;
|
|
}
|
|
}
|
|
abort_noFS:
|
|
lastError = ERR_NO_FILESYSTEM;
|
|
return 1;
|
|
}
|
|
|
|
/* Ðàçìåð òàáëèöû FAT â ñåêòîðàõ */
|
|
fsize = LD_uint16_t(buf + BPB_FATSz16);
|
|
if(fsize == 0) fsize = LD_uint32_t(buf + BPB_FATSz32);
|
|
|
|
/* Ðàçìåð ôàéëîâîé ñèñòåìû â ñåêòîðàõ */
|
|
tsect = LD_uint16_t( buf + BPB_TotSec16);
|
|
if(tsect == 0) tsect = LD_uint32_t(buf + BPB_TotSec32);
|
|
|
|
/* Ðàçìåð êîðíåâîãî êàòàëîãà (äîëæíî áûòü êðàòíî 16 è äëÿ FAT32 äîëæíî áûòü ðàíî íóëþ) */
|
|
fs_n_rootdir = LD_uint16_t(buf + BPB_RootEntCnt);
|
|
|
|
/* Àäðåñà òàáëèö FAT â ñåêòîðàõ */
|
|
fs_fatbase = bsect + LD_uint16_t(buf + BPB_RsvdSecCnt);
|
|
fs_fatbase2 = 0;
|
|
if(buf[BPB_NumFATs] >= 2) fs_fatbase2 = fs_fatbase + fsize;
|
|
|
|
/* Êîë-âî ñåêòîðîâ íà êëàñòåð */
|
|
fs_csize = buf[BPB_SecPerClus];
|
|
|
|
/* Êîë-âî êëàñòåðîâ */
|
|
fsize *= buf[BPB_NumFATs];
|
|
fs_n_fatent = (tsect - LD_uint16_t(buf + BPB_RsvdSecCnt) - fsize - fs_n_rootdir / 16) / fs_csize + 2;
|
|
|
|
/* Àäðåñ 2-îãî êëàñòåðà */
|
|
fs_database = fs_fatbase + fsize + fs_n_rootdir / 16;
|
|
|
|
/* Îïðåäåëåíèå ôàéëîâîé ñèñòåìû */
|
|
|
|
/* FAT 12 */
|
|
if(fs_n_fatent < 0xFF7) goto abort_noFS;
|
|
|
|
/* FAT 16 */
|
|
if(fs_n_fatent < 0xFFF7)
|
|
{
|
|
fs_dirbase = fs_fatbase + fsize;
|
|
fs_type = FS_FAT16;
|
|
return 0;
|
|
}
|
|
|
|
/* FAT 32 */
|
|
fs_dirbase = LD_uint32_t(buf + BPB_RootClus);
|
|
|
|
/* Ñáðàñûâàåì ñ÷åò÷èê ñâîáîäíîãî ìåñòà */
|
|
if(LD_uint16_t(buf + BPB_RsvdSecCnt)>0)
|
|
{
|
|
bsect++;
|
|
if(sd_readBuf(bsect)) return 1;
|
|
if(LD_uint32_t(buf) == 0x41615252 && LD_uint32_t(buf + 0x1E4) == 0x61417272 && LD_uint32_t(buf + 0x1FC) == 0xAA550000)
|
|
{
|
|
LD_uint32_t(buf + 0x1E8) = 0xFFFFFFFF;
|
|
LD_uint32_t(buf + 0x1EC) = 0xFFFFFFFF;
|
|
if(sd_writeBuf(bsect)) return 1;
|
|
}
|
|
}
|
|
fs_type = FS_FAT32;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Ïðîâåðêà íàëè÷èÿ äèñêà è åñëè íóæíî, òî åãî èíèöèàëèçàöèÿ *
|
|
**************************************************************************/
|
|
|
|
uint8_t fs_check()
|
|
{
|
|
if(!sd_check()) return 0;
|
|
return fs_init();
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Ïîëó÷èòü êëàñòåð èç FS_DIRENTRY *
|
|
* Ôóíêöèÿ íå ïîðòèò buf (ôóíêöèè, â êîòîðûõ ýòîãî íå íàïèñàíî, ïîðòÿò) *
|
|
**************************************************************************/
|
|
|
|
static uint32_t fs_getEntryCluster()
|
|
{
|
|
uint32_t c = LD_uint16_t(FS_DIRENTRY + DIR_FstClusLO);
|
|
if(fs_type != FS_FAT16) c |= ((uint32_t)LD_uint16_t(FS_DIRENTRY + DIR_FstClusHI)) << 16;
|
|
return c;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Ïîëó÷èòü ñëåäóþùèé êëàñòåð. *
|
|
* Àðãóìåíò è ðåçóëüòàò íàõîäÿòñÿ â fs_tmp. *
|
|
**************************************************************************/
|
|
|
|
static uint8_t fs_nextCluster()
|
|
{
|
|
if(fs_type == FS_FAT16)
|
|
{
|
|
if(sd_read((uint8_t*)&fs_tmp, fs_fatbase + fs_tmp / 256, (uint16_t)(uint8_t)fs_tmp * 2, 2)) goto abort;
|
|
fs_tmp &= 0xFFFF;
|
|
}
|
|
else
|
|
{
|
|
if(sd_read((uint8_t*)&fs_tmp, fs_fatbase + fs_tmp / 128, (uint16_t)((uint8_t)fs_tmp % 128) * 4, 4)) goto abort;
|
|
fs_tmp &= 0x0FFFFFFF;
|
|
}
|
|
/* Äëÿ óäîáñòâà ðàçðàáîòêè çàìåíÿåì ïîñëåäíèé êëàñòåð íà íîëü. */
|
|
if(fs_tmp < 2 || fs_tmp >= fs_n_fatent)
|
|
fs_tmp = 0;
|
|
return 0;
|
|
abort:
|
|
return 1;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Ïðåîáðàçîâàòü íîìåð êëàñòåðà â íîìåð ñåêòîðà *
|
|
* Àðãóìåíò è ðåçóëüòàò íàõîäÿòñÿ â fs_tmp. *
|
|
* Ôóíêöèÿ íå ïîðòèò buf *
|
|
***************************************************************************/
|
|
|
|
static void fs_clust2sect()
|
|
{
|
|
fs_tmp = (fs_tmp - 2) * fs_csize + fs_database;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Ïîëó÷èòü î÷åðåäíîé ôàéë èëè ïàïêó *
|
|
* Óäàëåííûå ôàéëû, ìåòêè òîìà, ïîñëåäíèé ýëåìåíò, LFN ïîêàçûâàþòñÿ *
|
|
* *
|
|
* Îïèñàíèå ðàáîòû ïîëíîñòüþ èäåíòè÷íî ôóíêöèè íèæå, ïîýòîìó çäåñü íå *
|
|
* ïðèâåäåíî *
|
|
* *
|
|
* Ôóíêöèÿ íå ïîðòèò buf[0..MAX_FILENAME-1] *
|
|
***************************************************************************/
|
|
|
|
static uint8_t fs_readdirInt()
|
|
{
|
|
if(fs_file.entry_able)
|
|
{
|
|
fs_file.entry_index++;
|
|
|
|
/* Â ïàïêå íå ìîæåò áûòü áîëüøå 65536 ôàéëîâ, à â êîðíå FAT16 íå áîëüøå fs_n_rootdir */
|
|
if(fs_file.entry_index == 0 || (fs_file.entry_cluster == 0 && fs_file.entry_index == fs_n_rootdir))
|
|
{
|
|
fs_file.entry_index = 0;
|
|
retEnd:
|
|
FS_DIRENTRY[DIR_Name] = 0; /* Ïðèçíàê ïîñëåäíåãî ôàéëà äëÿ ïîëüçîâàòåëÿ âûçûâàþùåãî fs_dirread */
|
|
fs_file.entry_able = 0;
|
|
return 0;
|
|
}
|
|
|
|
/* Ãðàíèöà ñåêòîðà */
|
|
if(fs_file.entry_index % 16 == 0)
|
|
{
|
|
fs_file.entry_sector++;
|
|
|
|
/* Ãðàíèöà êëàñòåðà */
|
|
if(fs_file.entry_cluster != 0 && ((fs_file.entry_index / 16) % fs_csize) == 0)
|
|
{
|
|
|
|
/* Ñëåäóþùèé êëàñòåð */
|
|
fs_tmp = fs_file.entry_cluster;
|
|
if(fs_nextCluster()) return 1;
|
|
if(fs_tmp == 0) goto retEnd; /* Ïîñëåäíèé êëàñòåð, óñòàíàëèâàåì fs_file.entry_able = 0 */
|
|
|
|
/* Ñîõðàíÿåì */
|
|
fs_file.entry_cluster = fs_tmp;
|
|
fs_clust2sect();
|
|
fs_file.entry_sector = fs_tmp;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fs_file.entry_index = 0;
|
|
fs_file.entry_able = 1;
|
|
fs_tmp = fs_file.entry_start_cluster;
|
|
|
|
/* Ïåðâûé êëàñòåð è ñåêòîð ïàïêè. Ýòîò êîä íå èìååò ñìûñëà âûïîëíÿòü
|
|
äëÿ FAT16, íî çàòî êîä õîðîøî ñæèìàåòñÿ. Ò.ê. ýòîò êóñîê êîäà àíàëîãè÷åí
|
|
êóñêó âûøå. */
|
|
fs_file.entry_cluster = fs_tmp;
|
|
fs_clust2sect();
|
|
fs_file.entry_sector = fs_tmp;
|
|
|
|
/* Êîðíåâàÿ ïàïêà FS_FAT16 */
|
|
if(fs_file.entry_cluster == 0) fs_file.entry_sector = fs_dirbase;
|
|
}
|
|
|
|
return sd_read(FS_DIRENTRY, fs_file.entry_sector, (uint16_t)((fs_file.entry_index % 16) * 32), 32);
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Ïîëó÷èòü î÷åðåäíîé ôàéë èëè ïàïêó (óäàëåííûå ôàéëû ïðîïóñêàþòñÿ) *
|
|
* *
|
|
* Ýòà ôóíêöèÿ âûçûâàåòñÿ ïîñëå fs_opendir, êîòîðàÿ íàñòðàèâàåò âñå *
|
|
* íóæíûå ïåðåìåííûå, ïîýòîìó âàì íè÷åãî òðîãàòü íå íàäî. Èíôîðìàöèÿ *
|
|
* íèæå ïðèâåäåíà äëÿ ëó÷øåãî ïîíèìàíèÿ ðàáîòû *
|
|
* *
|
|
* Åñëè íà âõîäå entry_able=0, òî íà÷èíàåòñÿ íîâûé ïîèñê â ïàïêå *
|
|
* ïî àäðåñó entry_start_cluster. Ïðè ýòîì èíèöèàëèçèðóþòñÿ ïåðåìåííûå: *
|
|
* entry_able, entry_index, entry_sector, entry_cluster. *
|
|
* *
|
|
* Åñëè íà âõîäå fs_file.entry_able=1, òî èñïîëüçóþòñÿ ýòè 4 ïåðåìåííûå. *
|
|
* *
|
|
* Íà âûõîäå *
|
|
* entry_able - åñëè 0 çíà÷èò äîñòèãíóò êîíåö êàòàëîãà *
|
|
* entry_sector - ñåêòîð îïèñàòåëÿ *
|
|
* entry_cluster - êëàñòåð îïèñàòåëÿ *
|
|
* entry_index - íîìåð îïèñàòåëÿ *
|
|
* FS_DIRENTRY - îïèñàòåëü *
|
|
* *
|
|
* Ôóíêöèÿ íå ïîðòèò buf[0..MAX_FILENAME-1] *
|
|
**************************************************************************/
|
|
|
|
uint8_t fs_readdir_nocheck()
|
|
{
|
|
while(!fs_readdirInt())
|
|
{
|
|
if(FS_DIRENTRY[DIR_Name] == 0) fs_file.entry_able = 0;
|
|
if(fs_file.entry_able == 0) return 0;
|
|
if(FS_DIRENTRY[DIR_Name] == 0xE5) continue; /* Ìîæåò áûòü åùå 0x05 */
|
|
if(FS_DIRENTRY[DIR_Name] == '.') continue;
|
|
if((FS_DIRENTRY[DIR_Attr] & AM_VOL) == 0) return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
uint8_t fs_readdir()
|
|
{
|
|
#ifndef FS_DISABLE_CHECK
|
|
/* Ïàïêà äîëæíà áûòü îòêðûòà */
|
|
if(fs_file.opened != OPENED_DIR)
|
|
{
|
|
lastError = ERR_NOT_OPENED;
|
|
return 1;
|
|
}
|
|
#endif
|
|
return fs_readdir_nocheck();
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Ñîõðàíèòü èçìåíåíèÿ â îáå òàáëèöû FAT *
|
|
**************************************************************************/
|
|
|
|
static uint8_t fs_saveFatSector(uint32_t sector)
|
|
{
|
|
if(fs_fatbase2) if(sd_writeBuf(fs_fatbase2+sector)) return 1;
|
|
return sd_writeBuf(fs_fatbase+sector);
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Âûäåëèòü êëàñòåð *
|
|
* *
|
|
* Íàéäåííûé êëàñòåð ñîõðàíÿåòñÿ â fs_tmp *
|
|
**************************************************************************/
|
|
|
|
/* Ðàäè ôóíêöèè fs_getfree ïðèøëîñü óñëîæíèòü ôóíêöèþ fs_allocCluster.
|
|
Åñëè ôóíêöèÿ íå èñïîëüçóåòñÿ, òî ìîæíî ñ ïîìîùüþ ìàêðîñà FS_DISABLE_GETFREESPACE
|
|
èñêëþ÷èòü ëèøíèé êîä */
|
|
|
|
#ifdef FS_DISABLE_GETFREESPACE
|
|
#define DIS(X)
|
|
#define ALLOCCLUSTER
|
|
#else
|
|
#define DIS(X) X
|
|
#define ALLOCCLUSTER 0
|
|
#endif
|
|
|
|
static uint8_t fs_allocCluster(DIS(uint8_t freeSpace))
|
|
{
|
|
uint8_t i;
|
|
uint32_t s;
|
|
uint8_t *a;
|
|
|
|
/* Íà÷èíàåì ïîèñê ñ ýòîãî êëàñòåðà */
|
|
fs_tmp = fs_fatoptim;
|
|
|
|
/* Ïîñëåäîâàòåëüíî ïåðåáèðàåì ñåêòîðà */
|
|
while(1)
|
|
{
|
|
/* Ñåêòîð è ñìåùåíèå */
|
|
s = fs_tmp / 256, i = (uint8_t)fs_tmp, a = (uint8_t*)((uint16_t*)buf + i);
|
|
if(fs_type != FS_FAT16) s = fs_tmp / 128, i |= 128, a = (uint8_t*)((uint32_t*)buf - 128 + i);
|
|
|
|
/* ×èòàåì ñåêòîð */
|
|
if(sd_readBuf(fs_fatbase + s)) goto abort;
|
|
|
|
/* Ñðåäè 128/256 ÷èñåë â ñåêòîðå èùåì 0 */
|
|
/* Êó÷à ïðîâåðîê âíóòðè öèêëà íå ñàìîå áûñòðîå ðåøåíèå, íî çàòî ïîëó÷àåòñÿ î÷åíü êîìïàêòíûé êîä. */
|
|
do
|
|
{
|
|
/* Êëàñòåðû êîí÷èëèñü */
|
|
if(fs_tmp >= fs_n_fatent)
|
|
{
|
|
DIS(if(freeSpace) return 0;) lastError = ERR_NO_FREE_SPACE;
|
|
goto abort;
|
|
}
|
|
|
|
/* Èùåì ñâîáîäíûé êëàñòåð è ïîìå÷àåì êàê ïîñëåäíèé */
|
|
if(fs_type == FS_FAT16)
|
|
{
|
|
if(LD_uint16_t(a) == 0)
|
|
{
|
|
DIS(if(!freeSpace)
|
|
{
|
|
) LD_uint16_t(a) = (uint16_t)LAST_CLUSTER;
|
|
goto founded;
|
|
DIS(
|
|
}
|
|
fs_file.sector++;)
|
|
}
|
|
a += 2;
|
|
}
|
|
else
|
|
{
|
|
if(LD_uint32_t(a) == 0)
|
|
{
|
|
DIS(if(!freeSpace)
|
|
{
|
|
) LD_uint32_t(a) = LAST_CLUSTER;
|
|
goto founded;
|
|
DIS(
|
|
}
|
|
fs_file.sector++;)
|
|
}
|
|
a += 4;
|
|
}
|
|
|
|
/* Ñ÷åò÷èê */
|
|
++fs_tmp, ++i;
|
|
}
|
|
while(i != 0);
|
|
}
|
|
founded:
|
|
/* Îïòèìèçàöèÿ */
|
|
fs_fatoptim = fs_tmp;
|
|
|
|
/* Ñîõðàíÿåì èçìåíåíèÿ */
|
|
return fs_saveFatSector(s);
|
|
abort:
|
|
return 1;
|
|
}
|
|
|
|
#undef DIS
|
|
|
|
/**************************************************************************
|
|
* Èçìåíåíèå òàáëèöû FAT *
|
|
* *
|
|
* Åñëè fs_tmp!=0, òî FAT[cluster] = fs_tmp *
|
|
* Åñëè fs_tmp==0, òî swap(FAT[cluster], fs_tmp) *
|
|
**************************************************************************/
|
|
|
|
static uint8_t fs_setNextCluster(uint32_t cluster)
|
|
{
|
|
uint32_t s, prev;
|
|
void* a;
|
|
|
|
/* Âû÷èñëÿåì ñåêòîð */
|
|
s = cluster / 128;
|
|
if(fs_type == FS_FAT16) s = cluster / 256;
|
|
|
|
/* ×èòàåì ñåêòîð */
|
|
if(sd_readBuf(fs_fatbase + s)) return 1;
|
|
|
|
/* Èçìåíÿåì îòäåëüíûé êëàñòåð */
|
|
if(fs_type == FS_FAT16)
|
|
{
|
|
a = (uint16_t*)buf + (uint8_t)cluster;
|
|
prev = LD_uint16_t(a);
|
|
LD_uint16_t(a) = (uint16_t)fs_tmp;
|
|
}
|
|
else
|
|
{
|
|
a = (uint32_t*)buf + (uint8_t)cluster % 128;
|
|
prev = LD_uint32_t(a);
|
|
LD_uint32_t(a) = fs_tmp;
|
|
}
|
|
|
|
/* Îïòèìèçàöèÿ ïîèñêà ñâîáîäíîãî êëàñòåðà. Âíåçàïíî if() if() çàíèìàåò ìåíüøå ÏÇÓ, ÷åì && */
|
|
if(fs_tmp == FREE_CLUSTER) if(cluster < fs_fatoptim) fs_fatoptim = cluster;
|
|
|
|
/* Ðåçóëüòàò */
|
|
if(fs_tmp == LAST_CLUSTER || fs_tmp == FREE_CLUSTER)
|
|
fs_tmp = prev;
|
|
|
|
/* Ñîõðàíÿåì ñåêòîð */
|
|
return fs_saveFatSector(s);
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Óñòàíîâèòü â îïèñàòåëü êëàñòåð *
|
|
**************************************************************************/
|
|
|
|
static void fs_setEntryCluster(uint8_t* entry, uint32_t cluster)
|
|
{
|
|
LD_uint16_t(entry + DIR_FstClusLO) = (uint16_t)(cluster);
|
|
LD_uint16_t(entry + DIR_FstClusHI) = (uint16_t)(cluster >> 16);
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Î÷èñòèòü êëàñòåð è áóôåð *
|
|
**************************************************************************/
|
|
|
|
static uint8_t fs_eraseCluster(uint8_t i)
|
|
{
|
|
memset(buf, 0, 512);
|
|
for(; i < fs_csize; ++i)
|
|
if(sd_writeBuf(fs_tmp + i)) return 1;
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Âûäåëèòü îïèñàòåëü â êàòàëîãå *
|
|
* *
|
|
* entry_able äîëæíî áûòü ðàâíî 0 *
|
|
* entry_start_cluster äîëæåí ñîäåðæàòü ïåðâûé êëàñòåð ïàïêè *
|
|
**************************************************************************/
|
|
|
|
static uint8_t* fs_allocEntry()
|
|
{
|
|
/* Èùåì â ïàïêå ïóñòîé îïèñàòåëü. */
|
|
while(1)
|
|
{
|
|
if(fs_readdirInt()) return 0;
|
|
|
|
/* Êëàñòåðû êîí÷èëèñü */
|
|
if(!fs_file.entry_able) break;
|
|
|
|
/* Ýòî ñâîáîäíûé îïèñàòåëü */
|
|
if(FS_DIRENTRY[0] == 0xE5 || FS_DIRENTRY[0] == 0) /* Ìîæåò áûòü åùå 0x05 */
|
|
{
|
|
|
|
/* ×èòàåì ñåêòîð */
|
|
if(sd_readBuf(fs_file.entry_sector)) return 0;
|
|
|
|
/* Íàéäåííûé îïèñàòåëü */
|
|
return buf + (fs_file.entry_index % 16) * 32;
|
|
}
|
|
}
|
|
|
|
/* Îãðàíè÷åíèå ïî êîë-âó ôàéëîâ */
|
|
/* Êîðíåâîé êàòàëîã FAT16 òàê æå âåðíåò fs_file.entry_index == 0 */
|
|
if(fs_file.entry_index == 0)
|
|
{
|
|
lastError = ERR_DIR_FULL;
|
|
return 0;
|
|
}
|
|
|
|
/* Âûäåëèòü êëàñòåð. Ðåçóëüòàò â fs_tmp */
|
|
if(fs_allocCluster(ALLOCCLUSTER)) return 0;
|
|
|
|
/* Äîáàâèòü åùå îäèí êëàñòåð ê ïàïêå. */
|
|
if(fs_setNextCluster(fs_file.entry_cluster)) return 0; /* fs_tmp ñîõðàíèòñÿ, òàê êàê îí íå LAST è íå FREE */
|
|
|
|
/* Çàïîëíÿåì îòâåò */
|
|
fs_file.entry_cluster = fs_tmp;
|
|
fs_clust2sect();
|
|
fs_file.entry_sector = fs_tmp;
|
|
|
|
/* Î÷èùàåì êëàñòåð è çà îäíî BUF (èñïîëüçóåòñÿ ïåðåìåííàÿ fs_tmp) */
|
|
fs_eraseCluster(0);
|
|
|
|
/* Íàéäåííûé îïèñàòåëü */
|
|
return buf;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Îòêðûòü/ñîçäàòü ôàéë èëè ïàïêó *
|
|
* *
|
|
* Èìÿ ôàéëà â buf. Îíî íå äîëæíî ïðåâûøàòü FS_MAXFILE ñèìîëîâ âêëþ÷àÿ 0 *
|
|
* *
|
|
* what = OPENED_NONE - Îòêðûòü ôàéë èëè ïàïêó *
|
|
* what = OPENED_FILE - Ñîçäàòü ôàéë (ñîçäàííûé ôàéë îòêðûò) *
|
|
* what = OPENED_DIR - Ñîçäàòü ïàïêó (ñîçäàííàÿ ïàïêà íå îòêðûòà) *
|
|
* what | 0x80 - Íå ñîçäàâàòü ôàéë â ïàïêå entry_start_cluster *
|
|
* *
|
|
* Íà âûõîäå *
|
|
* FS_DIRENTRY - îïèñàòåëü *
|
|
* fs_file.entry_able - 0 (åñëè îòêðûò ñóùåñòâóþùèé ôàéë/ïàïêà) *
|
|
* fs_file.entry_sector - ñåêòîð îïèñàòåëÿ *
|
|
* fs_file.entry_cluster - êëàñòåð îïèñàòåëÿ *
|
|
* fs_file.entry_index - íîìåð îïèñàòåëÿ *
|
|
* fs_file.entry_start_cluster - ïåðâûé êëàñòåð ôàéëà èëè ïàïêè *
|
|
* fs_parent_dir_cluster - ïåðâûé êëàñòåð ïàïêè ïðåäêà (CREATE) *
|
|
* fs_file.ptr - 0 (åñëè îòêðûò ôàéë) *
|
|
* fs_file.size - ðàçìåð ôàéëà (åñëè îòêðûò ôàéë) *
|
|
* *
|
|
* Ôóíêöèÿ íå ïîðòèò buf[0..MAX_FILENAME-1] *
|
|
**************************************************************************/
|
|
|
|
static uint8_t fs_open0_create(uint8_t dir); /* forward */
|
|
static uint8_t* fs_open0_name(uint8_t *p); /* forward */
|
|
|
|
#define FS_DIRFIND (buf + 469) /* 11 áàéò èñïîëüçóþùèåñÿ âíóòðè ôóíêöèè fs_open0 */
|
|
#define fs_notrootdir (*(uint8_t*)&fs_file.size) /* Èñïîëüçóåòñÿ fs_open0, â ýòî âðåìÿ ïåðåìåííûå fs_file. íå ñîäåæàò íóæíûõ çíà÷åíèÿ */
|
|
#define fs_parent_dir_cluster fs_file.sector /* Òàê æå èñïîëüçóåòñÿ fs_file.sector äëÿ õðàíåíèÿ ïåðâîãî êëàñòåðà ïàïêè ïðåäêà. */
|
|
|
|
uint8_t fs_open0(uint8_t what)
|
|
{
|
|
uint8_t *path;
|
|
uint8_t r;
|
|
|
|
/* Ïðîâåðêà îøèáîê ïðîãðàììèñòà */
|
|
#ifndef FS_DISABLE_CHECK
|
|
if(fs_type == FS_ERROR)
|
|
{
|
|
lastError = ERR_NO_FILESYSTEM;
|
|
goto abort;
|
|
}
|
|
fs_file.opened = OPENED_NONE;
|
|
#endif
|
|
|
|
/* Ïðåäîòâðàùåíèå ðåêóðñèè */
|
|
r = what & 0x80;
|
|
what &= 0x7F;
|
|
fs_parent_dir_cluster = fs_file.entry_start_cluster;
|
|
|
|
/* Êîðíåâîé êàòàëîã */
|
|
fs_notrootdir = 0;
|
|
fs_file.entry_start_cluster = fs_dirbase;
|
|
if(fs_type == FS_FAT16) fs_file.entry_start_cluster = 0;
|
|
|
|
/* Êîðíåâàÿ ïàïêà */
|
|
if(buf[0] == 0)
|
|
{
|
|
if(what) goto abort_noPath;
|
|
FS_DIRENTRY[0] = 0; /* Ïðèçíàê êîðíåâîé ïàïêè */
|
|
FS_DIRENTRY[DIR_Attr] = AM_DIR; /* Äëÿ óïðîùåíèÿ îïðåäåëåíèÿ ôàéë/ïàïêà çàïèøåì ñþäà AM_DIR */
|
|
}
|
|
else
|
|
{
|
|
path = buf;
|
|
while(1)
|
|
{
|
|
/* Ïîëó÷àåì î÷åðåäíîå èìÿ èç path â FS_DIRFIND */
|
|
path = fs_open0_name(path);
|
|
if(path == (uint8_t*)1) goto abort_noPath;
|
|
/* Èùåì èìÿ â ïàïêå */
|
|
fs_file.entry_able = 0;
|
|
while(1)
|
|
{
|
|
if(fs_readdir_nocheck()) return 1;
|
|
if(fs_file.entry_able == 0) break;
|
|
if(!memcmp(FS_DIRENTRY, FS_DIRFIND, 11)) break;
|
|
}
|
|
/* Ïîñëåäíèé ýëåìåíòó ïóòè â ðåæèìå ñîçäàíèÿ */
|
|
if(what && path == 0)
|
|
{
|
|
fs_parent_dir_cluster = fs_file.entry_start_cluster; /* Ñîõðàíÿåì â ýòîé ïåðåìåííîé ðåçóëüòàò äëÿ ôóíöèè fs_move */
|
|
if(fs_type == FS_FAT32 && fs_parent_dir_cluster == fs_dirbase) fs_parent_dir_cluster = 0;
|
|
if(fs_file.entry_able == 0) return fs_open0_create(what-1); /* Ïðîäîëæèì òàì */
|
|
lastError = ERR_FILE_EXISTS;
|
|
goto abort;
|
|
}
|
|
/* Ôàéë/ïàïêà íå íàéäåíà */
|
|
if(fs_file.entry_able == 0) goto abort_noPath;
|
|
|
|
/* ×òî òî íàéäåíî */
|
|
fs_file.entry_start_cluster = fs_getEntryCluster();
|
|
/* Ýòî áûë ïîñëåäíèé ýëåìåíò ïóòè */
|
|
if(path == 0) break;
|
|
/* Ýòî äîëæíà áûòü ïàïêà */
|
|
if((FS_DIRENTRY[DIR_Attr] & AM_DIR) == 0) goto abort_noPath;
|
|
/* Ïðåäîòâðàùàåì ðåêóðñèþ äëÿ ôóíêöèè fs_move */
|
|
if(r && fs_file.entry_start_cluster == fs_parent_dir_cluster) goto abort_noPath;
|
|
/* Íàäåííàÿ ïàïêà óæå íå áóäåò êîðíåâîé */
|
|
fs_notrootdir = 1;
|
|
}
|
|
}
|
|
/* Óñòàíàâëèâàåì ïåðåìåííûå */
|
|
fs_file.entry_able = 0;
|
|
fs_file.size = LD_uint32_t(FS_DIRENTRY + DIR_FileSize);
|
|
fs_file.ptr = 0;
|
|
#ifndef FS_DISABLE_CHECK
|
|
fs_file.opened = OPENED_FILE;
|
|
if(FS_DIRENTRY[DIR_Attr] & AM_DIR) fs_file.opened = OPENED_DIR;
|
|
#endif
|
|
|
|
/* Íåëüçÿ äâàæäû îòêðûâàòü ôàéë */
|
|
#ifndef FS_DISABLE_CHECK
|
|
#ifndef FS_DISABLE_SWAP
|
|
if(fs_secondFile.opened==OPENED_FILE && fs_file.opened==OPENED_FILE && fs_secondFile.entry_sector == fs_file.entry_sector && fs_secondFile.entry_index==fs_file.entry_index)
|
|
{
|
|
fs_file.opened = OPENED_NONE;
|
|
lastError = ERR_ALREADY_OPENED;
|
|
goto abort;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
return 0;
|
|
abort_noPath:
|
|
lastError = ERR_NO_PATH;
|
|
abort:
|
|
return 1;
|
|
}
|
|
|
|
static uint8_t exists(const /*flash*/ uint8_t* str, uint8_t c)
|
|
{
|
|
while(*str)
|
|
if(*str++ == c)
|
|
return c;
|
|
return 0;
|
|
}
|
|
|
|
static uint8_t * fs_open0_name(uint8_t *p)
|
|
{
|
|
uint8_t c, ni, i;
|
|
|
|
memset(FS_DIRFIND, ' ', 11);
|
|
i = 0;
|
|
ni = 8;
|
|
while(1)
|
|
{
|
|
c = *p++;
|
|
if(c == 0)
|
|
{
|
|
if(i == 0) break; /* Ïóñòîå èìÿ ôàéëà */
|
|
return 0;
|
|
}
|
|
if(c == '/') return p;
|
|
if(c == '.')
|
|
{
|
|
if(i == 0) break; /* Ïóñòîå èìÿ ôàéëà */
|
|
#ifndef FS_DISABLE_CHECK
|
|
if(ni != 8) break; /* Âòîðàÿ òî÷êà */
|
|
#endif
|
|
i = 8;
|
|
ni = 11;
|
|
continue;
|
|
}
|
|
/* Ñëèøêîì äëèííîå èìå */
|
|
if(i == ni) break;
|
|
/* Çàïðåùåííûå ñèìâîëû */
|
|
#ifndef FS_DISABLE_CHECK
|
|
if(exists((const /*flash*/ uint8_t*)"+,;=[]*?<:>\\|\"", c)) break;
|
|
if(c <= 0x20) break;
|
|
if(c >= 0x80) break;
|
|
#endif
|
|
/* Ïðèâîäèì ê âåðõíåìó ðåãèñòðó */
|
|
if(c >= 'a' && c <= 'z') c -= 0x20;
|
|
/* Ñîõðàíÿåì èìÿ */
|
|
FS_DIRFIND[i++] = c;
|
|
}
|
|
/* Îøèáêà */
|
|
return (uint8_t*)1;
|
|
}
|
|
|
|
static uint8_t fs_open0_create(uint8_t dir)
|
|
{
|
|
uint8_t new_name[11];
|
|
uint32_t allocatedCluster;
|
|
uint8_t* allocatedEntry;
|
|
|
|
/* Ñîõðàíÿåì èìÿ, òàê êàê âåñü áóôåð áóäåò çàòåðò */
|
|
memcpy(new_name, FS_DIRFIND, 11);
|
|
|
|
/* Âûäåëÿåì êëàñòåð äëÿ ïàïêè */
|
|
if(dir)
|
|
{
|
|
if(fs_allocCluster(ALLOCCLUSTER)) goto abort; /* fs_file.entry_start_cluster èçìåíåí íå áóäåò, òàì ïåðâûé êëàñòåð ïàïêè â êîòîðîé ìû ñîçäàäèì ôàéë */
|
|
allocatedCluster = fs_tmp;
|
|
}
|
|
|
|
/* Äîáàâëÿåì â ïàïêó îïèñàòåëü (ñåêòîð íå ñîõðàíåí) */
|
|
allocatedEntry = fs_allocEntry();
|
|
if(allocatedEntry == 0)
|
|
{
|
|
|
|
/*  ñëó÷àå îøèáêè îñâîáîæäàåì êëàñòåð */
|
|
fs_tmp = FREE_CLUSTER;
|
|
fs_setNextCluster(allocatedCluster);
|
|
goto abort;
|
|
}
|
|
|
|
/* Óñòàíàëèâàåì èìÿ â îïèñàòåëü. */
|
|
memset(allocatedEntry, 0, 32);
|
|
memcpy(allocatedEntry, new_name, 11);
|
|
|
|
/* ========== ÓÑÒÀÍÎÂÊÀ ÄÀÒÛ È ÂÐÅÌÅÍÈ ========== */
|
|
/* Ïîëó÷àåì òåêóùåå âðåìÿ è äàòó */
|
|
uint16_t fat_time = fat_pack_time();
|
|
uint16_t fat_date = fat_pack_date();
|
|
|
|
/* Óñòàíàâëèâàåì âðåìÿ ñîçäàíèÿ */
|
|
LD_uint16_t(allocatedEntry + DIR_CrtTime) = fat_time;
|
|
LD_uint16_t(allocatedEntry + DIR_CrtDate) = fat_date;
|
|
|
|
/* Óñòàíàâëèâàåì âðåìÿ ïîñëåäíåé çàïèñè (òàêîå æå, êàê è âðåìÿ ñîçäàíèÿ) */
|
|
LD_uint16_t(allocatedEntry + DIR_WrtTime) = fat_time;
|
|
LD_uint16_t(allocatedEntry + DIR_WrtDate) = fat_date;
|
|
|
|
/* Îáíóëÿåì çàðåçåðâèðîâàííîå ïîëå (äëÿ ñîâìåñòèìîñòè) */
|
|
allocatedEntry[DIR_NTres] = 0;
|
|
/* ============================================== */
|
|
|
|
if(!dir)
|
|
{
|
|
/* Ñîõðàíÿåì îïèñàòåëü íà äèñê */
|
|
if(sd_writeBuf(fs_file.entry_sector)) goto abort;
|
|
/* fs_file.entry_sector, fs_file.entry_index - óñòàíàâëèàåòñÿ â fs_allocCluster */
|
|
fs_file.entry_start_cluster = 0;
|
|
fs_file.size = 0;
|
|
fs_file.ptr = 0;
|
|
#ifndef FS_DISABLE_CHECK
|
|
fs_file.opened = OPENED_FILE;
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
/* Ýòî ïàïêà */
|
|
allocatedEntry[DIR_Attr] = AM_DIR;
|
|
fs_setEntryCluster(allocatedEntry, allocatedCluster);
|
|
|
|
/* Ñîõðàíÿåì îïèñàòåëü íà äèñê */
|
|
if(sd_writeBuf(fs_file.entry_sector)) goto abort;
|
|
|
|
/* Ñåêòîð äëÿ íîâîé ïàïêè */
|
|
fs_tmp = allocatedCluster;
|
|
fs_clust2sect();
|
|
|
|
/* Î÷èùàåì fs_tmp è çà îäíî buf */
|
|
fs_eraseCluster(1);
|
|
|
|
/* Ñîçäàåì ïóñòóþ ïàïêó */
|
|
memset(buf, ' ', 11);
|
|
buf[0] = '.';
|
|
buf[11] = 0x10;
|
|
fs_setEntryCluster(buf, allocatedCluster);
|
|
|
|
/* Óñòàíàâëèâàåì äàòó/âðåìÿ äëÿ çàïèñè "." â ïàïêå */
|
|
LD_uint16_t(buf + DIR_CrtTime) = fat_time;
|
|
LD_uint16_t(buf + DIR_CrtDate) = fat_date;
|
|
LD_uint16_t(buf + DIR_WrtTime) = fat_time;
|
|
LD_uint16_t(buf + DIR_WrtDate) = fat_date;
|
|
|
|
memset(buf+32, ' ', 11);
|
|
buf[32] = '.';
|
|
buf[33] = '.';
|
|
buf[32+11] = 0x10;
|
|
if(fs_notrootdir) fs_setEntryCluster(buf + 32, fs_file.entry_start_cluster); /* Ñåé÷àñ â fs_file.size==0 çíà÷èò êîðíåâîé êàòàëîã */
|
|
|
|
/* Óñòàíàâëèâàåì äàòó/âðåìÿ äëÿ çàïèñè ".." â ïàïêå */
|
|
LD_uint16_t(buf + 32 + DIR_CrtTime) = fat_time;
|
|
LD_uint16_t(buf + 32 + DIR_CrtDate) = fat_date;
|
|
LD_uint16_t(buf + 32 + DIR_WrtTime) = fat_time;
|
|
LD_uint16_t(buf + 32 + DIR_WrtDate) = fat_date;
|
|
|
|
/* Ñîõðàíÿåì ïàïêó */
|
|
return sd_writeBuf(fs_tmp);
|
|
abort:
|
|
return 1;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Îòêðûòü ôàéë *
|
|
**************************************************************************/
|
|
|
|
uint8_t fs_open()
|
|
{
|
|
if(fs_openany()) goto abort;
|
|
#ifndef FS_DISABLE_CHECK
|
|
if(fs_file.opened == OPENED_FILE) return 0;
|
|
fs_file.opened = OPENED_NONE;
|
|
#else
|
|
if((FS_DIRENTRY[DIR_Attr] & AM_DIR) == 0) return 0;
|
|
#endif
|
|
lastError = ERR_NO_PATH;
|
|
abort:
|
|
return 1;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Îòêðûòü ïàïêó *
|
|
**************************************************************************/
|
|
|
|
uint8_t fs_opendir()
|
|
{
|
|
if(fs_openany()) goto abort;
|
|
#ifndef FS_DISABLE_CHECK
|
|
if(fs_file.opened == OPENED_DIR) return 0;
|
|
fs_file.opened = OPENED_NONE;
|
|
#else
|
|
if(FS_DIRENTRY[DIR_Attr] & AM_DIR) return 0;
|
|
#endif
|
|
lastError = ERR_NO_PATH;
|
|
abort:
|
|
return 1;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Âû÷èñëèòü íîìåð ñëåäóþùåãî ñåêòîðà äëÿ ÷òåíèÿ/çàïèñè *
|
|
* Âûçûâàåòñÿ òîëüêî èç fs_read0, fs_write_start *
|
|
**************************************************************************/
|
|
|
|
static uint8_t fs_nextRWSector()
|
|
{
|
|
if(fs_file.ptr == 0)
|
|
{
|
|
/* ×òåíèå ôàéëà åùå íå íà÷àòî */
|
|
fs_tmp = fs_file.entry_start_cluster;
|
|
}
|
|
else
|
|
{
|
|
/* Åùå íå êîíåö ñåêòîðà */
|
|
if((uint16_t)fs_file.ptr % 512) return 0;
|
|
|
|
/* Ñëåäóþùèé ñåêòîð */
|
|
fs_file.sector++;
|
|
|
|
/* Åùå íå êîíåö êëàñòåðà */
|
|
if(((fs_file.sector - fs_database) % fs_csize) != 0) return 0;
|
|
|
|
/* Ñëåäóþùèé êëàñòåð */
|
|
fs_tmp = fs_file.cluster;
|
|
if(fs_nextCluster()) return 1;
|
|
}
|
|
|
|
/* Åñëè ýòî áûë ïîñëåäíèé êëàñòåð, äîáàâëÿåì íîâûé */
|
|
if(fs_tmp == 0)
|
|
{
|
|
if(fs_allocCluster(ALLOCCLUSTER)) return 1;
|
|
if(fs_file.ptr == 0) fs_file.entry_start_cluster = fs_tmp;
|
|
else fs_setNextCluster(fs_file.cluster); /* fs_tmp ñîõðàíèòñÿ, òàê êàê îí íå LAST è íå FREE */
|
|
}
|
|
|
|
/* Îê */
|
|
fs_file.cluster = fs_tmp;
|
|
fs_clust2sect();
|
|
fs_file.sector = fs_tmp;
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Ïðî÷èòàòü èç ôàéëà íåñêîëüêî áàéò â buf *
|
|
* *
|
|
* Ïîëüçîâàòåëü íå äîëæåí âûõîäèòü çà ïðåäåëû ôàéëà ïðè ÷òåíèè, èíà÷å *
|
|
* âîçíèêíåò óòå÷êà ñâîáîæíîãî ìåñòà íà äèñêå. *
|
|
* *
|
|
* Àðãóìåíòû: *
|
|
* ptr - áóôåð äëÿ ÷òåíèÿ, ìîæåò áûòü buf *
|
|
* len - êîë-âî áàéò, êîòîðûå íåîáõîäèìî ïðî÷èòàòü *
|
|
**************************************************************************/
|
|
|
|
uint8_t fs_read0(uint8_t* ptr, uint16_t len)
|
|
{
|
|
uint16_t sectorLen;
|
|
|
|
/* Ïðîâåðêà îøèáîê ïðîãðàììèñòà */
|
|
#ifndef FS_DISABLE_CHECK
|
|
if(fs_file.opened != OPENED_FILE)
|
|
{
|
|
lastError = ERR_NOT_OPENED;
|
|
goto abort;
|
|
}
|
|
#endif
|
|
|
|
while(len)
|
|
{
|
|
/* Åñëè óêàçàòåëü íàõîäèòñÿ íà ãðàíèöå ñåêòîðà */
|
|
if(fs_nextRWSector()) goto abort;
|
|
|
|
/* Êîë-âî áàéò äî êîíöà ñåêòîðà */
|
|
sectorLen = 512 - ((uint16_t)fs_file.ptr % 512);
|
|
if(len < sectorLen) sectorLen = len;
|
|
|
|
/* ×èòàåì äàííûå */
|
|
if(ptr)
|
|
{
|
|
if(sd_read(ptr, fs_file.sector, (uint16_t)fs_file.ptr % 512, sectorLen)) goto abort;
|
|
ptr += sectorLen;
|
|
}
|
|
|
|
/* Óâåëè÷èâàåì ñìåùåíèå */
|
|
fs_file.ptr += sectorLen;
|
|
len -= sectorLen;
|
|
}
|
|
|
|
/* Óâåëè÷åíèå ðàçìåðà ôàéëà */
|
|
if(fs_file.ptr > fs_file.size) fs_file.size = fs_file.ptr, fs_file.changed = 1;
|
|
|
|
return 0;
|
|
abort:
|
|
#ifndef FS_DISABLE_CHECK
|
|
fs_file.opened = OPENED_NONE;
|
|
#endif
|
|
return 1;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Ïðî÷èòàòü èç ôàéëà íåñêîëüêî áàéò â buf *
|
|
* *
|
|
* Àðãóìåíòû: *
|
|
* ptr - áóôåð äëÿ ÷òåíèÿ, ìîæåò áûòü buf *
|
|
* len - êîë-âî áàéò, êîòîðûå íåîáõîäèìî ïðî÷èòàòü *
|
|
* readed - óêàçàòåëü, äëÿ ñîõðàíåíèÿ êîë-âà ðåàëüíî ïðî÷èòàííûõ áàéò *
|
|
**************************************************************************/
|
|
|
|
uint8_t fs_read(uint8_t* ptr, uint16_t len, uint16_t* readed)
|
|
{
|
|
/* Îãðàíè÷èâàåì êîë-âî áàéò äëÿ ÷òåíèÿ */
|
|
if(len > fs_file.size - fs_file.ptr) len = (uint16_t)(fs_file.size - fs_file.ptr);
|
|
*readed = len;
|
|
|
|
/* Ïðîâåðêà íà îøèáêè ïðîèñõîäèò òàì */
|
|
return fs_read0(ptr, len);
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Ñîõðàíèòü äëèíó ôàéëà è ïðåâûé êëàñòåð â îïèñòàåëü *
|
|
* Âûçûâàåòñÿ èç fs_lseek, fs_write_start, fs_write_end, fs_write_eof *
|
|
**************************************************************************/
|
|
|
|
static char fs_saveFileLength()
|
|
{
|
|
uint8_t* entry;
|
|
|
|
if(fs_file.changed == 0) return 0;
|
|
fs_file.changed = 0;
|
|
|
|
/* Èçìåíåíèå îïèñàòåëÿ ôàéëà */
|
|
if(sd_readBuf(fs_file.entry_sector)) return 1;
|
|
|
|
entry = buf + (fs_file.entry_index % 16) * 32;
|
|
LD_uint32_t(entry + DIR_FileSize) = fs_file.size;
|
|
fs_setEntryCluster(entry, fs_file.entry_start_cluster);
|
|
|
|
return sd_writeBuf(fs_file.entry_sector);
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Óñòàíîâèòü ñìåùåíèå ÷òåíèÿ/çàïèñè ôàéëà *
|
|
**************************************************************************/
|
|
|
|
#define LSEEK_STEP 32768
|
|
|
|
uint8_t fs_lseek(uint32_t off, uint8_t mode)
|
|
{
|
|
uint32_t l;
|
|
|
|
/* Ðåæèì */
|
|
if(mode==1) off += fs_file.ptr;
|
|
else if(mode==2) off += fs_file.size;
|
|
|
|
/* Ìîæíî çàìåíèòü íà fs_file.ptr = 0 äëÿ óìåíüøåíèÿ êîäà*/
|
|
if(off >= fs_file.ptr) off -= fs_file.ptr;
|
|
else fs_file.ptr = 0;
|
|
|
|
do /* Âûïîëíÿåì îäèí öèêë äàæå äëÿ off=0, òàê êàê âíóòðè ïðîèñõîäèò ïðîâåðêà íà îøèáêè */
|
|
{
|
|
l = off;
|
|
if(l > LSEEK_STEP) l = LSEEK_STEP;
|
|
if(fs_read0(0, (uint16_t)l)) return 1;
|
|
off -= l;
|
|
}
|
|
while(off);
|
|
|
|
/* Ðàçìåð ôàéëà ìîã èçìåíèòñÿ */
|
|
fs_saveFileLength();
|
|
|
|
/* Ðåçóëüòàò */
|
|
fs_tmp = fs_file.ptr;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Çàïèñàòü â ôàéë (øàã 1) *
|
|
***************************************************************************/
|
|
|
|
uint8_t fs_write_start()
|
|
{
|
|
uint16_t len;
|
|
|
|
/* Ïðîâåðêà îøèáîê ïðîãðàììèñòà */
|
|
#ifndef FS_DISABLE_CHECK
|
|
if(fs_file.opened != OPENED_FILE)
|
|
{
|
|
lastError = ERR_NOT_OPENED;
|
|
goto abort;
|
|
}
|
|
if(fs_wtotal == 0)
|
|
{
|
|
lastError = ERR_NO_DATA;
|
|
goto abort;
|
|
}
|
|
#endif
|
|
|
|
/* Ñêîëüêî ìîæíî åùå äîïèñàòü â ýòîò ñåêòîð? */
|
|
len = 512 - (uint16_t)fs_file.ptr % 512;
|
|
|
|
/* Îãðàíè÷èâàåì îñòàòêîì äàííûõ â ôàéëå */
|
|
if(len > fs_wtotal) len = (uint16_t)fs_wtotal;
|
|
|
|
/* Âû÷èñëåíèå fs_file.sector, âûäåëåíèå êëàñòåðîâ */
|
|
if(fs_nextRWSector()) goto abort; /* Äîëæíî âûëåòàòü òîëüêî ïî îøèáêàì ERR_NO_FREE_SPACE, ERR_DISK_ERR */
|
|
|
|
/* Êîððåêòèðóåì äëèíó ôàéëà */
|
|
if(fs_file.size < fs_file.ptr + len)
|
|
{
|
|
fs_file.size = fs_file.ptr + len;
|
|
fs_file.changed = 1;
|
|
}
|
|
|
|
/* ×èòàåì äàííûå ñåêòîðà, åñëè íå âåñü ñåêòîð áóäåò çàïîëíåí */
|
|
if(len != 512)
|
|
{
|
|
if(sd_readBuf(fs_file.sector)) goto abort;
|
|
}
|
|
|
|
fs_file_wlen = len;
|
|
fs_file_woff = (uint16_t)fs_file.ptr % 512;
|
|
return 0;
|
|
abort:
|
|
/* Ñêîðåå âñåãî ýòî îøèáêà ERR_NO_FREE_SPACE */
|
|
/* Åñëè ðàçìåð ôàéëà áûë èçìåíåí, òî íàäî áû ñîõðàíèòü èçìåíåíèÿ â îïèñàòåëü ôàéëà. */
|
|
fs_saveFileLength();
|
|
/* Çàêðûâàåì ôàéë */
|
|
#ifndef FS_DISABLE_CHECK
|
|
fs_file.opened = OPENED_NONE;
|
|
#endif
|
|
return 1;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Çàïèñàòü â ôàéë (øàã 2) *
|
|
***************************************************************************/
|
|
|
|
uint8_t fs_write_end()
|
|
{
|
|
#ifndef FS_DISABLE_CHECK
|
|
if(fs_file.opened != OPENED_FILE)
|
|
{
|
|
lastError = ERR_NOT_OPENED;
|
|
goto abort;
|
|
}
|
|
#endif
|
|
|
|
/* Çàïèñûâàåì èçìåíåíèÿ íà äèñê */
|
|
if(sd_writeBuf(fs_file.sector)) goto abort;
|
|
|
|
/*  ñëó÷àå îøèáêè ôàéë ìîæåò ñîäåðæàòü áîëüøå êëàñòåðîâ, ÷åì òðåáóåòñÿ ïî åãî ðàçìåðó. */
|
|
/* Íî ýòî íå ïëîõî, äàííûå íå ïîâðåæäåíû. À ýòà îøèáêà ïðîÿâèòñÿ ëèøü â óìåíüøåíèè */
|
|
/* ìåñòà íà äèñêå. */
|
|
|
|
/* Ñ÷åò÷èêè */
|
|
fs_file.ptr += fs_file_wlen;
|
|
fs_wtotal -= fs_file_wlen;
|
|
|
|
/* Åñëè çàïèñü çàêîí÷åíà, ñîõðàíÿåì ðàçìåðà ôàéëà è ïåðâûé êëàñòåð */
|
|
if(fs_wtotal == 0)
|
|
{
|
|
if(fs_saveFileLength()) goto abort;
|
|
|
|
if(fs_update_timestamp() != 0) {
|
|
/* Îøèáêà îáíîâëåíèÿ âðåìåíè - íå êðèòè÷íî, íî ìîæíî âåðíóòü îøèáêó */
|
|
/* goto abort; */ /* Ðàñêîììåíòèðóéòå, åñëè õîòèòå âîçâðàùàòü îøèáêó */
|
|
}
|
|
}
|
|
|
|
/* Îê */
|
|
return 0;
|
|
abort:
|
|
#ifndef FS_DISABLE_CHECK
|
|
fs_file.opened = OPENED_NONE;
|
|
#endif
|
|
return 1;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Îñâîáîäèòü öåïî÷êó êëàñòåðîâ íà÷èíàÿ ñ fs_tmp *
|
|
**************************************************************************/
|
|
|
|
static uint8_t fs_freeChain()
|
|
{
|
|
uint32_t c;
|
|
while(1)
|
|
{
|
|
if(fs_tmp < 2 || fs_tmp >= fs_n_fatent) return 0;
|
|
/* Îñâîáîäèòü êëàñòåð fs_tmp è çàïèñòü â fs_tmp ñëåäóþùèé çà íèì êëàñòåð */
|
|
c = fs_tmp, fs_tmp = FREE_CLUSTER;
|
|
if(fs_setNextCluster(c)) break; /* fs_tmp áóäåò ñîäåðæàòü ñëåäóþùèé êëàñòåð, òàê êàê çàïèñûâàåòñÿ FREE_CLUSTER */
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Ïåðåìåñòèòü ôàéë/ïàïêó *
|
|
**************************************************************************/
|
|
|
|
uint8_t fs_move0()
|
|
{
|
|
uint8_t* entry;
|
|
uint8_t tmp[21];
|
|
uint16_t old_index;
|
|
uint32_t old_sector, old_start_cluster;
|
|
|
|
#ifndef FS_DISABLE_CHECK
|
|
if(fs_file.opened == OPENED_NONE)
|
|
{
|
|
lastError = ERR_NOT_OPENED;
|
|
goto abort;
|
|
}
|
|
#endif
|
|
|
|
/* Çàïîìèíàåì ñòàðûé îïèñàòåëü */
|
|
old_index = fs_file.entry_index;
|
|
old_sector = fs_file.entry_sector;
|
|
old_start_cluster = fs_file.entry_start_cluster;
|
|
|
|
/* Ñîçäàåì íîâûé ôàéë. Â ïàïêó îí ïðåâðàòèòñÿ ïîçæå. 0x80 - ýòî ïðåäîòâðàùàåì ðåêóðñèþ. */
|
|
if(fs_open0(OPENED_FILE | 0x80)) goto abort;
|
|
|
|
/* Ïðåäîòâðàùàåì îøèáêè ïðîãðàììèñòà */
|
|
#ifndef FS_DISABLE_CHECK
|
|
fs_file.opened = OPENED_NONE;
|
|
#ifndef FS_DISABLE_SWAP
|
|
fs_secondFile.opened = OPENED_NONE;
|
|
#endif
|
|
#endif
|
|
/* fs_file.sector ñîäåæèò ïåðâûé êëàñòåð ïàïêè, â êîòîðîé íàõîäèòñÿ ñîçäàííûé ôàéë. */
|
|
|
|
/* Óäàëåíèå ñòàðîãî ôàéëà/ïàïêè è ïåðåíîñ âñåõ ñâîéñòâ */
|
|
if(sd_readBuf(old_sector)) goto abort;
|
|
entry = buf + (old_index % 16) * 32;
|
|
memcpy(tmp, entry+11, 21);
|
|
entry[0] = 0xE5;
|
|
if(sd_writeBuf(old_sector)) goto abort;
|
|
|
|
/* Êîïèðóåì âñå ñâîéñòâà íîâîìó ôàéëó, òåì ñàìûì ïðåâðàùàÿ åãî â ïàïêó */
|
|
if(sd_readBuf(fs_file.entry_sector)) goto abort;
|
|
entry = buf + (fs_file.entry_index % 16) * 32;
|
|
memcpy(entry+11, tmp, 21);
|
|
if(sd_writeBuf(fs_file.entry_sector)) goto abort;
|
|
|
|
/* Â ïàïêå íàäî åùå ñêîððåòèðîâàòü îïèñàòåëü .. */
|
|
if(entry[DIR_Attr] & AM_DIR)
|
|
{
|
|
fs_tmp = old_start_cluster; /* Ïåðâûé êëàñòåð íàøåé ïàïêè */
|
|
fs_clust2sect();
|
|
if(sd_readBuf(fs_tmp)) goto abort;
|
|
fs_setEntryCluster(buf+32, fs_parent_dir_cluster); /* Ïåðâûé êëàñòåð ïàïêè ïðåäêà.*/
|
|
if(sd_writeBuf(fs_tmp)) goto abort;
|
|
}
|
|
|
|
return 0;
|
|
abort:
|
|
return 1;
|
|
}
|
|
|
|
uint8_t fs_move(const char* from, const char* to)
|
|
{
|
|
strcpy((char*)buf, from);
|
|
if(fs_openany()) return 1;
|
|
strcpy((char*)buf, to);
|
|
return fs_move0();
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Óäàëèòü ôàéë èëè ïóñòóþ ïàïêó *
|
|
* Èìÿ ôàéëà äîëæíî ñîäåðæàòüñÿ â buf è íå ïðåâûøàòü FS_MAXFILE ñèìîëîâ *
|
|
* âêëþ÷àÿ òåðìèíàòîð *
|
|
**************************************************************************/
|
|
|
|
uint8_t fs_delete()
|
|
{
|
|
uint32_t entrySector;
|
|
uint8_t* entry;
|
|
|
|
/* Òàì áóäåò ïðîâåðåí fs_type == FS_ERROR */
|
|
if(fs_openany()) goto abort;
|
|
|
|
/* Ïðåäîòâðàùàåì îøèáêè ïðîãðàììèñòà */
|
|
fs_file.opened = OPENED_NONE;
|
|
#ifndef FS_DISABLE_SWAP
|
|
fs_secondFile.opened = OPENED_NONE;
|
|
#endif
|
|
|
|
/* Êîðíåâóþ ïàïêó óäàëÿòü íåëüçÿ */
|
|
if(FS_DIRENTRY[0] == 0)
|
|
{
|
|
lastError = ERR_NO_PATH;
|
|
goto abort;
|
|
}
|
|
|
|
/* Ñîõðàíÿåì èíòåðôîðìàöèþ î íàéäåííîì ôàéëå, òàê êàê fs_readdir íèæå èõ ïðèáüåò */
|
|
entrySector = fs_file.entry_sector;
|
|
entry = buf + (fs_file.entry_index % 16) * 32;
|
|
|
|
/* Â ïàïêå íå äîëæíî áûòü ôàéëîâ */
|
|
if(FS_DIRENTRY[DIR_Attr] & AM_DIR)
|
|
{
|
|
/* Ïåðåìàòûâåì ïàïêó íà íà÷àëî */
|
|
fs_file.entry_able = 0;
|
|
/* Èùåì ïåðâûé ôàéë èëè ïàïêó */
|
|
/* fs_file.entry_start_cluster ñîõðÿíÿåòñÿ (ñîäåðæèò ïåðâûé êëàñòåð ôàéëà èëè ïàïêè) */
|
|
if(fs_readdir_nocheck()) goto abort;
|
|
/* Åñëè íàøëè, òî îøèáêà */
|
|
if(fs_file.entry_able)
|
|
{
|
|
lastError = ERR_DIR_NOT_EMPTY;
|
|
goto abort;
|
|
}
|
|
}
|
|
|
|
/* Óäàëÿåì îïèñàòåëü */
|
|
if(sd_readBuf(entrySector)) goto abort;
|
|
entry[0] = 0xE5;
|
|
if(sd_writeBuf(entrySector)) goto abort;
|
|
|
|
/* Îñâîáîæäàåì öåïî÷êó êëàñòåðîâ */
|
|
fs_tmp = fs_file.entry_start_cluster;
|
|
return fs_freeChain();
|
|
abort:
|
|
return 1;
|
|
}
|
|
/**************************************************************************
|
|
* Îáíîâèòü âðåìÿ ïîñëåäíåé çàïèñè ôàéëà *
|
|
* Ôàéë äîëæåí áûòü îòêðûò *
|
|
**************************************************************************/
|
|
static uint8_t fs_update_timestamp(void)
|
|
{
|
|
#ifndef FS_DISABLE_CHECK
|
|
if(fs_file.opened != OPENED_FILE && fs_file.opened != OPENED_DIR)
|
|
{
|
|
lastError = ERR_NOT_OPENED;
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
/* Ïîëó÷àåì òåêóùåå âðåìÿ */
|
|
uint16_t fat_time = fat_pack_time();
|
|
uint16_t fat_date = fat_pack_date();
|
|
|
|
/* ×èòàåì ñåêòîð ñ çàïèñüþ */
|
|
if(sd_readBuf(fs_file.entry_sector)) return 1;
|
|
|
|
/* Ïîëó÷àåì óêàçàòåëü íà çàïèñü â êàòàëîãå */
|
|
uint8_t* entry = buf + (fs_file.entry_index % 16) * 32;
|
|
|
|
/* Îáíîâëÿåì âðåìÿ ïîñëåäíåé çàïèñè */
|
|
LD_uint16_t(entry + DIR_WrtTime) = fat_time;
|
|
LD_uint16_t(entry + DIR_WrtDate) = fat_date;
|
|
|
|
/* Åñëè âðåìÿ ñîçäàíèÿ íå óñòàíîâëåíî, óñòàíàâëèâàåì åãî */
|
|
if(LD_uint16_t(entry + DIR_CrtTime) == 0 && LD_uint16_t(entry + DIR_CrtDate) == 0)
|
|
{
|
|
LD_uint16_t(entry + DIR_CrtTime) = fat_time;
|
|
LD_uint16_t(entry + DIR_CrtDate) = fat_date;
|
|
}
|
|
|
|
/* Ñîõðàíÿåì èçìåíåíèÿ */
|
|
return sd_writeBuf(fs_file.entry_sector);
|
|
}
|
|
/**************************************************************************
|
|
* Óñòàíîâèòü êîíåö ôàéëà *
|
|
**************************************************************************/
|
|
|
|
uint8_t fs_write_eof()
|
|
{
|
|
/* Ïðîâåðêà îøèáîê ïðîãðàììèñòà */
|
|
#ifndef FS_DISABLE_CHECK
|
|
if(fs_file.opened != OPENED_FILE)
|
|
{
|
|
lastError = ERR_NOT_OPENED;
|
|
goto abort;
|
|
}
|
|
#endif
|
|
|
|
/* Êîððåêòèðóåì ëèáî FAT, ëèáî îïèñàòåëü ôàéëà. */
|
|
if(fs_file.ptr == 0)
|
|
{
|
|
/* Óäàëåì âñå êëàñòåðû ôàéëà */
|
|
fs_tmp = fs_file.entry_start_cluster;
|
|
fs_file.entry_start_cluster = 0;
|
|
}
|
|
else
|
|
{
|
|
/* Ýòîò êëàñòåð ôàéëà ïîñëåäíèé. */
|
|
fs_tmp = LAST_CLUSTER;
|
|
if(fs_setNextCluster(fs_file.cluster)) goto abort; /* fs_tmp áóäåò ñîäåðæàòü ñëåäóþùèé êëàñòåð, òàê êàê çàïèñûâàåòñÿ LAST_CLUSTER */
|
|
}
|
|
|
|
/* Óäàëåì âñå êëàñòåðû ôàéëà ïîñëå ýòîãî. (îíè ñîäåðæàòñÿ â fs_tmp); */
|
|
if(fs_freeChain()) goto abort;
|
|
|
|
/* Ñîõðàíÿåì äëíó è ïåðâûé êëàñòåð */
|
|
fs_file.size = fs_file.ptr;
|
|
fs_file.changed = 1;
|
|
if(!fs_saveFileLength()) return 0;
|
|
|
|
abort:
|
|
#ifndef FS_DISABLE_CHECK
|
|
fs_file.opened = OPENED_NONE;
|
|
#endif
|
|
return 1;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Çàïèñàòü â ôàéë *
|
|
**************************************************************************/
|
|
|
|
uint8_t fs_write(uint8_t* ptr, uint16_t len)
|
|
{
|
|
/* Ïðîâåðêà íà îøèáêè ïðîèñõîäèò â âûçûâàåìûõ ôóíêöèÿõ */
|
|
|
|
/* Êîíåö ôàéëà */
|
|
if(len == 0) return fs_write_eof();
|
|
|
|
fs_wtotal = len;
|
|
do
|
|
{
|
|
if(fs_write_start()) goto abort;
|
|
memcpy(fs_file_wbuf, ptr, fs_file_wlen);
|
|
ptr += fs_file_wlen;
|
|
if(fs_write_end()) goto abort;
|
|
}
|
|
while(fs_wtotal);
|
|
|
|
return 0;
|
|
abort:
|
|
return 1;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Ïåðåêëþ÷èòü ôàéëû *
|
|
**************************************************************************/
|
|
|
|
#ifndef FS_DISABLE_SWAP
|
|
void fs_swap()
|
|
{
|
|
/* Ýòî çàíèìàåò ìåíüøå ÏÇÓ, ÷åì òðè ôóíêöèè memcpy */
|
|
uint8_t t, *a = (uint8_t*)&fs_file, *b = (uint8_t*)&fs_secondFile, n = sizeof(File);
|
|
do
|
|
{
|
|
t=*a, *a=*b, *b=t;
|
|
++a;
|
|
++b;
|
|
}
|
|
while(--n);
|
|
}
|
|
#endif
|
|
|
|
/**************************************************************************
|
|
* Ðàñ÷åò ñâîáîäíîãî ìåñòà *
|
|
* *
|
|
* Ðåçóëüòàò â ïåðåìåííîé fs_tmp â ìåãàáàéòàõ *
|
|
* Ôóíêöèÿ çàêðûâàåò ôàéë *
|
|
**************************************************************************/
|
|
|
|
#ifndef FS_DISABLE_GETFREESPACE
|
|
uint8_t fs_getfree()
|
|
{
|
|
/* Ìû èñïîðòèì ïåðåìåííóþ fs_file.sector, ïîýòîìó çàêðûâàåì ôàéë */
|
|
fs_file.opened = OPENED_NONE;
|
|
|
|
/* Êîë-âî ñâîáîäíûõ êëàñòåðîâ áóäåò â fs_file.sector */
|
|
fs_file.sector = 0;
|
|
if(fs_allocCluster(1)) return 1;
|
|
|
|
/* Ïåðåñ÷åò â ìåãàáàéòû */
|
|
fs_tmp = ((fs_file.sector >> 10) + 1) / 2 * fs_csize;
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
/**************************************************************************
|
|
* Ðàçìåð íàêîïèòåëÿ â ìåãàáàéòàõ *
|
|
**************************************************************************/
|
|
|
|
uint8_t fs_gettotal()
|
|
{
|
|
/* Ïðîâåðêà îøèáîê ïðîãðàììèñòà */
|
|
#ifndef FS_DISABLE_CHECK
|
|
if(fs_type == FS_ERROR)
|
|
{
|
|
lastError = ERR_NO_FILESYSTEM;
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
fs_tmp = ((fs_n_fatent >> 10) + 1) / 2 * fs_csize;
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Ðàçìåð ôàéëà *
|
|
**************************************************************************/
|
|
|
|
uint8_t fs_getfilesize()
|
|
{
|
|
#ifndef FS_DISABLE_CHECK
|
|
if(fs_file.opened != OPENED_FILE)
|
|
{
|
|
lastError = ERR_NOT_OPENED;
|
|
return 1;
|
|
}
|
|
#endif
|
|
fs_tmp = fs_file.size;
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* Óêàçàòåëü ÷òåíèÿ çàïèñè ôàéëà *
|
|
**************************************************************************/
|
|
|
|
uint8_t fs_tell()
|
|
{
|
|
#ifndef FS_DISABLE_CHECK
|
|
if(fs_file.opened != OPENED_FILE)
|
|
{
|
|
lastError = ERR_NOT_OPENED;
|
|
return 1;
|
|
}
|
|
#endif
|
|
fs_tmp = fs_file.ptr;
|
|
return 0;
|
|
}
|