|
|
|
|
@ -42,21 +42,20 @@ typedef struct { |
|
|
|
|
uint32_t size; |
|
|
|
|
uint16_t dir_cluster; |
|
|
|
|
uint16_t dir_index; |
|
|
|
|
uint8_t valid; |
|
|
|
|
uint8_t removed; |
|
|
|
|
} fat16_inode_t; |
|
|
|
|
|
|
|
|
|
static fat16_inode_t inodes[MAX_INODES]; |
|
|
|
|
|
|
|
|
|
static fat16_inode_t *inode_create(uint16_t first_cluster, uint32_t size, uint16_t dir_cluster, uint16_t dir_index) { |
|
|
|
|
for (uint64_t i = 0; i < MAX_INODES; i++) { |
|
|
|
|
if (!inodes[i].valid) { |
|
|
|
|
if (!inodes[i].refs) { |
|
|
|
|
inodes[i] = (fat16_inode_t){ |
|
|
|
|
.refs = 1, |
|
|
|
|
.first_cluster = first_cluster, |
|
|
|
|
.size = size, |
|
|
|
|
.dir_cluster = dir_cluster, |
|
|
|
|
.dir_index = dir_index, |
|
|
|
|
.valid = 1, |
|
|
|
|
}; |
|
|
|
|
return &inodes[i]; |
|
|
|
|
} |
|
|
|
|
@ -66,7 +65,7 @@ static fat16_inode_t *inode_create(uint16_t first_cluster, uint32_t size, uint16 |
|
|
|
|
|
|
|
|
|
static fat16_inode_t *inode_get(uint32_t dir_cluster, uint16_t dir_index) { |
|
|
|
|
for (uint64_t i = 0; i < MAX_INODES; i++) { |
|
|
|
|
if (inodes[i].valid && inodes[i].dir_cluster == dir_cluster && inodes[i].dir_index == dir_index) { |
|
|
|
|
if (inodes[i].refs && inodes[i].dir_cluster == dir_cluster && inodes[i].dir_index == dir_index) { |
|
|
|
|
return &inodes[i]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -84,14 +83,8 @@ static fat16_inode_t *inode_use(uint16_t first_cluster, uint32_t size, uint16_t |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void inode_free(fat16_inode_t *inode) { |
|
|
|
|
inode->refs--; |
|
|
|
|
if (!inode->refs) { |
|
|
|
|
for (uint64_t i = 0; i < MAX_INODES; i++) { |
|
|
|
|
if (&inodes[i] == inode) { |
|
|
|
|
inodes[i].valid = 0; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (inode->refs) { |
|
|
|
|
inode->refs--; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -263,6 +256,10 @@ fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name, uint64_t |
|
|
|
|
return NUL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (((fat16_node_t *)directory)->inode->removed) { |
|
|
|
|
return NUL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint16_t dir_cluster = ((fat16_node_t *)directory)->inode->first_cluster; |
|
|
|
|
|
|
|
|
|
char name_8_3[12]; |
|
|
|
|
@ -350,6 +347,10 @@ fs_node_t *fat16_open_at(const fs_node_t *directory, uint16_t index, uint64_t fl |
|
|
|
|
return NUL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (((fat16_node_t *)directory)->inode->removed) { |
|
|
|
|
return NUL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint16_t dir_cluster = ((fat16_node_t *)directory)->inode->first_cluster; |
|
|
|
|
|
|
|
|
|
fat16_dir_entry_t *entries; |
|
|
|
|
@ -403,6 +404,10 @@ uint64_t fat16_read(const fs_node_t *file, uint32_t offset, uint32_t bytes, void |
|
|
|
|
return (uint64_t)-1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (fat_file->inode->removed) { |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (offset >= fat_file->inode->size) { |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
@ -460,6 +465,10 @@ uint64_t fat16_write(fs_node_t *file, uint32_t offset, const void *from, uint32_ |
|
|
|
|
return (uint64_t)-1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (fat_file->inode->removed) { |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ensure_fat(); |
|
|
|
|
|
|
|
|
|
if (!fat_file->inode->first_cluster) { |
|
|
|
|
@ -540,6 +549,10 @@ uint64_t fat16_truncate(fs_node_t *file, uint32_t size) { |
|
|
|
|
return (uint64_t)-1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (fat_file->inode->removed) { |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (file->size == size) { |
|
|
|
|
return size; |
|
|
|
|
} else if (file->size < size) { |
|
|
|
|
@ -585,6 +598,57 @@ uint64_t fat16_truncate(fs_node_t *file, uint32_t size) { |
|
|
|
|
return (uint64_t)-1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint64_t fat16_remove(fs_node_t *file) { |
|
|
|
|
fat16_node_t *fat_file = (fat16_node_t *)file; |
|
|
|
|
|
|
|
|
|
if (fat_file->base.type != FAT16) { |
|
|
|
|
return (uint64_t)-1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (fat_file->inode->removed) { |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (file->is_dir) { |
|
|
|
|
fat16_dir_entry_t *subentries; |
|
|
|
|
uint16_t subentries_count = read_directory(fat_file->inode->first_cluster, &subentries); |
|
|
|
|
uint16_t ei = 0, vi = 0; |
|
|
|
|
while (ei < subentries_count && subentries[ei].name[0]) { |
|
|
|
|
if ((uint8_t)subentries[ei].name[0] != 0xE5 && (uint8_t)subentries[ei].attributes != 0x0F) { |
|
|
|
|
vi++; |
|
|
|
|
} |
|
|
|
|
ei++; |
|
|
|
|
} |
|
|
|
|
memory_free(subentries); |
|
|
|
|
if (vi > 2) { |
|
|
|
|
return (uint64_t)-1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fat_file->inode->removed = 1; |
|
|
|
|
|
|
|
|
|
if (fat_file->inode->first_cluster) { |
|
|
|
|
ensure_fat(); |
|
|
|
|
uint64_t next_cluster = fat_file->inode->first_cluster; |
|
|
|
|
do { |
|
|
|
|
uint32_t swap = fat[next_cluster]; |
|
|
|
|
fat[next_cluster] = 0; |
|
|
|
|
next_cluster = swap; |
|
|
|
|
} while (next_cluster < 0xFFF8); |
|
|
|
|
flush_fat(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fat16_dir_entry_t *entries; |
|
|
|
|
uint16_t entries_count = read_directory(fat_file->inode->dir_cluster, &entries); |
|
|
|
|
entries[fat_file->inode->dir_index].name[0] = 0xE5; |
|
|
|
|
entries[fat_file->inode->dir_index].first_cluster = 0; |
|
|
|
|
entries[fat_file->inode->dir_index].size = 0; |
|
|
|
|
write_directory(fat_file->inode->dir_cluster, entries, entries_count); |
|
|
|
|
memory_free(entries); |
|
|
|
|
|
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
|
stream_t stream; |
|
|
|
|
fs_node_t *node; |
|
|
|
|
|