175
									
								
								src/fat12.c
									
									
									
									
									
								
							
							
						
						
									
										175
									
								
								src/fat12.c
									
									
									
									
									
								
							@@ -5,7 +5,8 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
 | 
			
		||||
struct fat12_partition {
 | 
			
		||||
struct fat12_partition
 | 
			
		||||
{
 | 
			
		||||
    struct pang_io *io;
 | 
			
		||||
 | 
			
		||||
    // Number of bytes in a sector (512)
 | 
			
		||||
@@ -31,67 +32,79 @@ struct fat12_partition {
 | 
			
		||||
    void *fat;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void fat12_write_u8(void *ptr, uint8_t val) {
 | 
			
		||||
void fat12_write_u8(void *ptr, uint8_t val)
 | 
			
		||||
{
 | 
			
		||||
    ((uint8_t *)ptr)[0] = (val >> 0) & 0xff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t fat12_read_u8(void *ptr) {
 | 
			
		||||
uint8_t fat12_read_u8(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t val = 0;
 | 
			
		||||
    val |= (((uint8_t *)ptr)[0] << 0) & 0xff;
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fat12_write_u16(void *ptr, uint16_t val) {
 | 
			
		||||
void fat12_write_u16(void *ptr, uint16_t val)
 | 
			
		||||
{
 | 
			
		||||
    ((uint8_t *)ptr)[0] = (val >> 0) & 0xff;
 | 
			
		||||
    ((uint8_t *)ptr)[1] = (val >> 8) & 0xff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint16_t fat12_read_u16(void *ptr) {
 | 
			
		||||
uint16_t fat12_read_u16(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t val = 0;
 | 
			
		||||
    val |= (((uint8_t *)ptr)[0] << 0) & 0x00ff;
 | 
			
		||||
    val |= (((uint8_t *)ptr)[1] << 8) & 0xff00;
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fat12_write_u32(void *ptr, uint32_t val) {
 | 
			
		||||
void fat12_write_u32(void *ptr, uint32_t val)
 | 
			
		||||
{
 | 
			
		||||
    ((uint8_t *)ptr)[0] = (val >> 0) & 0xff;
 | 
			
		||||
    ((uint8_t *)ptr)[1] = (val >> 8) & 0xff;
 | 
			
		||||
    ((uint8_t *)ptr)[2] = (val >> 16) & 0xff;
 | 
			
		||||
    ((uint8_t *)ptr)[3] = (val >> 24) & 0xff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t fat12_read_u32(void *ptr) {
 | 
			
		||||
uint32_t fat12_read_u32(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t val = 0;
 | 
			
		||||
    val |= (((uint8_t *)ptr)[0] << 0)  & 0x000000ff;
 | 
			
		||||
    val |= (((uint8_t *)ptr)[1] << 8)  & 0x0000ff00;
 | 
			
		||||
    val |= (((uint8_t *)ptr)[0] << 0) & 0x000000ff;
 | 
			
		||||
    val |= (((uint8_t *)ptr)[1] << 8) & 0x0000ff00;
 | 
			
		||||
    val |= (((uint8_t *)ptr)[2] << 16) & 0x00ff0000;
 | 
			
		||||
    val |= (((uint8_t *)ptr)[3] << 24) & 0xff000000;
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fat12_set_cluster(void *fat, uint32_t cluster, uint32_t value) {
 | 
			
		||||
void fat12_set_cluster(void *fat, uint32_t cluster, uint32_t value)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t offset = (cluster * 3) / 2;
 | 
			
		||||
    // fprintf(stderr, "Cluster %d -> %03x (%02x%02x -> ", cluster, value, ((uint8_t *)fat)[offset], ((uint8_t *)fat)[offset + 1]);
 | 
			
		||||
    if (cluster&1) {
 | 
			
		||||
    if (cluster & 1)
 | 
			
		||||
    {
 | 
			
		||||
        ((uint8_t *)fat)[offset] = (((uint8_t *)fat)[offset] & 0x0f) | ((value << 4) & 0xf0);
 | 
			
		||||
        ((uint8_t *)fat)[offset + 1] = value >> 4;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        ((uint8_t *)fat)[offset] = value;
 | 
			
		||||
        ((uint8_t *)fat)[offset + 1] = (((uint8_t *)fat)[offset + 1] & 0xf0) | ((value >> 8) & 0x0f);
 | 
			
		||||
    }
 | 
			
		||||
    // fprintf(stderr, "%02x%02x)\n", ((uint8_t *)fat)[offset], ((uint8_t *)fat)[offset + 1]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t fat12_get_cluster(void *fat, uint32_t cluster) {
 | 
			
		||||
uint32_t fat12_get_cluster(void *fat, uint32_t cluster)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t offset = (cluster * 3) / 2;
 | 
			
		||||
    uint32_t value = 0;
 | 
			
		||||
 | 
			
		||||
    if (cluster&1) {
 | 
			
		||||
    if (cluster & 1)
 | 
			
		||||
    {
 | 
			
		||||
        value |= (((uint8_t *)fat)[offset] >> 4) & 0x00f;
 | 
			
		||||
        value |= (((uint8_t *)fat)[offset + 1] << 4) & 0xff0;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        value |= ((uint8_t *)fat)[offset];
 | 
			
		||||
        value |= (((uint8_t *)fat)[offset + 1] << 8) & 0xf00;
 | 
			
		||||
    }
 | 
			
		||||
@@ -101,13 +114,15 @@ uint32_t fat12_get_cluster(void *fat, uint32_t cluster) {
 | 
			
		||||
    return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct fat12_partition *fat12_alloc(void) {
 | 
			
		||||
struct fat12_partition *fat12_alloc(void)
 | 
			
		||||
{
 | 
			
		||||
    struct fat12_partition *part = malloc(sizeof(struct fat12_partition));
 | 
			
		||||
    memset(part, 0, sizeof(*part));
 | 
			
		||||
    return part;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fat12_open(struct fat12_partition *part, const char *filename) {
 | 
			
		||||
int fat12_open(struct fat12_partition *part, const char *filename)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    if (!part)
 | 
			
		||||
        return -1;
 | 
			
		||||
@@ -142,7 +157,7 @@ int fat12_open(struct fat12_partition *part, const char *filename) {
 | 
			
		||||
    // Move to the root directory
 | 
			
		||||
    part->current_cluster = part->first_offset;
 | 
			
		||||
 | 
			
		||||
///
 | 
			
		||||
    ///
 | 
			
		||||
    fprintf(stderr, "part->sector_size: %d\n", part->sector_size);
 | 
			
		||||
 | 
			
		||||
    // These are in single-unit quantities
 | 
			
		||||
@@ -159,9 +174,10 @@ int fat12_open(struct fat12_partition *part, const char *filename) {
 | 
			
		||||
    fprintf(stderr, "part->cluster_count: %d\n", part->cluster_count);
 | 
			
		||||
    fprintf(stderr, "part->cluster_bytes: %d\n", part->cluster_bytes);
 | 
			
		||||
    fprintf(stderr, "data_bytes: %d\n", bytes);
 | 
			
		||||
///
 | 
			
		||||
    ///
 | 
			
		||||
 | 
			
		||||
    if (1) {
 | 
			
		||||
    if (1)
 | 
			
		||||
    {
 | 
			
		||||
        part->fat = malloc(part->fat_size * part->sector_size);
 | 
			
		||||
        pang_read(part->io, part->fat_offset * part->sector_size, part->fat, part->fat_size * part->sector_size);
 | 
			
		||||
    }
 | 
			
		||||
@@ -169,18 +185,21 @@ int fat12_open(struct fat12_partition *part, const char *filename) {
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fat12_sync(struct fat12_partition *part) {
 | 
			
		||||
void fat12_reload(struct fat12_partition *part)
 | 
			
		||||
{
 | 
			
		||||
    pang_read(part->io, part->fat_offset * part->sector_size, part->fat, part->fat_size * part->sector_size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fat12_ls_foreach_sector(struct fat12_partition *part, uint32_t sector, uint32_t count,
 | 
			
		||||
                                    void *data, int (*callback)(void *data, const struct fat12_dirent *dirent)) {
 | 
			
		||||
                                   void *data, int (*callback)(void *data, const struct fat12_dirent *dirent))
 | 
			
		||||
{
 | 
			
		||||
    struct fat12_dirent dirent;
 | 
			
		||||
    uint8_t buf[part->sector_size];
 | 
			
		||||
    uint32_t offset;
 | 
			
		||||
    pang_read(part->io, sector * part->sector_size, buf, sizeof(buf));
 | 
			
		||||
 | 
			
		||||
    for (offset = 0; offset < count; offset++) {
 | 
			
		||||
    for (offset = 0; offset < count; offset++)
 | 
			
		||||
    {
 | 
			
		||||
        struct fat_directory_entry *entry = &((struct fat_directory_entry *)buf)[offset];
 | 
			
		||||
        memset(&dirent, 0, sizeof(dirent));
 | 
			
		||||
        memcpy(dirent.filename, entry->file_name, 8);
 | 
			
		||||
@@ -194,24 +213,29 @@ static int fat12_ls_foreach_sector(struct fat12_partition *part, uint32_t sector
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fat12_ls_foreach(struct fat12_partition *part, uint32_t dir_cluster, void *data, int (*callback)(void *data, const struct fat12_dirent *dirent)) {
 | 
			
		||||
int fat12_ls_foreach(struct fat12_partition *part, uint32_t dir_cluster, void *data, int (*callback)(void *data, const struct fat12_dirent *dirent))
 | 
			
		||||
{
 | 
			
		||||
    uint32_t sector;
 | 
			
		||||
    if (dir_cluster < 2) {
 | 
			
		||||
    if (dir_cluster < 2)
 | 
			
		||||
    {
 | 
			
		||||
        sector = part->root_offset;
 | 
			
		||||
        uint32_t dir_entries;
 | 
			
		||||
        uint32_t max_entries = part->root_entries;
 | 
			
		||||
        uint32_t entries_per_sector = part->sector_size / sizeof(struct fat_directory_entry);
 | 
			
		||||
        uint32_t loop = 0;
 | 
			
		||||
        for (dir_entries = 0; dir_entries < max_entries; dir_entries += entries_per_sector) {
 | 
			
		||||
        for (dir_entries = 0; dir_entries < max_entries; dir_entries += entries_per_sector)
 | 
			
		||||
        {
 | 
			
		||||
            uint32_t entries_to_list = entries_per_sector;
 | 
			
		||||
            if (max_entries - dir_entries < entries_to_list)
 | 
			
		||||
                entries_to_list = max_entries - dir_entries;
 | 
			
		||||
            fat12_ls_foreach_sector(part, part->root_offset + loop++, entries_to_list, data, callback);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        sector = dir_cluster * part->cluster_size + part->first_offset;
 | 
			
		||||
        while (dir_cluster > 1 && dir_cluster < 0xff8) {
 | 
			
		||||
        while (dir_cluster > 1 && dir_cluster < 0xff8)
 | 
			
		||||
        {
 | 
			
		||||
            // dir_cluster = fat12_get_cluster(part->fd, dir_cluster);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -219,27 +243,32 @@ int fat12_ls_foreach(struct fat12_partition *part, uint32_t dir_cluster, void *d
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fat12_flush(struct fat12_partition *part) {
 | 
			
		||||
void fat12_flush(struct fat12_partition *part)
 | 
			
		||||
{
 | 
			
		||||
    pang_write(part->io, part->fat_offset * part->sector_size, part->fat, part->fat_size * part->sector_size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fat12_close(struct fat12_partition *part) {
 | 
			
		||||
int fat12_close(struct fat12_partition *part)
 | 
			
		||||
{
 | 
			
		||||
    if (!part)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    if (1) {
 | 
			
		||||
    if (1)
 | 
			
		||||
    {
 | 
			
		||||
        fat12_flush(part);
 | 
			
		||||
        free(part->fat);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (-1 == pang_close(&part->io)) {
 | 
			
		||||
    if (-1 == pang_close(&part->io))
 | 
			
		||||
    {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fat12_free(struct fat12_partition **part) {
 | 
			
		||||
void fat12_free(struct fat12_partition **part)
 | 
			
		||||
{
 | 
			
		||||
    if (!part)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
@@ -253,26 +282,30 @@ void fat12_free(struct fat12_partition **part) {
 | 
			
		||||
    *part = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t fat12_find_free_cluster(struct fat12_partition *part, uint32_t start) {
 | 
			
		||||
static uint32_t fat12_find_free_cluster(struct fat12_partition *part, uint32_t start)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t cluster_value;
 | 
			
		||||
    if (start < 1)
 | 
			
		||||
        start = 1;
 | 
			
		||||
    do {
 | 
			
		||||
    do
 | 
			
		||||
    {
 | 
			
		||||
        cluster_value = fat12_get_cluster(part->fat, ++start);
 | 
			
		||||
        fprintf(stderr, "Cluster %d value: %03x\n", start, cluster_value);
 | 
			
		||||
    } while(cluster_value != 0);
 | 
			
		||||
    } while (cluster_value != 0);
 | 
			
		||||
    fprintf(stderr, "Found free cluster %d\n", start);
 | 
			
		||||
    return start;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fat12_add_dirent_sector(struct fat12_partition *part, uint32_t sector, uint32_t count, const struct fat_directory_entry *new_dirent) {
 | 
			
		||||
static int fat12_add_dirent_sector(struct fat12_partition *part, uint32_t sector, uint32_t count, const struct fat_directory_entry *new_dirent)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    struct fat12_dirent dirent;
 | 
			
		||||
    uint8_t buf[part->sector_size];
 | 
			
		||||
    uint32_t offset;
 | 
			
		||||
    pang_read(part->io, sector * part->sector_size, buf, sizeof(buf));
 | 
			
		||||
 | 
			
		||||
    for (offset = 0; offset < count; offset++) {
 | 
			
		||||
    for (offset = 0; offset < count; offset++)
 | 
			
		||||
    {
 | 
			
		||||
        struct fat_directory_entry *entry = &((struct fat_directory_entry *)buf)[offset];
 | 
			
		||||
        memset(&dirent, 0, sizeof(dirent));
 | 
			
		||||
        memcpy(dirent.filename, entry->file_name, 8);
 | 
			
		||||
@@ -280,7 +313,8 @@ static int fat12_add_dirent_sector(struct fat12_partition *part, uint32_t sector
 | 
			
		||||
        dirent.first_cluster = fat12_read_u16(&entry->first_cluster);
 | 
			
		||||
        dirent.size = fat12_read_u32(&entry->file_size);
 | 
			
		||||
 | 
			
		||||
        if ((entry->file_name[0] == 0xe5) || (entry->file_name[0] == 0x00)) {
 | 
			
		||||
        if ((entry->file_name[0] == 0xe5) || (entry->file_name[0] == 0x00))
 | 
			
		||||
        {
 | 
			
		||||
            ((struct fat_directory_entry *)buf)[offset] = *new_dirent;
 | 
			
		||||
            pang_write(part->io, sector * part->sector_size, buf, sizeof(buf));
 | 
			
		||||
            return 0;
 | 
			
		||||
@@ -289,37 +323,43 @@ static int fat12_add_dirent_sector(struct fat12_partition *part, uint32_t sector
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fat12_dir_update_or_add_dirent(struct fat12_partition *part, uint32_t dir_cluster, const struct fat_directory_entry *dirent) {
 | 
			
		||||
    if (1) {
 | 
			
		||||
static int fat12_dir_update_or_add_dirent(struct fat12_partition *part, uint32_t dir_cluster, const struct fat_directory_entry *dirent)
 | 
			
		||||
{
 | 
			
		||||
    if (1)
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t sector = part->root_offset;
 | 
			
		||||
        uint32_t dir_entries;
 | 
			
		||||
        uint32_t max_entries = part->root_entries;
 | 
			
		||||
        uint32_t entries_per_sector = part->sector_size / sizeof(struct fat_directory_entry);
 | 
			
		||||
        uint32_t loop = 0;
 | 
			
		||||
        for (dir_entries = 0; dir_entries < max_entries; dir_entries += entries_per_sector) {
 | 
			
		||||
        for (dir_entries = 0; dir_entries < max_entries; dir_entries += entries_per_sector)
 | 
			
		||||
        {
 | 
			
		||||
            uint32_t entries_to_list = entries_per_sector;
 | 
			
		||||
            if (max_entries - dir_entries < entries_to_list)
 | 
			
		||||
                entries_to_list = max_entries - dir_entries;
 | 
			
		||||
            // TODO: See if a filename already exists
 | 
			
		||||
            if (! fat12_add_dirent_sector(part, part->root_offset + loop++, entries_to_list, dirent))
 | 
			
		||||
            if (!fat12_add_dirent_sector(part, part->root_offset + loop++, entries_to_list, dirent))
 | 
			
		||||
                return 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void fat_dirent_set_name(struct fat_directory_entry *dirent, const char *filename) {
 | 
			
		||||
static void fat_dirent_set_name(struct fat_directory_entry *dirent, const char *filename)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    int ext_split = -1;
 | 
			
		||||
    int name_off = 0;
 | 
			
		||||
    int dirent_off = 0;
 | 
			
		||||
 | 
			
		||||
    for (name_off = 0; filename[name_off] != '\0'; name_off++) {
 | 
			
		||||
    for (name_off = 0; filename[name_off] != '\0'; name_off++)
 | 
			
		||||
    {
 | 
			
		||||
        if (filename[name_off] == '.')
 | 
			
		||||
            ext_split = name_off + 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (dirent_off = 0; dirent_off < 8; dirent_off++) {
 | 
			
		||||
    for (dirent_off = 0; dirent_off < 8; dirent_off++)
 | 
			
		||||
    {
 | 
			
		||||
        if (dirent_off < (ext_split - 1))
 | 
			
		||||
            dirent->file_name[dirent_off] = toupper(filename[dirent_off]);
 | 
			
		||||
        else
 | 
			
		||||
@@ -327,7 +367,8 @@ static void fat_dirent_set_name(struct fat_directory_entry *dirent, const char *
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    name_off = ext_split + 1;
 | 
			
		||||
    for (dirent_off = 0; dirent_off < 3; dirent_off++) {
 | 
			
		||||
    for (dirent_off = 0; dirent_off < 3; dirent_off++)
 | 
			
		||||
    {
 | 
			
		||||
        if ((ext_split >= 0) && (filename[ext_split]))
 | 
			
		||||
            dirent->extension[dirent_off] = toupper(filename[ext_split++]);
 | 
			
		||||
        else
 | 
			
		||||
@@ -335,7 +376,8 @@ static void fat_dirent_set_name(struct fat_directory_entry *dirent, const char *
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fat12_write_file(struct fat12_partition *part, const char *filename, const void *bfr, uint32_t size) {
 | 
			
		||||
int fat12_write_file(struct fat12_partition *part, const char *filename, const void *bfr, uint32_t size)
 | 
			
		||||
{
 | 
			
		||||
    // TODO: directory support
 | 
			
		||||
    uint32_t first_cluster;
 | 
			
		||||
    uint32_t cluster;
 | 
			
		||||
@@ -351,20 +393,22 @@ int fat12_write_file(struct fat12_partition *part, const char *filename, const v
 | 
			
		||||
    fat12_write_u32(dirent.file_size, size);
 | 
			
		||||
    fat12_dir_update_or_add_dirent(part, 0, &dirent);
 | 
			
		||||
 | 
			
		||||
    while (size > 0) {
 | 
			
		||||
    while (size > 0)
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t bytes_to_write = size;
 | 
			
		||||
        if (bytes_to_write > part->cluster_size * part->sector_size)
 | 
			
		||||
            bytes_to_write = part->cluster_size * part->sector_size;
 | 
			
		||||
 | 
			
		||||
        pang_write(part->io,
 | 
			
		||||
            ((cluster - 2) * part->cluster_size + part->first_offset) * part->sector_size,
 | 
			
		||||
            bfr,
 | 
			
		||||
            bytes_to_write);
 | 
			
		||||
                   ((cluster - 2) * part->cluster_size + part->first_offset) * part->sector_size,
 | 
			
		||||
                   bfr,
 | 
			
		||||
                   bytes_to_write);
 | 
			
		||||
        size -= bytes_to_write;
 | 
			
		||||
        fprintf(stderr, "%s: %d bytes left\n", filename, size);
 | 
			
		||||
        if (!size)
 | 
			
		||||
            fat12_set_cluster(part->fat, cluster, 0xff8);
 | 
			
		||||
        else {
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            uint32_t next_cluster = fat12_find_free_cluster(part, cluster);
 | 
			
		||||
            fat12_set_cluster(part->fat, cluster, next_cluster);
 | 
			
		||||
            cluster = next_cluster;
 | 
			
		||||
@@ -372,25 +416,30 @@ int fat12_write_file(struct fat12_partition *part, const char *filename, const v
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t find_root_cluster_for_file(struct fat12_partition *part, const char *filename) {
 | 
			
		||||
static uint32_t find_root_cluster_for_file(struct fat12_partition *part, const char *filename)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t file_cluster = 0;
 | 
			
		||||
 | 
			
		||||
    // Find the dirent of the file
 | 
			
		||||
    uint32_t dirent_cluster = 0;
 | 
			
		||||
 | 
			
		||||
    // TODO: Support directories other than the root directory
 | 
			
		||||
    if (1) {
 | 
			
		||||
    if (1)
 | 
			
		||||
    {
 | 
			
		||||
        struct fat_directory_entry dirent;
 | 
			
		||||
        uint32_t entries_per_sector = part->sector_size / sizeof(struct fat_directory_entry);
 | 
			
		||||
        fat_dirent_set_name(&dirent, filename);
 | 
			
		||||
        int i = 0;
 | 
			
		||||
        int check_entry_i;
 | 
			
		||||
        int sector = part->root_offset - 1; // -1 because we use it to update the entry below.
 | 
			
		||||
        while (i < part->root_entries) {
 | 
			
		||||
        while (i < part->root_entries)
 | 
			
		||||
        {
 | 
			
		||||
            struct fat_directory_entry entries[entries_per_sector];
 | 
			
		||||
            pang_read(part->io, ++sector * part->sector_size, entries, sizeof(entries));
 | 
			
		||||
            for (check_entry_i = 0; (check_entry_i < entries_per_sector) && (i < part->root_entries); check_entry_i++, i++) {
 | 
			
		||||
                if (!memcmp(&entries[check_entry_i], &dirent, 11)) {
 | 
			
		||||
            for (check_entry_i = 0; (check_entry_i < entries_per_sector) && (i < part->root_entries); check_entry_i++, i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (!memcmp(&entries[check_entry_i], &dirent, 11))
 | 
			
		||||
                {
 | 
			
		||||
                    entries[check_entry_i].file_name[0] = 0xe5;
 | 
			
		||||
                    pang_write(part->io, sector * part->sector_size, entries, sizeof(entries));
 | 
			
		||||
                    return fat12_read_u16(entries[check_entry_i].first_cluster);
 | 
			
		||||
@@ -401,23 +450,25 @@ static uint32_t find_root_cluster_for_file(struct fat12_partition *part, const c
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fat12_delete_file(struct fat12_partition *part, const char *filename) {
 | 
			
		||||
int fat12_delete_file(struct fat12_partition *part, const char *filename)
 | 
			
		||||
{
 | 
			
		||||
    // Find the root cluster of the file
 | 
			
		||||
    uint32_t root_cluster = find_root_cluster_for_file(part, filename);
 | 
			
		||||
 | 
			
		||||
    // A return value of 0 (or 1) is not a valid cluster, so there's
 | 
			
		||||
    // nothing to do.
 | 
			
		||||
    if (root_cluster < 2) {
 | 
			
		||||
    if (root_cluster < 2)
 | 
			
		||||
    {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Change the first character of the dirent to 0xe5 to indicate
 | 
			
		||||
    // it's been deleted.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Set all clusters in the FAT to 0x000, indicating they're free.
 | 
			
		||||
    uint32_t this_cluster = root_cluster;
 | 
			
		||||
    do {
 | 
			
		||||
    do
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t next_cluster = fat12_get_cluster(part->fat, this_cluster);
 | 
			
		||||
        // fprintf(stderr, "This cluster: %03d  Next cluster: %03d  Next-next cluster: %03d\n", this_cluster, next_cluster, next_next_cluster);
 | 
			
		||||
        fat12_set_cluster(part->fat, this_cluster, 0);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								src/io.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								src/io.c
									
									
									
									
									
								
							@@ -5,19 +5,23 @@
 | 
			
		||||
 | 
			
		||||
#ifdef unix
 | 
			
		||||
 | 
			
		||||
struct pang_io {
 | 
			
		||||
struct pang_io
 | 
			
		||||
{
 | 
			
		||||
    int fd;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ssize_t pang_write(struct pang_io *io, off_t offset, const void *buf, size_t count) {
 | 
			
		||||
ssize_t pang_write(struct pang_io *io, off_t offset, const void *buf, size_t count)
 | 
			
		||||
{
 | 
			
		||||
    return pwrite(io->fd, buf, count, offset);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ssize_t pang_read(struct pang_io *io, off_t offset, void *buf, size_t count) {
 | 
			
		||||
ssize_t pang_read(struct pang_io *io, off_t offset, void *buf, size_t count)
 | 
			
		||||
{
 | 
			
		||||
    return pread(io->fd, buf, count, offset);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct pang_io *pang_open(const char *pathname) {
 | 
			
		||||
struct pang_io *pang_open(const char *pathname)
 | 
			
		||||
{
 | 
			
		||||
    int fd = open(pathname, O_RDWR | O_CREAT, 0777);
 | 
			
		||||
    if (-1 == fd)
 | 
			
		||||
        return NULL;
 | 
			
		||||
@@ -26,7 +30,8 @@ struct pang_io *pang_open(const char *pathname) {
 | 
			
		||||
    return io;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pang_close(struct pang_io **io) {
 | 
			
		||||
int pang_close(struct pang_io **io)
 | 
			
		||||
{
 | 
			
		||||
    if (!io)
 | 
			
		||||
        return -1;
 | 
			
		||||
    if (!*io)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user