support for deleting files, and setting file size.

master
Ondřej Hruška 10 years ago
parent 0e42d3e1de
commit dfa70f8d32
  1. 129
      fat16.c
  2. 9
      fat16.h
  3. 42
      main.c

@ -16,7 +16,7 @@ void read_bs(const BLOCKDEV* dev, Fat16BootSector* info, const uint32_t addr);
uint32_t find_bs(const BLOCKDEV* dev); uint32_t find_bs(const BLOCKDEV* dev);
/** Get cluster's starting address */ /** Get cluster's starting address */
uint32_t clu_start(const FAT16* fat, const uint16_t cluster); uint32_t clu_addr(const FAT16* fat, const uint16_t cluster);
/** Find following cluster using FAT for jumps */ /** Find following cluster using FAT for jumps */
uint16_t next_clu(const FAT16* fat, uint16_t cluster); uint16_t next_clu(const FAT16* fat, uint16_t cluster);
@ -36,8 +36,8 @@ uint16_t alloc_cluster(const FAT16* fat);
/** Zero out entire cluster. */ /** Zero out entire cluster. */
void wipe_cluster(const FAT16* fat, const uint16_t clu); void wipe_cluster(const FAT16* fat, const uint16_t clu);
/** Write new file size (also to the disk). Does not allocate clusters. */ /** Free cluster chain, starting at given number */
void set_file_size(FAT16_FILE* file, uint32_t size); void free_cluster_chain(const FAT16* fat, uint16_t clu);
/** /**
* Check if there is already a file of given RAW name * Check if there is already a file of given RAW name
@ -45,6 +45,12 @@ void set_file_size(FAT16_FILE* file, uint32_t size);
*/ */
bool dir_contains_file_raw(FAT16_FILE* dir, char* fname); bool dir_contains_file_raw(FAT16_FILE* dir, char* fname);
/** Write a value into FAT */
void write_fat(const FAT16* fat, const uint16_t cluster, const uint16_t value);
/** Read a value from FAT */
uint16_t read_fat(const FAT16* fat, const uint16_t cluster);
// =========== INTERNAL FUNCTION IMPLEMENTATIONS ========= // =========== INTERNAL FUNCTION IMPLEMENTATIONS =========
@ -126,8 +132,22 @@ void read_bs(const BLOCKDEV* dev, Fat16BootSector* info, const uint32_t addr)
} }
void write_fat(const FAT16* fat, const uint16_t cluster, const uint16_t value)
{
fat->dev->seek(fat->fat_addr + (cluster * 2));
fat->dev->write16(value);
}
uint16_t read_fat(const FAT16* fat, const uint16_t cluster)
{
fat->dev->seek(fat->fat_addr + (cluster * 2));
return fat->dev->read16();
}
/** Get cluster starting address */ /** Get cluster starting address */
uint32_t clu_start(const FAT16* fat, const uint16_t cluster) uint32_t clu_addr(const FAT16* fat, const uint16_t cluster)
{ {
if (cluster < 2) return fat->rd_addr; if (cluster < 2) return fat->rd_addr;
return fat->data_addr + (cluster - 2) * fat->bs.bytes_per_cluster; return fat->data_addr + (cluster - 2) * fat->bs.bytes_per_cluster;
@ -136,8 +156,7 @@ uint32_t clu_start(const FAT16* fat, const uint16_t cluster)
uint16_t next_clu(const FAT16* fat, uint16_t cluster) uint16_t next_clu(const FAT16* fat, uint16_t cluster)
{ {
fat->dev->seek(fat->fat_addr + (cluster * 2)); return read_fat(fat, cluster);
return fat->dev->read16();
} }
@ -151,7 +170,7 @@ uint32_t clu_add(const FAT16* fat, uint16_t cluster, uint32_t addr)
addr -= fat->bs.bytes_per_cluster; addr -= fat->bs.bytes_per_cluster;
} }
return clu_start(fat, cluster) + addr; return clu_addr(fat, cluster) + addr;
} }
@ -163,7 +182,7 @@ uint32_t clu_add(const FAT16* fat, uint16_t cluster, uint32_t addr)
*/ */
void wipe_cluster(const FAT16* fat, const uint16_t clu) void wipe_cluster(const FAT16* fat, const uint16_t clu)
{ {
uint32_t addr = clu_start(fat, clu); uint32_t addr = clu_addr(fat, clu);
const BLOCKDEV* dev = fat->dev; const BLOCKDEV* dev = fat->dev;
@ -185,14 +204,11 @@ uint16_t alloc_cluster(const FAT16* fat)
for (i = 2; i < fat->bs.fat_size_sectors * 256; i++) for (i = 2; i < fat->bs.fat_size_sectors * 256; i++)
{ {
// read value from FAT // read value from FAT
fat->dev->seek(fat->fat_addr + (i * 2)); b = read_fat(fat, i);
b = fat->dev->read16(); if (b == 0) // unused cluster
if (b == 0)
{ {
// Write FFFF to "i", to mark end of file // Write FFFF to "i", to mark end of file
b = 0xFFFF; write_fat(fat, i, 0xFFFF);
fat->dev->seek(fat->fat_addr + (i * 2));
fat->dev->write16(b);
// Wipe the cluster // Wipe the cluster
wipe_cluster(fat, i); wipe_cluster(fat, i);
@ -212,13 +228,30 @@ bool append_cluster(const FAT16* fat, const uint16_t clu)
if (clu2 == 0xFFFF) return false; if (clu2 == 0xFFFF) return false;
// Write "i" to "clu" // Write "i" to "clu"
fat->dev->seek(fat->fat_addr + (clu * 2)); write_fat(fat, clu, clu2);
fat->dev->write16(clu2);
return true; return true;
} }
void free_cluster_chain(const FAT16* fat, uint16_t clu)
{
do {
// get address of the next cluster
const uint16_t clu2 = read_fat(fat, clu);
// mark cluster as unused
write_fat(fat, clu, 0x0000);
printf("Cluster free at %d\n", clu);
// advance
clu = clu2;
} while (clu != 0xFFFF);
}
/** /**
* Check if there is already a file of given RAW name * Check if there is already a file of given RAW name
* Raw name - name as found on disk, not "display name". * Raw name - name as found on disk, not "display name".
@ -244,18 +277,6 @@ bool dir_contains_file_raw(FAT16_FILE* dir, char* fname)
} }
/** Write new file size (also to the disk). Does not allocate clusters. */
void set_file_size(FAT16_FILE* file, uint32_t size)
{
// Find address for storing the size
const uint32_t addr = clu_add(file->fat, file->clu, file->num * 32 + 28);
file->size = size;
const BLOCKDEV* dev = file->fat->dev;
dev->seek(addr);
dev->store(&size, 4);
}
// =============== PUBLIC FUNCTION IMPLEMENTATIONS ================= // =============== PUBLIC FUNCTION IMPLEMENTATIONS =================
@ -309,7 +330,7 @@ bool fat16_fseek(FAT16_FILE* file, uint32_t addr)
addr -= file->fat->bs.bytes_per_cluster; addr -= file->fat->bs.bytes_per_cluster;
} }
file->cur_abs = clu_start(file->fat, file->cur_clu) + addr; file->cur_abs = clu_addr(file->fat, file->cur_clu) + addr;
file->cur_ofs = addr; file->cur_ofs = addr;
// Physically seek to that location // Physically seek to that location
@ -331,7 +352,7 @@ void fat16_fopen(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster,
uint32_t addr; uint32_t addr;
if (dir_cluster == 0) if (dir_cluster == 0)
{ {
addr = clu_start(fat, dir_cluster) + num * 32; // root directory, max 512 entries. addr = clu_addr(fat, dir_cluster) + num * 32; // root directory, max 512 entries.
} else } else
{ {
addr = clu_add(fat, dir_cluster, num * 32); // cluster + N (wrapping to next cluster if needed) addr = clu_add(fat, dir_cluster, num * 32); // cluster + N (wrapping to next cluster if needed)
@ -461,7 +482,7 @@ bool fat16_fread(FAT16_FILE* file, void* target, uint32_t len)
if (file->cur_ofs >= fat->bs.bytes_per_cluster) if (file->cur_ofs >= fat->bs.bytes_per_cluster)
{ {
file->cur_clu = next_clu(fat, file->cur_clu); file->cur_clu = next_clu(fat, file->cur_clu);
file->cur_abs = clu_start(fat, file->cur_clu); file->cur_abs = clu_addr(fat, file->cur_clu);
file->cur_ofs = 0; file->cur_ofs = 0;
} }
@ -519,13 +540,13 @@ bool fat16_fwrite(FAT16_FILE* file, void* src, uint32_t len)
// advance cursors to the next cluster // advance cursors to the next cluster
file->cur_clu = next_clu(fat, file->cur_clu); file->cur_clu = next_clu(fat, file->cur_clu);
file->cur_abs = clu_start(fat, file->cur_clu); file->cur_abs = clu_addr(fat, file->cur_clu);
file->cur_ofs = 0; file->cur_ofs = 0;
} }
} }
// Save new size // Save new size
set_file_size(file, pos_start + len); fat16_set_file_size(file, pos_start + len);
// Seek back to where it was before // Seek back to where it was before
fat16_fseek(file, pos_start); fat16_fseek(file, pos_start);
@ -553,7 +574,7 @@ bool fat16_fwrite(FAT16_FILE* file, void* src, uint32_t len)
if (file->cur_ofs >= fat->bs.bytes_per_cluster) if (file->cur_ofs >= fat->bs.bytes_per_cluster)
{ {
file->cur_clu = next_clu(fat, file->cur_clu); file->cur_clu = next_clu(fat, file->cur_clu);
file->cur_abs = clu_start(fat, file->cur_clu); file->cur_abs = clu_addr(fat, file->cur_clu);
file->cur_ofs = 0; file->cur_ofs = 0;
} }
@ -880,7 +901,47 @@ char* fat16_undisplay_name(const char* name, char* fixed)
} }
/** Write new file size (also to the disk). Does not allocate clusters. */
void fat16_set_file_size(FAT16_FILE* file, uint32_t size)
{
const FAT16* fat = file->fat;
const BLOCKDEV* dev = file->fat->dev;
// Find address for storing the size
const uint32_t addr = clu_add(fat, file->clu, file->num * 32 + 28);
file->size = size;
dev->seek(addr);
dev->store(&size, 4);
// Seek to the end of the file, to make sure clusters are allocated
fat16_fseek(file, size - 1);
const uint16_t next = next_clu(fat, file->cur_clu);
if (next != 0xFFFF)
{
printf("Trimming file clusters\n");
free_cluster_chain(fat, next);
// Mark that there's no further clusters
write_fat(fat, file->cur_clu, 0xFFFF);
}
}
void fat16_delete_file(FAT16_FILE* file)
{
const FAT16* fat = file->fat;
// seek to file record
fat->dev->seek(clu_add(fat, file->clu, file->num * 32));
// mark as deleted
fat->dev->write(0xE5); // "deleted" mark
// free allocated clusters
free_cluster_chain(fat, file->clu_start);
file->type = FT_DELETED;
}

