diff --git a/include/fat12.h b/include/fat12.h index 353f124..5106e52 100644 --- a/include/fat12.h +++ b/include/fat12.h @@ -4,16 +4,28 @@ #include struct fat12_partition; +struct fat12_dirent { + char filename[256]; + uint32_t first_cluster; + uint32_t size; + uint32_t file_attributes; + uint32_t ctime; + uint32_t mtime; +}; 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); +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); uint16_t fat12_read_u16(void *ptr); +void fat12_write_u32(void *ptr, uint32_t val); +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); diff --git a/src/fat12.c b/src/fat12.c index d65458f..d5414f0 100644 --- a/src/fat12.c +++ b/src/fat12.c @@ -50,6 +50,22 @@ uint16_t fat12_read_u16(void *ptr) { return 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) { + uint16_t val = 0; + 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) { uint32_t offset = (cluster * 3) / 2; if (cluster&1) { @@ -119,6 +135,9 @@ int fat12_open(struct fat12_partition *part, const char *filename) { part->cluster_count = bytes / part->sector_size / part->cluster_size; part->cluster_bytes = (part->cluster_count * 3) / 2; + // Move to the root directory + part->current_cluster = part->first_offset; + /// fprintf(stderr, "part->sector_size: %d\n", part->sector_size); @@ -141,6 +160,53 @@ int fat12_open(struct fat12_partition *part, const char *filename) { return 0; } +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)) { + struct fat12_dirent dirent; + uint8_t buf[part->sector_size]; + uint32_t offset; + pang_seek(part->fd, sector * part->sector_size, SEEK_SET); + pang_read(part->fd, buf, sizeof(buf)); + + 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); + memcpy(dirent.filename + 8, entry->extension, 3); + 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)) + callback(data, &dirent); + } + 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)) { + uint32_t sector; + 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) { + 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 { + sector = dir_cluster * part->cluster_size + part->first_offset; + while (dir_cluster > 1 && dir_cluster < 0xff0) { + // dir_cluster = fat12_get_cluster(part->fd, dir_cluster); + } + } + + return 0; +} + int fat12_close(struct fat12_partition *part) { if (!part) return -1; diff --git a/tests/fragment-file.c b/tests/fragment-file.c index 12733ad..44d3c09 100644 --- a/tests/fragment-file.c +++ b/tests/fragment-file.c @@ -25,22 +25,29 @@ static int make_image(const char *name, uint32_t size) { return 0; } +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); +} + int main(int argc, char **argv) { - const char *img_name = "build/fat12-1800k.img"; + // const char *img_name = "build/fat12-1800k.img"; + const char *img_name = "disk-image"; int ret = 0; int fd; struct fat12_partition *part = fat12_alloc(); - ret = make_image(img_name, 1800 * 1024); - if (ret == -1) { - return 1; - } + // ret = make_image(img_name, 1800 * 1024); + // if (ret == -1) { + // return 1; + // } if (-1 == fat12_open(part, img_name)) { fprintf(stderr, "couldn't open fat12 on %s: %s\n", img_name, strerror(errno)); return 1; } + fat12_ls_foreach(part, 0, NULL, list_directory); + fat12_close(part); fat12_free(&part);