#include "fat12.h" #include "fat12-internals.h" #include "io.h" #include struct fat12_partition { int fd; // Number of bytes in a sector (512) uint32_t sector_size; uint8_t sector_buffer[512]; // These units are "sectors" uint32_t fat_offset; uint32_t fat_size; uint32_t root_offset; uint32_t first_offset; uint32_t cluster_size; // These are in single-unit quantities uint32_t root_entries; uint32_t cluster_count; uint32_t cluster_bytes; uint32_t sector_count; // Used for traversing directories uint32_t current_cluster; }; void fat12_write_u8(void *ptr, uint8_t val) { ((uint8_t *)ptr)[0] = (val >> 0) & 0xff; } 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) { ((uint8_t *)ptr)[0] = (val >> 0) & 0xff; ((uint8_t *)ptr)[1] = (val >> 8) & 0xff; } 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_set_cluster(void *fat, uint32_t cluster, uint32_t value) { uint32_t offset = (cluster * 3) / 2; if (cluster&1) { ((uint8_t *)fat)[offset] = (((uint8_t *)fat)[offset] & 0x0f) | ((value << 4) & 0xf0); ((uint8_t *)fat)[offset + 1] = value >> 4; } else { ((uint8_t *)fat)[offset] = value; ((uint8_t *)fat)[offset + 1] = (((uint8_t *)fat)[offset] & 0xf0) | ((value >> 8) & 0x0f); } } uint32_t fat12_get_cluster(void *fat, uint32_t cluster) { uint32_t offset = (cluster * 3) / 2; uint32_t value = 0; if (cluster&1) { value |= (((uint8_t *)fat)[offset] >> 4) & 0x00f; value |= (((uint8_t *)fat)[offset + 1] << 4) & 0xff0; } else { value |= ((uint8_t *)fat)[offset]; value |= (((uint8_t *)fat)[offset + 1] << 8) & 0xf00; } return value; } 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) { if (!part) return -1; if (part->fd > 0) return -1; part->fd = pang_open(filename, O_RDWR); if (part->fd == -1) { part->fd = 0; return -1; } if (pang_read(part->fd, part->sector_buffer, sizeof(part->sector_buffer)) != sizeof(part->sector_buffer)) { return -1; } part->sector_size = fat12_read_u16(part->sector_buffer + 0x0b); // These are in single-unit quantities part->root_entries = fat12_read_u16(part->sector_buffer + 0x11); part->sector_count = fat12_read_u16(part->sector_buffer + 0x13); // These units are "sectors" part->fat_offset = fat12_read_u16(part->sector_buffer + 0x0e); part->fat_size = fat12_read_u16(part->sector_buffer + 0x16); part->root_offset = part->fat_offset + part->fat_size; part->first_offset = part->root_offset + (part->root_entries * sizeof(struct fat_directory_entry)) / part->sector_size; part->cluster_size = fat12_read_u8(part->sector_buffer + 0x0d); uint32_t bytes = (part->sector_count - part->first_offset) * part->sector_size; part->cluster_count = bytes / part->sector_size / part->cluster_size; part->cluster_bytes = (part->cluster_count * 3) / 2; /// fprintf(stderr, "part->sector_size: %d\n", part->sector_size); // These are in single-unit quantities fprintf(stderr, "part->root_entries: %d\n", part->root_entries); fprintf(stderr, "part->sector_count: %d\n", part->sector_count); // These units are "sectors" fprintf(stderr, "part->fat_offset: %d\n", part->fat_offset); fprintf(stderr, "part->fat_size: %d\n", part->fat_size); fprintf(stderr, "part->root_offset: %d\n", part->root_offset); fprintf(stderr, "part->first_offset: %d\n", part->first_offset); fprintf(stderr, "part->cluster_size: %d\n", part->cluster_size); 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); /// return 0; } int fat12_close(struct fat12_partition *part) { if (!part) return -1; if (part->fd <= 0) return -1; if (-1 == pang_close(part->fd)) { return -1; } part->fd = 0; return 0; } void fat12_free(struct fat12_partition **part) { if (!part) return; if (!*part) return; free(*part); *part = NULL; }