Код:
/*-----------------------------------------------------------------------*/
/* Format name for directory entry */
/*-----------------------------------------------------------------------*/
// Стандартная функция create_name изменяет второй аргумент, а это
// нам не надо.
static FRESULT create_name_2(DIR* dj, const char* name) {
return create_name(dj, &name);
}
/*-----------------------------------------------------------------------*/
/* Save sector */
/*-----------------------------------------------------------------------*/
// Сохранить сектор на диск
static DRESULT disk_write(const BYTE* buf, DWORD sector) {
DRESULT r;
// Начало операции записи
if(r = disk_writep(0, sector)) return r;
// Запись данных
if(r = disk_writep(buf, 512)) return r;
// Окончание операции записи
return disk_writep(0, 0);
}
/*-----------------------------------------------------------------------*/
/* Reset free space counters on start */
/*-----------------------------------------------------------------------*/
// Вызов этой функции надо добавить в конец pf_mount
//
// if(fs->fs_type==FS_FAT32 && LD_WORD(buf+BPB_RsvdSecCnt-13)>0)
// if(resetFreeSpace(bsect+1, buf512))
// return FR_DISK_ERR;
static DRESULT resetFreeSpaceFat32(unsigned long bootSectorPlus1, BYTE* buf512) {
DRESULT r;
if(r = disk_readp(buf512, bootSectorPlus1, 0, 512)) return r;
if(*(unsigned long*)buf512 != 0x41615252) return RES_OK;
if(*(unsigned long*)(buf512+0x1E4) != 0x61417272) return RES_OK;
if(*(unsigned long*)(buf512+0x1FC) != 0xAA550000) return RES_OK;
*(unsigned long*)(buf512+0x1E8) = 0xFFFFFFFF;
*(unsigned long*)(buf512+0x1EC) = 0xFFFFFFFF;
return disk_write(buf512, bootSectorPlus1);
}
/*-----------------------------------------------------------------------*/
/* Save fat sector in all FAT tables */
/*-----------------------------------------------------------------------*/
static char saveFatSector(unsigned long sector, const BYTE* buf) {
if(sector == -1) return 0;
if(FatFs->fatbase2) if(disk_write(buf, FatFs->fatbase2 + sector)) return 1;
return disk_write(buf, FatFs->fatbase + sector);
}
/*-----------------------------------------------------------------------*/
/* Alloc cluster */
/*-----------------------------------------------------------------------*/
static FRESULT allocClusterFat32(unsigned long* cluster, BYTE* buf) {
unsigned char i;
unsigned long s, sectorsInFat, *a;
// Кол-во секторов в таблице FAT
sectorsInFat = (FatFs->n_fatent + 127) / 128;
// В первом секторе первых 2 числа пропускаем
i = 2, a = ((unsigned long*)buf)+2;
// Последовательно перебираем сектора
for(s = 0; s < sectorsInFat; s++) {
if(disk_readp(buf, FatFs->fatbase + s, 0, 512)) return FR_DISK_ERR;
// Среди 128 чисел в секторе ищем 0
for(; i < 128; i++, a++) {
if(*a == 0) {
// Мы могли вылететь за пределы таблицы FAT
*cluster = i + s * 128;
if(*cluster >= FatFs->n_fatent) return FR_NO_FREE_SPACE;
// Помечаем кластер как последний
*a = 0x0FFFFFFF;
// Сохраняем изменения
if(saveFatSector(s, buf)) return FR_DISK_ERR;
// Ок
return FR_OK;
}
}
// Для цикла выше.
i = 0, a = (unsigned long*)buf;
}
// Свобожных кластеров нет.
return FR_NO_FREE_SPACE;
}
/*-----------------------------------------------------------------------*/
/* Add cluster in chain */
/*-----------------------------------------------------------------------*/
static char setNextClusterFat32(unsigned long cluster, unsigned long nextCluster, BYTE* buf512) {
unsigned long sector;
sector = cluster/128;
if(disk_readp(buf512, FatFs->fatbase + sector, 0, 512)) return 1;
((unsigned long*)buf512)[cluster % 128] = nextCluster;
return saveFatSector(sector, buf512);
}
/*-----------------------------------------------------------------------*/
/* Alloc directoy entry */
/*-----------------------------------------------------------------------*/
static FRESULT allocEntryFat32(DIR* dj, const char* name, BYTE* buf512, BYTE** outEntry) {
FRESULT res;
BYTE c, *a;
unsigned char i;
DWORD cluster;
// Форматируем имя
if(res = create_name_2(dj, name)) return res;
// Ищем это имя в папке
res = dir_find(dj, buf512);
if(res != FR_NO_FILE) {
if(res == FR_OK) return FR_FILE_EXISTS;
return res;
}
// Перематываем папку в начало
if(res = dir_rewind(dj)) return res;
// Ищем в папке пустой описатель
res = FR_NO_FILE;
while (dj->sect) {
if (disk_readp(buf512, dj->sect, 0, 512)) return FR_DISK_ERR;
for(i=0, a=buf512; i<16; i++, a+=32) {
if((a[DIR_Attr] & AM_VOL) == 0 && (*a == 0 || *a == 0xE5)) {
// Если мы добавляем в последний элемент, то надо надо создать последний элемент
if(*a==0) {
if(i<15) {
memset(a+32, 0, 512-32-i*32);
} else
if(dj->index/16+1 < FatFs->csize) {
// Это последний элемент в секторе, но не в кластере
memset(buf512, 0, 512);
if(disk_write(buf512, dj->sect+1)) return FR_DISK_ERR;
// Восстанавливаем буфер
if(disk_readp(buf512, dj->sect, 0, 512)) return FR_DISK_ERR;
}
}
// Инициализируем найденный элемент
memset(a, 0, 32);
goto break2;
}
}
// Следующий сектор
dj->index += 15;
if(res = dir_next(dj)) {
if(res != FR_NO_FILE) return res;
// В папке может быть не более 65535 файлов
if((unsigned short)dj->index==65535)
return FR_DIR_FULL;
// Добавить еще один кластер к папке.
if(res = allocClusterFat32(&cluster, buf512)) return res;
if(setNextClusterFat32(dj->clust, cluster, buf512)) return FR_DISK_ERR;
dj->clust = cluster;
dj->sect = clust2sect(cluster);
// Инициализируем сектор
memset(buf512, 0, 512);
a = buf512;
break;
}
}
break2:
// Запоняем имя
dj->fn = a;
create_name_2(dj, name);
// Возвращаем указатель на найденный элемент
if(outEntry) *outEntry = a;
// Ок
return FR_OK;
}
/*-----------------------------------------------------------------------*/
/* Free cluster chain */
/*-----------------------------------------------------------------------*/
static FRESULT freeChain(unsigned long cluster, BYTE* buf512) {
unsigned long s, s1, *a;
s1 = -1;
while(cluster >= 2 && cluster < FatFs->n_fatent) {
s = cluster/128;
if(s!=s1) {
if(saveFatSector(s1, buf512)) return FR_DISK_ERR;
s1 = s;
if(disk_readp(buf512, FatFs->fatbase+s, 0, 512)) return FR_DISK_ERR;
}
a = (unsigned long*)(buf512 + (cluster%128)*4);
cluster = *a;
*a = 0;
}
if(saveFatSector(s1, buf512)) return FR_DISK_ERR;
return FR_OK;
}
/*-----------------------------------------------------------------------*/
/* Is empty folder */
/*-----------------------------------------------------------------------*/
static FRESULT isEmptyFolder(DWORD cluster, BYTE* buf512) {
DIR dir;
FRESULT res;
BYTE* a;
unsigned char i;
// Для последовательного четния всех секторов папки
dir.sclust = cluster;
if(res = dir_rewind(&dir)) return res;
// Первые два элемента пропускаем (должны быть .. и .)
i = 2, a = buf512 + 64;
// Обрабатываем все сектора
while(dir.sect) {
if(disk_readp(buf512, dir.sect, 0, 512)) return FR_DISK_ERR;
// В секторе 16 описателей
for(; i < 16; i++, a += 32) {
// Это был последний описатель
if(*a == 0) return FR_OK;
// Найден файл или папка, ошибка
if((a[DIR_Attr] & AM_VOL) == 0 && *a != 0xE5) return FR_DIR_NOT_EMPTY;
}
// Следующий сектор
dir.index += 15;
if(res = dir_next(&dir)) {
// Это был последний сектор, всё ок.
if(res == FR_NO_FILE) return FR_OK;
// Ошибка
return res;
}
// Для цикла выше
i = 0, a = buf512;
}
}
/*-----------------------------------------------------------------------*/
/* Convert bytyes to clusters */
/*-----------------------------------------------------------------------*/
static unsigned long bytesToClusters(unsigned long sizeInBytes) {
unsigned long bytesInCluster;
bytesInCluster = FatFs->csize*512;
return (sizeInBytes + bytesInCluster - 1) / bytesInCluster;
}