@ -17,7 +17,7 @@ typedef struct {
// Absolute seek // Absolute seek
void (*seek)(const uint32_t); void (*seek)(const uint32_t);
// Relative seek // Relative seek
void (*rseek)(const uint16_t); void (*rseek)(const int16_t);
} BLOCKDEV; } BLOCKDEV;
@ -169,7 +169,14 @@ bool fat16_fwrite(FAT16_FILE* file, void* src, uint32_t len);
*/ */
bool fat16_newfile(FAT16_FILE* directory, FAT16_FILE* file, const char* name); bool fat16_newfile(FAT16_FILE* directory, FAT16_FILE* file, const char* name);
/**
* Write new file size (also to the disk).
* Allocates / frees needed clusters, does not erase them.
*/
void fat16_set_file_size(FAT16_FILE* file, uint32_t size);
/** Delete a file entry and free clusters. Does NOT descend into subdirectories. */
void fat16_delete_file(FAT16_FILE* file);
// --------- NAVIGATION ------------ // --------- NAVIGATION ------------

@ -18,7 +18,7 @@ void test_seek(const uint32_t pos)
fseek(testf, pos, SEEK_SET); fseek(testf, pos, SEEK_SET);
} }
void test_rseek(const uint16_t pos) void test_rseek(const int16_t pos)
{ {
fseek(testf, pos, SEEK_CUR); fseek(testf, pos, SEEK_CUR);
} }
@ -112,22 +112,43 @@ int main(int argc, char const *argv[])
do { do {
if (!fat16_is_file_valid(&file)) continue; if (!fat16_is_file_valid(&file)) continue;
printf("File name: %s, %c, %d B\n", printf("File name: %s, %c, %d B, @ 0x%x\n",
fat16_display_name(&file, str), fat16_display_name(&file, str),
file.type, file.size); file.type, file.size, file.clu_start);
} while (fat16_next(&file)); } while (fat16_next(&file));
fat16_open_root(&fat, &file); fat16_open_root(&fat, &file);
printf("Exists? %d\n", fat16_find_file(&file, "nuclear.war")); // bool found = fat16_find_file(&file, "NEW_FILE.DAT");
printf("Size: %d\n", file.size); //
// if (found)
// {
// fat16_delete_file(&file);
// fat16_set_file_size(&file, 16000);
// }
//printf("Exists? %d\n", fat16_find_file(&file, "nuclear.war"));
//printf("Size: %d\n", file.size);
//fat16_set_file_size(&file, 5);
//fat16_fseek(&file, 40000); //fat16_fseek(&file, 40000);
//fat16_fwrite(&file, "BANANA", 6); //fat16_fwrite(&file, "BANANA", 6);
// FAT16_FILE neu; // FAT16_FILE neu;
//fat16_newfile(&file, &neu, "NEWFILE.MP3"); // bool ok = fat16_newfile(&file, &neu, "NEWFILE3.DAT");
// if (!ok) {
// printf("FAIL.");
// return -1;
// }
//
// char c = '_';
// for (uint16_t i = 0; i < 35000; i++) {
// fat16_fwrite(&neu, &i, 2);
// fat16_fwrite(&neu, &c, 1);
// }
//fat16_fwrite(&neu, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 16); //fat16_fwrite(&neu, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 16);
@ -147,6 +168,15 @@ int main(int argc, char const *argv[])
// //
// printf("%.5s\n", boo); // printf("%.5s\n", boo);
// char ham[20000];
//
// fat16_find_file(&file, "HAMLET.TXT");
// fat16_fread(&file, ham, 20000);
// ham[19999] = 0;
// printf("%s\n", ham);
test_close(); test_close();
return 0; return 0;

Loading…
Cancel
Save