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);
/** 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 */
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. */
void wipe_cluster(const FAT16* fat, const uint16_t clu);
/** Write new file size (also to the disk). Does not allocate clusters. */
void set_file_size(FAT16_FILE* file, uint32_t size);
/** Free cluster chain, starting at given number */
void free_cluster_chain(const FAT16* fat, uint16_t clu);
/**
* 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);
/** 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 =========
@ -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 */
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;
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)
{
fat->dev->seek(fat->fat_addr + (cluster * 2));
return fat->dev->read16();
return read_fat(fat, cluster);
}
@ -151,7 +170,7 @@ uint32_t clu_add(const FAT16* fat, uint16_t cluster, uint32_t addr)
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)
{
uint32_t addr = clu_start(fat, clu);
uint32_t addr = clu_addr(fat, clu);
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++)
{
// read value from FAT
fat->dev->seek(fat->fat_addr + (i * 2));
b = fat->dev->read16();
if (b == 0)
b = read_fat(fat, i);
if (b == 0) // unused cluster
{
// Write FFFF to "i", to mark end of file
b = 0xFFFF;
fat->dev->seek(fat->fat_addr + (i * 2));
fat->dev->write16(b);
write_fat(fat, i, 0xFFFF);
// Wipe the cluster
wipe_cluster(fat, i);
@ -212,13 +228,30 @@ bool append_cluster(const FAT16* fat, const uint16_t clu)
if (clu2 == 0xFFFF) return false;
// Write "i" to "clu"
fat->dev->seek(fat->fat_addr + (clu * 2));
fat->dev->write16(clu2);
write_fat(fat, clu, clu2);
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
* 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 =================
@ -309,7 +330,7 @@ bool fat16_fseek(FAT16_FILE* file, uint32_t addr)
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;
// 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;
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
{
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)
{
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;
}
@ -519,13 +540,13 @@ bool fat16_fwrite(FAT16_FILE* file, void* src, uint32_t len)
// advance cursors to the next cluster
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;
}
}
// 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
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)
{
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;
}
@ -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
void (*seek)(const uint32_t);
// Relative seek
void (*rseek)(const uint16_t);
void (*rseek)(const int16_t);
} 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);
/**
* 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 ------------

@ -18,7 +18,7 @@ void test_seek(const uint32_t pos)
fseek(testf, pos, SEEK_SET);
}
void test_rseek(const uint16_t pos)
void test_rseek(const int16_t pos)
{
fseek(testf, pos, SEEK_CUR);
}
@ -112,22 +112,43 @@ int main(int argc, char const *argv[])
do {
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),
file.type, file.size);
file.type, file.size, file.clu_start);
} while (fat16_next(&file));
fat16_open_root(&fat, &file);
printf("Exists? %d\n", fat16_find_file(&file, "nuclear.war"));
printf("Size: %d\n", file.size);
// bool found = fat16_find_file(&file, "NEW_FILE.DAT");
//
// 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_fwrite(&file, "BANANA", 6);
// 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);
@ -147,6 +168,15 @@ int main(int argc, char const *argv[])
//
// 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();
return 0;

Loading…
Cancel
Save