Skip to content

Commit 502052f

Browse files
Attempting to fix FAT16 (im so mad)
1 parent 8d25463 commit 502052f

File tree

4 files changed

+125
-109
lines changed

4 files changed

+125
-109
lines changed

disk.img

0 Bytes
Binary file not shown.

source/includes/filesystems/fat16.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include <basics.h>
1616
#include <graphics.h>
17+
#include <ahci.h>
1718

1819
#define FAT16_EOC 0xFFF8
1920
#define FAT16_ROOT_CLUSTER 0
@@ -97,7 +98,7 @@ typedef enum {
9798
FAT_ERR_BAD_CLUSTER,
9899
} fat_err_t;
99100

100-
int detect_fat_type(int8* buf);
101+
partition_fs_type_t detect_fat_type_enum(const int8* buf);
101102
int fat16_mount(int portno, uint32_t partition_lba, fat16_fs_t* fs) ;
102103
uint16_t fat16_read_fat_fs(fat16_fs_t* fs, uint16_t cluster);
103104
void fat16_list_root(fat16_fs_t* fs);
@@ -107,7 +108,6 @@ int fat16_find_in_dir(fat16_fs_t* fs, uint16_t current_cluster, const char* name
107108
void fat16_list_dir_cluster(fat16_fs_t* fs, uint16_t start_cluster);
108109
void fat16_format_name(const char* input, char out[11]);
109110
int fat16_find_file(fat16_fs_t* fs, const char* name, fat16_dir_entry_t* out);
110-
void fat16_read_file(fat16_fs_t* fs, fat16_dir_entry_t* file);
111111

112112
int fat16_open(fat16_fs_t* fs, const char* path, fat16_file_t* f);
113113
int fat16_read(fat16_file_t* f, uint8_t* out, uint32_t size);

source/kernel/C/filesystems/fat16.c

Lines changed: 103 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@
1313
#include <strings.h>
1414
#include <ahci.h>
1515

16-
int detect_fat_type(int8* buf) {
16+
static int fat16_is_reserved_name(cstring name) {
17+
return strcmp(name, ".") == 0 || strcmp(name, "..") == 0;
18+
}
19+
20+
partition_fs_type_t detect_fat_type_enum(const int8* buf) {
1721
fat16_boot_sector_t* bs = (fat16_boot_sector_t*)buf;
1822

1923
if (bs->sectors_per_fat != 0 && bs->max_root_dir_entries != 0) {
@@ -22,37 +26,16 @@ int detect_fat_type(int8* buf) {
2226
uint32_t cluster_count = data_sectors / bs->sectors_per_cluster;
2327

2428
if (cluster_count < 4085) {
25-
return 12;
29+
return FS_FAT12;
2630
} else if (cluster_count < 65525) {
27-
return 16;
31+
return FS_FAT16;
2832
} else {
29-
return 1;
33+
return FS_UNKNOWN;
3034
}
3135
} else if (bs->max_root_dir_entries == 0) {
32-
return 32;
36+
return FS_FAT32;
3337
} else {
34-
return FAT_OK;
35-
}
36-
}
37-
38-
static int fat16_is_reserved_name(const char* name) {
39-
return strcmp(name, ".") == 0 || strcmp(name, "..") == 0;
40-
}
41-
42-
partition_fs_type_t detect_fat_type_enum(const int8* buf){
43-
int fat = detect_fat_type(buf);
44-
45-
switch(fat){
46-
case 12:
47-
return FS_FAT12;
48-
case 16:
49-
return FS_FAT16;
50-
case 32:
51-
return FS_FAT32;
52-
case 1:
53-
case 0:
54-
default:
55-
return FS_UNKNOWN;
38+
return FS_UNKNOWN;
5639
}
5740
}
5841

@@ -171,50 +154,60 @@ void fat16_list_root(fat16_fs_t* fs) {
171154
}
172155
}
173156
}
174-
175-
print("\n");
176157
}
177158

178159

