minor reformatting
Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
48f1f33c49
commit
c018281728
@ -5,7 +5,8 @@
|
|||||||
|
|
||||||
struct pang_io;
|
struct pang_io;
|
||||||
struct fat12_partition;
|
struct fat12_partition;
|
||||||
struct fat12_dirent {
|
struct fat12_dirent
|
||||||
|
{
|
||||||
char filename[256];
|
char filename[256];
|
||||||
uint32_t first_cluster;
|
uint32_t first_cluster;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
@ -14,15 +15,13 @@ struct fat12_dirent {
|
|||||||
uint32_t mtime;
|
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_open(struct fat12_partition *part, const char *filename);
|
||||||
int fat12_close(struct fat12_partition *part);
|
int fat12_close(struct fat12_partition *part);
|
||||||
void fat12_free(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);
|
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);
|
void fat12_write_u8(void *ptr, uint8_t val);
|
||||||
uint8_t fat12_read_u8(void *ptr);
|
uint8_t fat12_read_u8(void *ptr);
|
||||||
void fat12_write_u16(void *ptr, uint16_t val);
|
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);
|
void fat12_set_cluster(void *fat, uint32_t cluster, uint32_t value);
|
||||||
uint32_t fat12_get_cluster(void *fat, uint32_t cluster);
|
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_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);
|
int fat12_delete_file(struct fat12_partition *part, const char *filename);
|
||||||
|
|
||||||
|
165
src/fat12.c
165
src/fat12.c
@ -5,7 +5,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
struct fat12_partition {
|
struct fat12_partition
|
||||||
|
{
|
||||||
struct pang_io *io;
|
struct pang_io *io;
|
||||||
|
|
||||||
// Number of bytes in a sector (512)
|
// Number of bytes in a sector (512)
|
||||||
@ -31,36 +32,42 @@ struct fat12_partition {
|
|||||||
void *fat;
|
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 *)ptr)[0] = (val >> 0) & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t fat12_read_u8(void *ptr) {
|
uint8_t fat12_read_u8(void *ptr)
|
||||||
|
{
|
||||||
uint16_t val = 0;
|
uint16_t val = 0;
|
||||||
val |= (((uint8_t *)ptr)[0] << 0) & 0xff;
|
val |= (((uint8_t *)ptr)[0] << 0) & 0xff;
|
||||||
return val;
|
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)[0] = (val >> 0) & 0xff;
|
||||||
((uint8_t *)ptr)[1] = (val >> 8) & 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;
|
uint16_t val = 0;
|
||||||
val |= (((uint8_t *)ptr)[0] << 0) & 0x00ff;
|
val |= (((uint8_t *)ptr)[0] << 0) & 0x00ff;
|
||||||
val |= (((uint8_t *)ptr)[1] << 8) & 0xff00;
|
val |= (((uint8_t *)ptr)[1] << 8) & 0xff00;
|
||||||
return val;
|
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)[0] = (val >> 0) & 0xff;
|
||||||
((uint8_t *)ptr)[1] = (val >> 8) & 0xff;
|
((uint8_t *)ptr)[1] = (val >> 8) & 0xff;
|
||||||
((uint8_t *)ptr)[2] = (val >> 16) & 0xff;
|
((uint8_t *)ptr)[2] = (val >> 16) & 0xff;
|
||||||
((uint8_t *)ptr)[3] = (val >> 24) & 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;
|
uint16_t val = 0;
|
||||||
val |= (((uint8_t *)ptr)[0] << 0) & 0x000000ff;
|
val |= (((uint8_t *)ptr)[0] << 0) & 0x000000ff;
|
||||||
val |= (((uint8_t *)ptr)[1] << 8) & 0x0000ff00;
|
val |= (((uint8_t *)ptr)[1] << 8) & 0x0000ff00;
|
||||||
@ -69,29 +76,35 @@ uint32_t fat12_read_u32(void *ptr) {
|
|||||||
return val;
|
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;
|
uint32_t offset = (cluster * 3) / 2;
|
||||||
// fprintf(stderr, "Cluster %d -> %03x (%02x%02x -> ", cluster, value, ((uint8_t *)fat)[offset], ((uint8_t *)fat)[offset + 1]);
|
// 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] = (((uint8_t *)fat)[offset] & 0x0f) | ((value << 4) & 0xf0);
|
||||||
((uint8_t *)fat)[offset + 1] = value >> 4;
|
((uint8_t *)fat)[offset + 1] = value >> 4;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
((uint8_t *)fat)[offset] = value;
|
((uint8_t *)fat)[offset] = value;
|
||||||
((uint8_t *)fat)[offset + 1] = (((uint8_t *)fat)[offset + 1] & 0xf0) | ((value >> 8) & 0x0f);
|
((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]);
|
// 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 offset = (cluster * 3) / 2;
|
||||||
uint32_t value = 0;
|
uint32_t value = 0;
|
||||||
|
|
||||||
if (cluster&1) {
|
if (cluster & 1)
|
||||||
|
{
|
||||||
value |= (((uint8_t *)fat)[offset] >> 4) & 0x00f;
|
value |= (((uint8_t *)fat)[offset] >> 4) & 0x00f;
|
||||||
value |= (((uint8_t *)fat)[offset + 1] << 4) & 0xff0;
|
value |= (((uint8_t *)fat)[offset + 1] << 4) & 0xff0;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
value |= ((uint8_t *)fat)[offset];
|
value |= ((uint8_t *)fat)[offset];
|
||||||
value |= (((uint8_t *)fat)[offset + 1] << 8) & 0xf00;
|
value |= (((uint8_t *)fat)[offset + 1] << 8) & 0xf00;
|
||||||
}
|
}
|
||||||
@ -101,13 +114,15 @@ uint32_t fat12_get_cluster(void *fat, uint32_t cluster) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fat12_partition *fat12_alloc(void) {
|
struct fat12_partition *fat12_alloc(void)
|
||||||
|
{
|
||||||
struct fat12_partition *part = malloc(sizeof(struct fat12_partition));
|
struct fat12_partition *part = malloc(sizeof(struct fat12_partition));
|
||||||
memset(part, 0, sizeof(*part));
|
memset(part, 0, sizeof(*part));
|
||||||
return 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)
|
if (!part)
|
||||||
return -1;
|
return -1;
|
||||||
@ -142,7 +157,7 @@ int fat12_open(struct fat12_partition *part, const char *filename) {
|
|||||||
// Move to the root directory
|
// Move to the root directory
|
||||||
part->current_cluster = part->first_offset;
|
part->current_cluster = part->first_offset;
|
||||||
|
|
||||||
///
|
///
|
||||||
fprintf(stderr, "part->sector_size: %d\n", part->sector_size);
|
fprintf(stderr, "part->sector_size: %d\n", part->sector_size);
|
||||||
|
|
||||||
// These are in single-unit quantities
|
// 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_count: %d\n", part->cluster_count);
|
||||||
fprintf(stderr, "part->cluster_bytes: %d\n", part->cluster_bytes);
|
fprintf(stderr, "part->cluster_bytes: %d\n", part->cluster_bytes);
|
||||||
fprintf(stderr, "data_bytes: %d\n", bytes);
|
fprintf(stderr, "data_bytes: %d\n", bytes);
|
||||||
///
|
///
|
||||||
|
|
||||||
if (1) {
|
if (1)
|
||||||
|
{
|
||||||
part->fat = malloc(part->fat_size * part->sector_size);
|
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);
|
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;
|
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);
|
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,
|
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;
|
struct fat12_dirent dirent;
|
||||||
uint8_t buf[part->sector_size];
|
uint8_t buf[part->sector_size];
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
pang_read(part->io, sector * part->sector_size, buf, sizeof(buf));
|
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];
|
struct fat_directory_entry *entry = &((struct fat_directory_entry *)buf)[offset];
|
||||||
memset(&dirent, 0, sizeof(dirent));
|
memset(&dirent, 0, sizeof(dirent));
|
||||||
memcpy(dirent.filename, entry->file_name, 8);
|
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;
|
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;
|
uint32_t sector;
|
||||||
if (dir_cluster < 2) {
|
if (dir_cluster < 2)
|
||||||
|
{
|
||||||
sector = part->root_offset;
|
sector = part->root_offset;
|
||||||
uint32_t dir_entries;
|
uint32_t dir_entries;
|
||||||
uint32_t max_entries = part->root_entries;
|
uint32_t max_entries = part->root_entries;
|
||||||
uint32_t entries_per_sector = part->sector_size / sizeof(struct fat_directory_entry);
|
uint32_t entries_per_sector = part->sector_size / sizeof(struct fat_directory_entry);
|
||||||
uint32_t loop = 0;
|
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;
|
uint32_t entries_to_list = entries_per_sector;
|
||||||
if (max_entries - dir_entries < entries_to_list)
|
if (max_entries - dir_entries < entries_to_list)
|
||||||
entries_to_list = max_entries - dir_entries;
|
entries_to_list = max_entries - dir_entries;
|
||||||
fat12_ls_foreach_sector(part, part->root_offset + loop++, entries_to_list, data, callback);
|
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;
|
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);
|
// 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;
|
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);
|
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)
|
if (!part)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (1) {
|
if (1)
|
||||||
|
{
|
||||||
fat12_flush(part);
|
fat12_flush(part);
|
||||||
free(part->fat);
|
free(part->fat);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-1 == pang_close(&part->io)) {
|
if (-1 == pang_close(&part->io))
|
||||||
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fat12_free(struct fat12_partition **part) {
|
void fat12_free(struct fat12_partition **part)
|
||||||
|
{
|
||||||
if (!part)
|
if (!part)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -253,26 +282,30 @@ void fat12_free(struct fat12_partition **part) {
|
|||||||
*part = NULL;
|
*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;
|
uint32_t cluster_value;
|
||||||
if (start < 1)
|
if (start < 1)
|
||||||
start = 1;
|
start = 1;
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
cluster_value = fat12_get_cluster(part->fat, ++start);
|
cluster_value = fat12_get_cluster(part->fat, ++start);
|
||||||
fprintf(stderr, "Cluster %d value: %03x\n", start, cluster_value);
|
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);
|
fprintf(stderr, "Found free cluster %d\n", start);
|
||||||
return 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;
|
struct fat12_dirent dirent;
|
||||||
uint8_t buf[part->sector_size];
|
uint8_t buf[part->sector_size];
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
pang_read(part->io, sector * part->sector_size, buf, sizeof(buf));
|
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];
|
struct fat_directory_entry *entry = &((struct fat_directory_entry *)buf)[offset];
|
||||||
memset(&dirent, 0, sizeof(dirent));
|
memset(&dirent, 0, sizeof(dirent));
|
||||||
memcpy(dirent.filename, entry->file_name, 8);
|
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.first_cluster = fat12_read_u16(&entry->first_cluster);
|
||||||
dirent.size = fat12_read_u32(&entry->file_size);
|
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;
|
((struct fat_directory_entry *)buf)[offset] = *new_dirent;
|
||||||
pang_write(part->io, sector * part->sector_size, buf, sizeof(buf));
|
pang_write(part->io, sector * part->sector_size, buf, sizeof(buf));
|
||||||
return 0;
|
return 0;
|
||||||
@ -289,37 +323,43 @@ static int fat12_add_dirent_sector(struct fat12_partition *part, uint32_t sector
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fat12_dir_update_or_add_dirent(struct fat12_partition *part, uint32_t dir_cluster, const struct fat_directory_entry *dirent) {
|
static int fat12_dir_update_or_add_dirent(struct fat12_partition *part, uint32_t dir_cluster, const struct fat_directory_entry *dirent)
|
||||||
if (1) {
|
{
|
||||||
|
if (1)
|
||||||
|
{
|
||||||
uint32_t sector = part->root_offset;
|
uint32_t sector = part->root_offset;
|
||||||
uint32_t dir_entries;
|
uint32_t dir_entries;
|
||||||
uint32_t max_entries = part->root_entries;
|
uint32_t max_entries = part->root_entries;
|
||||||
uint32_t entries_per_sector = part->sector_size / sizeof(struct fat_directory_entry);
|
uint32_t entries_per_sector = part->sector_size / sizeof(struct fat_directory_entry);
|
||||||
uint32_t loop = 0;
|
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;
|
uint32_t entries_to_list = entries_per_sector;
|
||||||
if (max_entries - dir_entries < entries_to_list)
|
if (max_entries - dir_entries < entries_to_list)
|
||||||
entries_to_list = max_entries - dir_entries;
|
entries_to_list = max_entries - dir_entries;
|
||||||
// TODO: See if a filename already exists
|
// 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 i;
|
||||||
int ext_split = -1;
|
int ext_split = -1;
|
||||||
int name_off = 0;
|
int name_off = 0;
|
||||||
int dirent_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] == '.')
|
if (filename[name_off] == '.')
|
||||||
ext_split = name_off + 1;
|
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))
|
if (dirent_off < (ext_split - 1))
|
||||||
dirent->file_name[dirent_off] = toupper(filename[dirent_off]);
|
dirent->file_name[dirent_off] = toupper(filename[dirent_off]);
|
||||||
else
|
else
|
||||||
@ -327,7 +367,8 @@ static void fat_dirent_set_name(struct fat_directory_entry *dirent, const char *
|
|||||||
}
|
}
|
||||||
|
|
||||||
name_off = ext_split + 1;
|
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]))
|
if ((ext_split >= 0) && (filename[ext_split]))
|
||||||
dirent->extension[dirent_off] = toupper(filename[ext_split++]);
|
dirent->extension[dirent_off] = toupper(filename[ext_split++]);
|
||||||
else
|
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
|
// TODO: directory support
|
||||||
uint32_t first_cluster;
|
uint32_t first_cluster;
|
||||||
uint32_t cluster;
|
uint32_t cluster;
|
||||||
@ -351,7 +393,8 @@ int fat12_write_file(struct fat12_partition *part, const char *filename, const v
|
|||||||
fat12_write_u32(dirent.file_size, size);
|
fat12_write_u32(dirent.file_size, size);
|
||||||
fat12_dir_update_or_add_dirent(part, 0, &dirent);
|
fat12_dir_update_or_add_dirent(part, 0, &dirent);
|
||||||
|
|
||||||
while (size > 0) {
|
while (size > 0)
|
||||||
|
{
|
||||||
uint32_t bytes_to_write = size;
|
uint32_t bytes_to_write = size;
|
||||||
if (bytes_to_write > part->cluster_size * part->sector_size)
|
if (bytes_to_write > part->cluster_size * part->sector_size)
|
||||||
bytes_to_write = part->cluster_size * part->sector_size;
|
bytes_to_write = part->cluster_size * part->sector_size;
|
||||||
@ -364,7 +407,8 @@ int fat12_write_file(struct fat12_partition *part, const char *filename, const v
|
|||||||
fprintf(stderr, "%s: %d bytes left\n", filename, size);
|
fprintf(stderr, "%s: %d bytes left\n", filename, size);
|
||||||
if (!size)
|
if (!size)
|
||||||
fat12_set_cluster(part->fat, cluster, 0xff8);
|
fat12_set_cluster(part->fat, cluster, 0xff8);
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
uint32_t next_cluster = fat12_find_free_cluster(part, cluster);
|
uint32_t next_cluster = fat12_find_free_cluster(part, cluster);
|
||||||
fat12_set_cluster(part->fat, cluster, next_cluster);
|
fat12_set_cluster(part->fat, cluster, next_cluster);
|
||||||
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;
|
uint32_t file_cluster = 0;
|
||||||
|
|
||||||
// Find the dirent of the file
|
// Find the dirent of the file
|
||||||
uint32_t dirent_cluster = 0;
|
uint32_t dirent_cluster = 0;
|
||||||
|
|
||||||
// TODO: Support directories other than the root directory
|
// TODO: Support directories other than the root directory
|
||||||
if (1) {
|
if (1)
|
||||||
|
{
|
||||||
struct fat_directory_entry dirent;
|
struct fat_directory_entry dirent;
|
||||||
uint32_t entries_per_sector = part->sector_size / sizeof(struct fat_directory_entry);
|
uint32_t entries_per_sector = part->sector_size / sizeof(struct fat_directory_entry);
|
||||||
fat_dirent_set_name(&dirent, filename);
|
fat_dirent_set_name(&dirent, filename);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int check_entry_i;
|
int check_entry_i;
|
||||||
int sector = part->root_offset - 1; // -1 because we use it to update the entry below.
|
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];
|
struct fat_directory_entry entries[entries_per_sector];
|
||||||
pang_read(part->io, ++sector * part->sector_size, entries, sizeof(entries));
|
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++) {
|
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)) {
|
{
|
||||||
|
if (!memcmp(&entries[check_entry_i], &dirent, 11))
|
||||||
|
{
|
||||||
entries[check_entry_i].file_name[0] = 0xe5;
|
entries[check_entry_i].file_name[0] = 0xe5;
|
||||||
pang_write(part->io, sector * part->sector_size, entries, sizeof(entries));
|
pang_write(part->io, sector * part->sector_size, entries, sizeof(entries));
|
||||||
return fat12_read_u16(entries[check_entry_i].first_cluster);
|
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;
|
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
|
// Find the root cluster of the file
|
||||||
uint32_t root_cluster = find_root_cluster_for_file(part, filename);
|
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
|
// A return value of 0 (or 1) is not a valid cluster, so there's
|
||||||
// nothing to do.
|
// nothing to do.
|
||||||
if (root_cluster < 2) {
|
if (root_cluster < 2)
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change the first character of the dirent to 0xe5 to indicate
|
// Change the first character of the dirent to 0xe5 to indicate
|
||||||
// it's been deleted.
|
// it's been deleted.
|
||||||
|
|
||||||
|
|
||||||
// Set all clusters in the FAT to 0x000, indicating they're free.
|
// Set all clusters in the FAT to 0x000, indicating they're free.
|
||||||
uint32_t this_cluster = root_cluster;
|
uint32_t this_cluster = root_cluster;
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
uint32_t next_cluster = fat12_get_cluster(part->fat, this_cluster);
|
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);
|
// 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);
|
fat12_set_cluster(part->fat, this_cluster, 0);
|
||||||
|
15
src/io.c
15
src/io.c
@ -5,19 +5,23 @@
|
|||||||
|
|
||||||
#ifdef unix
|
#ifdef unix
|
||||||
|
|
||||||
struct pang_io {
|
struct pang_io
|
||||||
|
{
|
||||||
int fd;
|
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);
|
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);
|
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);
|
int fd = open(pathname, O_RDWR | O_CREAT, 0777);
|
||||||
if (-1 == fd)
|
if (-1 == fd)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -26,7 +30,8 @@ struct pang_io *pang_open(const char *pathname) {
|
|||||||
return io;
|
return io;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pang_close(struct pang_io **io) {
|
int pang_close(struct pang_io **io)
|
||||||
|
{
|
||||||
if (!io)
|
if (!io)
|
||||||
return -1;
|
return -1;
|
||||||
if (!*io)
|
if (!*io)
|
||||||
|
@ -9,15 +9,18 @@
|
|||||||
#include "fat12.h"
|
#include "fat12.h"
|
||||||
#include "io.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);
|
struct pang_io *io = pang_open(name);
|
||||||
if (!io) {
|
if (!io)
|
||||||
|
{
|
||||||
fprintf(stderr, "couldn't open %s: %s\n", name, strerror(errno));
|
fprintf(stderr, "couldn't open %s: %s\n", name, strerror(errno));
|
||||||
return 1;
|
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));
|
fprintf(stderr, "couldn't make fat12 on %s: %s\n", name, strerror(errno));
|
||||||
pang_close(&io);
|
pang_close(&io);
|
||||||
return 1;
|
return 1;
|
||||||
@ -26,26 +29,32 @@ static int make_image(const char *name, uint32_t size) {
|
|||||||
return 0;
|
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);
|
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);
|
int ret = system(cmd);
|
||||||
if (ret) {
|
if (ret)
|
||||||
|
{
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
return 0;
|
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;
|
int i;
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
bfr[i] = val[i & 0x7];
|
bfr[i] = val[i & 0x7];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
uint8_t tmp_bfr[32768];
|
uint8_t tmp_bfr[32768];
|
||||||
const char *img_name = "build/fat12-fragmented.img";
|
const char *img_name = "build/fat12-fragmented.img";
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -53,11 +62,13 @@ int main(int argc, char **argv) {
|
|||||||
struct fat12_partition *part = fat12_alloc();
|
struct fat12_partition *part = fat12_alloc();
|
||||||
|
|
||||||
ret = make_image(img_name, 9 * 1024 * 1024);
|
ret = make_image(img_name, 9 * 1024 * 1024);
|
||||||
if (ret == -1) {
|
if (ret == -1)
|
||||||
|
{
|
||||||
return 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));
|
fprintf(stderr, "couldn't open fat12 on %s: %s\n", img_name, strerror(errno));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -9,15 +9,17 @@
|
|||||||
#include "fat12.h"
|
#include "fat12.h"
|
||||||
#include "io.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);
|
struct pang_io *io = pang_open(name);
|
||||||
if (!io) {
|
if (!io)
|
||||||
|
{
|
||||||
fprintf(stderr, "couldn't open %s: %s\n", name, strerror(errno));
|
fprintf(stderr, "couldn't open %s: %s\n", name, strerror(errno));
|
||||||
return 1;
|
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));
|
fprintf(stderr, "couldn't make fat12 on %s: %s\n", name, strerror(errno));
|
||||||
pang_close(&io);
|
pang_close(&io);
|
||||||
return 1;
|
return 1;
|
||||||
@ -26,7 +28,8 @@ static int make_image(const char *name, uint32_t size) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
ret += make_image("build/fat12-1300k.img", 1300 * 1024);
|
ret += make_image("build/fat12-1300k.img", 1300 * 1024);
|
||||||
|
Loading…
Reference in New Issue
Block a user