diff --git a/include/fat12.h b/include/fat12.h index 852d559..27506e6 100644 --- a/include/fat12.h +++ b/include/fat12.h @@ -5,7 +5,8 @@ struct pang_io; struct fat12_partition; -struct fat12_dirent { +struct fat12_dirent +{ char filename[256]; uint32_t first_cluster; uint32_t size; @@ -14,15 +15,13 @@ struct fat12_dirent { uint32_t mtime; }; -struct fat12_partition * fat12_alloc(void); +struct fat12_partition *fat12_alloc(void); int fat12_open(struct fat12_partition *part, const char *filename); int fat12_close(struct fat12_partition *part); void fat12_free(struct fat12_partition **part); -void fat12_sync(struct fat12_partition *part); +void fat12_reload(struct fat12_partition *part); void fat12_flush(struct fat12_partition *part); -int fat12_ls_foreach(struct fat12_partition *part, uint32_t dir_cluster, void *data, int (*callback)(void *data, const struct fat12_dirent *dirent)); - void fat12_write_u8(void *ptr, uint8_t val); uint8_t fat12_read_u8(void *ptr); void fat12_write_u16(void *ptr, uint16_t val); @@ -32,6 +31,8 @@ uint32_t fat12_read_u32(void *ptr); void fat12_set_cluster(void *fat, uint32_t cluster, uint32_t value); uint32_t fat12_get_cluster(void *fat, uint32_t cluster); +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_write_file(struct fat12_partition *part, const char *filename, const void *bfr, uint32_t size); int fat12_delete_file(struct fat12_partition *part, const char *filename); diff --git a/src/fat12.c b/src/fat12.c index 0c4ac6e..0905ef1 100644 --- a/src/fat12.c +++ b/src/fat12.c @@ -5,7 +5,8 @@ #include #include -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); diff --git a/src/io.c b/src/io.c index 6b3f58a..f431aa4 100644 --- a/src/io.c +++ b/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) diff --git a/tests/fragment-file.c b/tests/fragment-file.c index 6cc879a..edb5857 100644 --- a/tests/fragment-file.c +++ b/tests/fragment-file.c @@ -9,15 +9,18 @@ #include "fat12.h" #include "io.h" -static int make_image(const char *name, uint32_t size) { +static int make_image(const char *name, uint32_t size) +{ struct pang_io *io = pang_open(name); - if (!io) { + if (!io) + { fprintf(stderr, "couldn't open %s: %s\n", name, strerror(errno)); return 1; } - if (-1 == fat12_mkfs(io, size)) { + if (-1 == fat12_mkfs(io, size)) + { fprintf(stderr, "couldn't make fat12 on %s: %s\n", name, strerror(errno)); pang_close(&io); return 1; @@ -26,38 +29,46 @@ static int make_image(const char *name, uint32_t size) { return 0; } -static int list_directory(void *data, const struct fat12_dirent *dirent) { +static int list_directory(void *data, const struct fat12_dirent *dirent) +{ printf("%d %d %x %d %d %s\n", dirent->ctime, dirent->mtime, dirent->file_attributes, dirent->size, dirent->first_cluster, dirent->filename); } -static int run_command(const char *cmd) { +static int run_command(const char *cmd) +{ int ret = system(cmd); - if (ret) { + if (ret) + { exit(1); } return 0; } -static void memset_str(uint8_t *bfr, uint8_t *val, size_t count) { +static void memset_str(uint8_t *bfr, uint8_t *val, size_t count) +{ int i; - for (i = 0; i < count; i++) { + for (i = 0; i < count; i++) + { bfr[i] = val[i & 0x7]; } } -int main(int argc, char **argv) { +int main(int argc, char **argv) +{ uint8_t tmp_bfr[32768]; const char *img_name = "build/fat12-fragmented.img"; int ret = 0; int fd; struct fat12_partition *part = fat12_alloc(); - + ret = make_image(img_name, 9 * 1024 * 1024); - if (ret == -1) { + if (ret == -1) + { return 1; } - if (-1 == fat12_open(part, img_name)) { + if (-1 == fat12_open(part, img_name)) + { fprintf(stderr, "couldn't open fat12 on %s: %s\n", img_name, strerror(errno)); return 1; } diff --git a/tests/mkfs-simple.c b/tests/mkfs-simple.c index 93ef7d5..fa0ce0f 100644 --- a/tests/mkfs-simple.c +++ b/tests/mkfs-simple.c @@ -9,15 +9,17 @@ #include "fat12.h" #include "io.h" -static int make_image(const char *name, uint32_t size) { - +static int make_image(const char *name, uint32_t size) +{ struct pang_io *io = pang_open(name); - if (!io) { + if (!io) + { fprintf(stderr, "couldn't open %s: %s\n", name, strerror(errno)); return 1; } - if (-1 == fat12_mkfs(io, size)) { + if (-1 == fat12_mkfs(io, size)) + { fprintf(stderr, "couldn't make fat12 on %s: %s\n", name, strerror(errno)); pang_close(&io); return 1; @@ -26,7 +28,8 @@ static int make_image(const char *name, uint32_t size) { return 0; } -int main(int argc, char **argv) { +int main(int argc, char **argv) +{ int ret = 0; ret += make_image("build/fat12-1300k.img", 1300 * 1024);