179-
int fat16_find_path(
180-
fat16_fs_t* fs,
181-
const char* path,
182-
fat16_dir_entry_t* out
183-
) {
184-
char part[13];
185-
uint16_t current_cluster = FAT16_ROOT_CLUSTER;
160+
int fat16_find_path(fat16_fs_t* fs, const char* path, fat16_dir_entry_t* out) {
161+
if (!fs || !path || !*path) return FAT_ERR_NOT_FOUND;
162+
163+
uint16_t current_cluster = FAT16_ROOT_CLUSTER; // start at root
186164
const char* p = path;
165+
char part[13];
187166

167+
// Skip leading slashes
188168
while (*p == '/') p++;
189169

170+
// Root path
171+
if (*p == 0) {
172+
out->first_cluster = FAT16_ROOT_CLUSTER;
173+
out->attr = 0x10; // mark as directory
174+
return FAT_OK;
175+
}
176+
190177
while (*p) {
178+
// Extract next path component
191179
int len = 0;
192180
while (p[len] && p[len] != '/') len++;
181+
if (len >= sizeof(part)) return FAT_ERR_NOT_FOUND;
193182

194183
memcpy(part, p, len);
195184
part[len] = 0;
196185

197-
if (current_cluster == 0) {
198-
if (fat16_find_file(fs, part, out) != 0)
199-
return FAT_ERR_NOT_FOUND;
200-
} else {
201-
if (fat16_find_in_dir(fs, current_cluster, part, out) != 0)
202-
return FAT_ERR_NOT_FOUND;
203-
}
186+
fat16_dir_entry_t entry;
187+
int ret = fat16_find_in_dir(fs, current_cluster, part, &entry);
188+
if (ret != FAT_OK) return FAT_ERR_NOT_FOUND;
189+
190+
// Update current cluster for next iteration
191+
current_cluster = entry.first_cluster;
192+
193+
// If not last component, must be a directory
194+
if (p[len] == '/' && !(entry.attr & 0x10))
195+
return FAT_ERR_NOT_FOUND;
204196

205197
p += len;
206198
while (*p == '/') p++;
207199

208-
if (*p) {
209-
if (!(out->attr & 0x10))
210-
return FAT_ERR_NOT_FOUND; // not a directory
211-
current_cluster = out->first_cluster;
200+
if (*p == 0) {
201+
// last component reached
202+
*out = entry;
203+
return FAT_OK;
212204
}
213205
}
214206

215-
return FAT_OK;
207+
return FAT_ERR_NOT_FOUND;
216208
}
217209

210+
218211
int fat16_match_name(fat16_dir_entry_t* e, const char* name) {
219212
char fatname[11];
220213
fat16_format_name(name, fatname);
@@ -407,28 +400,6 @@ int fat16_find_file(fat16_fs_t* fs, const char* name, fat16_dir_entry_t* out) {
407400
return FAT_ERR_NOT_FOUND;
408401
}
409402

410-
411-
void fat16_read_file(fat16_fs_t* fs, fat16_dir_entry_t* file) {
412-
uint16_t cluster = file->first_cluster;
413-
uint8_t buf[512];
414-
415-
while (cluster < 0xFFF8) {
416-
uint32_t lba =
417-
fs->data_start +
418-
(cluster - 2) * fs->bs.sectors_per_cluster;
419-
420-
for (int s = 0; s < fs->bs.sectors_per_cluster; s++) {
421-
ahci_read_sector(fs->portno, lba + s, buf, 1);
422-
for (int i = 0; i < 512; i++)
423-
printfnoln("%c", buf[i]);
424-
}
425-
426-
cluster = fat16_read_fat_fs(fs, cluster);
427-
}
428-
429-
print("\n");
430-
}
431-
432403
int fat16_open(fat16_fs_t* fs, const char* path, fat16_file_t* f) {
433404
uint16_t parent;
434405
char name[13];
@@ -464,11 +435,13 @@ int fat16_read(fat16_file_t* f, uint8_t* out, uint32_t size) {
464435
uint32_t sector_in_cluster =
465436
(f->pos / 512) % f->fs->bs.sectors_per_cluster;
466437

467-
uint16_t cluster = f->cluster;
438+
uint16_t cluster = f->entry.first_cluster;
439+
uint32_t idx = f->pos / cluster_size;
468440

469-
// Advance cluster only when needed
470-
while (cluster_index--) {
441+
for (uint32_t i = 0; i < idx; i++) {
471442
cluster = fat16_read_fat_fs(f->fs, cluster);
443+
if (cluster >= FAT16_EOC)
444+
return read;
472445
}
473446

474447
uint32_t lba =
@@ -854,8 +827,6 @@ int fat16_unlink(fat16_fs_t* fs, uint16_t parent_cluster, const char* name) {
854827
return fat16_delete_entry_in_cluster(fs, parent_cluster, fatname);
855828
}
856829

857-
858-
859830
int fat16_truncate(fat16_file_t* f, uint32_t new_size) {
860831
if (new_size >= f->entry.filesize)
861832
return FAT_OK;
@@ -1234,9 +1205,10 @@ int fat16_ls(fat16_fs_t* fs, const char* path) {
12341205
}
12351206

12361207
int fat16_cd(fat16_fs_t* fs, const char* path, uint16_t* pwd_cluster) {
1237-
uint16_t new_cluster;
1208+
uint16_t new_cluster = 0;
1209+
uint16_t current = *pwd_cluster;
12381210

1239-
if (fat16_resolve_path(fs, path, *pwd_cluster, &new_cluster) != 0) {
1211+
if (fat16_resolve_path(fs, path, current, &new_cluster) != 0) {
12401212
printf("cd: no such directory: %s\n", path);
12411213
return FAT_ERR_NOT_FOUND;
12421214
}
@@ -1256,8 +1228,6 @@ int fat16_resolve_path(
12561228
uint16_t current_cluster;
12571229

12581230
const char* p = path;
1259-
1260-
// skip leading '/'
12611231
while (*p == '/') p++;
12621232

12631233
// absolute path starts from root
@@ -1378,38 +1348,72 @@ int fat16_rmdir(fat16_fs_t* fs, uint16_t dir_cluster)
13781348
{
13791349
uint8_t buf[512];
13801350

1381-
debug_printf("[fat16] rmdir cluster=%u\n", dir_cluster);
1382-
13831351
if (dir_cluster < 2)
13841352
return FAT_ERR_NOT_FOUND;
13851353

1386-
uint32_t lba = fat16_cluster_lba(fs, dir_cluster);
1354+
uint16_t cluster = dir_cluster;
13871355

1388-
for (uint32_t s = 0; s < fs->bs.sectors_per_cluster; s++) {
1389-
ahci_read_sector(fs->portno, lba + s, buf, 1);
1390-
fat16_dir_entry_t* e = (fat16_dir_entry_t*)buf;
1356+
/* ---------- PASS 1: recurse & free children ---------- */
1357+
while (cluster < FAT16_EOC) {
1358+
uint32_t lba = fat16_cluster_lba(fs, cluster);
13911359

1392-
for (int i = 0; i < DIR_ENTRIES_PER_SECTOR; i++) {
1360+
for (uint32_t s = 0; s < fs->bs.sectors_per_cluster; s++) {
1361+
ahci_read_sector(fs->portno, lba + s, buf, 1);
1362+
fat16_dir_entry_t* e = (fat16_dir_entry_t*)buf;
13931363

1394-
if (e[i].name[0] == 0x00)
1395-
goto done;
1364+
for (int i = 0; i < DIR_ENTRIES_PER_SECTOR; i++) {
1365+
if (e[i].name[0] == 0x00)
1366+
goto pass2;
13961367

1397-
if (e[i].name[0] == 0xE5)
1398-
continue;
1368+
if (e[i].name[0] == 0xE5)
1369+
continue;
13991370

1400-
if (!memcmp(e[i].name, ". ", 11) ||
1401-
!memcmp(e[i].name, ".. ", 11))
1402-
continue;
1371+
if (fat16_name_eq(e[i].name, ".") ||
1372+
fat16_name_eq(e[i].name, ".."))
1373+
continue;
14031374

1404-
if (e[i].attr & 0x10)
1405-
fat16_rmdir(fs, e[i].first_cluster);
1406-
else
1407-
fat16_free_chain(fs, e[i].first_cluster);
1375+
if (e[i].first_cluster < 2)
1376+
continue;
1377+
1378+
if (e[i].attr & 0x10)
1379+
fat16_rmdir(fs, e[i].first_cluster);
1380+
else
1381+
fat16_free_chain(fs, e[i].first_cluster);
1382+
1383+
e[i].name[0] = 0xE5;
1384+
ahci_write_sector(fs->portno, lba + s, buf, 1);
1385+
}
1386+
}
1387+
1388+
cluster = fat16_read_fat_fs(fs, cluster);
1389+
}
1390+
1391+
pass2:
1392+
cluster = dir_cluster;
1393+
1394+
/* ---------- PASS 2: mark entries deleted ---------- */
1395+
while (cluster < FAT16_EOC) {
1396+
uint32_t lba = fat16_cluster_lba(fs, cluster);
14081397

1409-
e[i].name[0] = 0xE5;
1398+
for (uint32_t s = 0; s < fs->bs.sectors_per_cluster; s++) {
1399+
ahci_read_sector(fs->portno, lba + s, buf, 1);
1400+
fat16_dir_entry_t* e = (fat16_dir_entry_t*)buf;
1401+
1402+
for (int i = 0; i < DIR_ENTRIES_PER_SECTOR; i++) {
1403+
if (e[i].name[0] == 0x00)
1404+
goto done;
1405+
1406+
if (fat16_name_eq(e[i].name, ".") ||
1407+
fat16_name_eq(e[i].name, ".."))
1408+
continue;
1409+
1410+
e[i].name[0] = 0xE5;
1411+
}
1412+
1413+
ahci_write_sector(fs->portno, lba + s, buf, 1);
14101414
}
14111415

1412-
ahci_write_sector(fs->portno, lba + s, buf, 1);
1416+
cluster = fat16_read_fat_fs(fs, cluster);
14131417
}
14141418

14151419
done:

source/kernel/C/filesystems/vfs.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -295,15 +295,14 @@ int vfs_rm_recursive(const char* path)
295295
fat16_dir_entry_t e;
296296
if (fat16_find_in_dir(fs, parent, name, &e) != 0)
297297
return -1;
298-
299-
fat16_delete_entry(fs, parent, name);
300-
298+
301299
if (e.attr & 0x10) {
302300
fat16_rmdir(fs, e.first_cluster);
303301
} else {
304302
fat16_free_chain(fs, e.first_cluster);
305303
}
306304

305+
fat16_delete_entry(fs, parent, name);
307306
return 0;
308307
}
309308

@@ -317,15 +316,28 @@ int vfs_cd(const char* path) {
317316
vfs_normalize_path(path, norm);
318317

319318
vfs_mount_res_t res;
320-
if (vfs_resolve_mount(norm, &res) != 0) return -2;
319+
if (vfs_resolve_mount(norm, &res) != 0) {
320+
return -1;
321+
}
322+
323+
if (res.mnt->type == FS_FAT16) {
324+
fat16_fs_t* fs = (fat16_fs_t*)res.mnt->fs;
321325

322-
if (res.mnt->type == FS_FAT16){
323326
uint16_t new_cluster;
324-
if (fat16_cd((fat16_fs_t*)res.mnt->fs, res.rel_path, &new_cluster) != 0) return -4;
327+
uint16_t base_cluster = vfs_cwd_cluster;
325328

326-
vfs_cwd_cluster = new_cluster;
327-
strncpy(vfs_cwd, norm, sizeof(vfs_cwd));
329+
// handle root specially
330+
if (*res.rel_path == '\0') {
331+
new_cluster = FAT16_ROOT_CLUSTER;
332+
} else {
333+
int ret = fat16_cd(fs, res.rel_path, &vfs_cwd_cluster);
328334

335+
if (ret != FAT_OK)
336+
return -4;
337+
338+
}
339+
strncpy(vfs_cwd, norm, sizeof(vfs_cwd));
340+
debug_printf("[vfs] cd : %s cluster=%u\n", norm, new_cluster);
329341
return 0;
330342
}
331343

0 commit comments

Comments
 (0)