diff --git a/Makefile b/Makefile index 2ba9a15..0d3f313 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,15 @@ CFLAGS ?= -Iinclude -all: build build/test-get-set-cluster build/test-mkfs-simple +all: build build/test-get-set-cluster build/test-mkfs-simple build/test-fragment-file build: mkdir build -build/test-get-set-cluster: tests/get-set-cluster.c src/fat12.c include/fat12.h - $(CC) $(CFLAGS) tests/get-set-cluster.c src/fat12.c -o build/test-get-set-cluster +build/test-get-set-cluster: tests/get-set-cluster.c src/fat12.c include/fat12.h src/io.c include/io.h + $(CC) $(CFLAGS) tests/get-set-cluster.c src/fat12.c src/io.c -o build/test-get-set-cluster -build/test-mkfs-simple: tests/mkfs-simple.c src/fat12.c include/fat12.h src/mkfat.c src/io.c - $(CC) $(CFLAGS) tests/mkfs-simple.c src/mkfat.c src/fat12.c src/io.c -o $@ \ No newline at end of file +build/test-mkfs-simple: tests/mkfs-simple.c src/fat12.c include/fat12.h src/mkfat.c src/io.c include/io.h + $(CC) $(CFLAGS) tests/mkfs-simple.c src/mkfat.c src/fat12.c src/io.c -o $@ + +build/test-fragment-file: tests/fragment-file.c src/fat12.c include/fat12.h src/mkfat.c src/io.c include/io.h + $(CC) $(CFLAGS) tests/fragment-file.c src/mkfat.c src/fat12.c src/io.c -o $@ \ No newline at end of file diff --git a/include/fat12-internals.h b/include/fat12-internals.h new file mode 100644 index 0000000..a937150 --- /dev/null +++ b/include/fat12-internals.h @@ -0,0 +1,20 @@ +#ifndef FAT12_INTERNALS_H__ +#define FAT12_INTERNALS_H__ + +struct fat_directory_entry { + uint8_t file_name[8]; + uint8_t extension[3]; + uint8_t file_attributes; + uint8_t reserved1; + uint8_t ctime_ms; + uint8_t ctime_hms[2]; + uint8_t ctime_date[2]; + uint8_t atime_date[2]; + uint8_t ea_index[2]; + uint8_t mtime_hms[2]; + uint8_t mtime_date[2]; + uint8_t first_cluster[2]; + uint8_t file_size[4]; +}; + +#endif /* FAT12_INTERNALS_H__ */ \ No newline at end of file diff --git a/include/fat12.h b/include/fat12.h index 4ca9527..353f124 100644 --- a/include/fat12.h +++ b/include/fat12.h @@ -3,6 +3,13 @@ #include +struct fat12_partition; + +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_write_u8(void *ptr, uint8_t val); uint8_t fat12_read_u8(void *ptr); void fat12_write_u16(void *ptr, uint16_t val); @@ -13,20 +20,4 @@ uint32_t fat12_get_cluster(void *fat, uint32_t cluster); int fat12_defrag(int fd); int fat12_mkfs(int fd, uint32_t bytes); -struct fat_directory_entry { - uint8_t file_name[8]; - uint8_t extension[3]; - uint8_t file_attributes; - uint8_t reserved1; - uint8_t ctime_ms; - uint8_t ctime_hms[2]; - uint8_t ctime_date[2]; - uint8_t atime_date[2]; - uint8_t ea_index[2]; - uint8_t mtime_hms[2]; - uint8_t mtime_date[2]; - uint8_t first_cluster[2]; - uint8_t file_size[4]; -}; - #endif /* PANG_O_LIN_FAT12_H__ */ \ No newline at end of file diff --git a/include/io.h b/include/io.h index 9d08cc3..53423ff 100644 --- a/include/io.h +++ b/include/io.h @@ -1,14 +1,20 @@ #ifndef PANG_O_LIN_IO_H__ #define PANG_O_LIN_IO_H__ -#include - #ifdef unix +#include +#include +#include +#include +#include +#include #include #endif ssize_t pang_write(int fd, const void *buf, size_t count); ssize_t pang_read(int fd, void *buf, size_t count); off_t pang_seek(int fd, off_t offset, int whence); +int pang_open(const char *pathname, int flags); +int pang_close(int fd); #endif /* PANG_O_LIN_IO_H__ */ \ No newline at end of file diff --git a/src/defrag.c b/src/defrag.c index d9ddc34..c98c39e 100644 --- a/src/defrag.c +++ b/src/defrag.c @@ -1,4 +1,8 @@ +#include +#include +#include + #include "io.h" #define try(x) do { int i = (x); if (i == -1) { return -1 } } while (0) @@ -34,12 +38,12 @@ int fat12_defrag(int fd) { } // 32 root entries keeps it padded correctly. - if (fat12_read_u16(mbr + 0x11, 32) != 32) { + if (fat12_read_u16(buf + 0x11, 32) != 32) { return -2; } // Total number of 512-byte sectors - fat12_write_u16(mbr + 0x13, bytes / sector_size); + uint32_t clufat12_read_u16(buf + 0x13, bytes / sector_size); return 0; } \ No newline at end of file diff --git a/src/fat12.c b/src/fat12.c index 6ee9bcb..d65458f 100644 --- a/src/fat12.c +++ b/src/fat12.c @@ -1,5 +1,32 @@ #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; @@ -49,4 +76,93 @@ uint32_t fat12_get_cluster(void *fat, uint32_t cluster) { } 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; } \ No newline at end of file diff --git a/src/io.c b/src/io.c index 223377b..c061c00 100644 --- a/src/io.c +++ b/src/io.c @@ -1,3 +1,6 @@ +#include +#include + #include "io.h" #ifdef unix @@ -12,4 +15,13 @@ ssize_t pang_read(int fd, void *buf, size_t count) { off_t pang_seek(int fd, off_t offset, int whence) { return lseek(fd, offset, whence); } + +int pang_open(const char *pathname, int flags) { + return open(pathname, flags); +} + +int pang_close(int fd) { + return close(fd); +} + #endif \ No newline at end of file diff --git a/src/mkfat.c b/src/mkfat.c index 0fe12aa..350a937 100644 --- a/src/mkfat.c +++ b/src/mkfat.c @@ -3,8 +3,11 @@ #include #include "fat12.h" +#include "fat12-internals.h" #include "io.h" +#include + // Create a FAT12 filesystem using the given file descriptor, // with length _bytes_. // It will define a root directory size and padding size so that the file sectors @@ -27,15 +30,15 @@ int fat12_mkfs(int fd, uint32_t bytes) { uint32_t root_directory_sector_count = cluster_size - (fat_size_sectors + reserved_sectors); uint32_t root_directory_entry_count = (sector_size / sizeof(struct fat_directory_entry)) * root_directory_sector_count; - // fprintf(stderr, "bytes: %d\n", bytes); - // fprintf(stderr, "sector_size: %d\n", sector_size); - // fprintf(stderr, "cluster_size: %d\n", cluster_size); - // fprintf(stderr, "reserved_sectors: %d\n", reserved_sectors); - // fprintf(stderr, "fat_size: %d\n", fat_size); - // fprintf(stderr, "fat_size_sectors: %d\n", fat_size_sectors); - // fprintf(stderr, "root_directory_sector_count: %d\n", root_directory_sector_count); - // fprintf(stderr, "root_directory_entry_count: %d\n", root_directory_entry_count); - // fprintf(stderr, "\n"); + fprintf(stderr, "bytes: %d\n", bytes); + fprintf(stderr, "sector_size: %d\n", sector_size); + fprintf(stderr, "cluster_size: %d\n", cluster_size); + fprintf(stderr, "reserved_sectors: %d\n", reserved_sectors); + fprintf(stderr, "fat_size: %d\n", fat_size); + fprintf(stderr, "fat_size_sectors: %d\n", fat_size_sectors); + fprintf(stderr, "root_directory_sector_count: %d\n", root_directory_sector_count); + fprintf(stderr, "root_directory_entry_count: %d\n", root_directory_entry_count); + fprintf(stderr, "\n"); memset(mbr, 0, sizeof(mbr)); diff --git a/tests/fragment-file.c b/tests/fragment-file.c new file mode 100644 index 0000000..12733ad --- /dev/null +++ b/tests/fragment-file.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "fat12.h" + +static int make_image(const char *name, uint32_t size) { + + int fd = open(name, O_WRONLY | O_CREAT, 0777); + if (-1 == fd) { + fprintf(stderr, "couldn't open %s: %s\n", name, strerror(errno)); + return 1; + } + + if (-1 == fat12_mkfs(fd, size)) { + fprintf(stderr, "couldn't make fat12 on %s: %s\n", name, strerror(errno)); + close(fd); + return 1; + } + close(fd); + return 0; +} + +int main(int argc, char **argv) { + const char *img_name = "build/fat12-1800k.img"; + int ret = 0; + int fd; + struct fat12_partition *part = fat12_alloc(); + + 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_close(part); + fat12_free(&part); + + return 0; +} \ No newline at end of file