1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "fat16.h"
typedef enum {
READ_ONLY = 0x1,
HIDDEN = 0x2,
SYSTEM = 0x4,
VOLUME_LABEL = 0x8,
SUBDIRECTORY = 0x10,
ARCHIVE = 0x20,
DEVICE = 0x40
} fat_attribute_t;
const char DELETED = 0xE5;
size_t get_root_directory_location(bios_parameter_block_t bpb) {
size_t fat_sectors = (size_t) bpb.num_fats * bpb.sectors_per_fat;
return (1 + bpb.reserved_sectors + fat_sectors) * bpb.bytes_per_sector;
}
size_t get_offset_from_cluster(size_t cluster, bios_parameter_block_t bpb) {
return get_root_directory_location(bpb) +
bpb.max_root_entries * sizeof(directory_entry_t) +
(cluster - 2) * bpb.sectors_per_cluster * bpb.bytes_per_sector;
}
bool is_directory(directory_entry_t entry) {
return (entry.attribute & SUBDIRECTORY) != 0;
}
bool is_hidden(directory_entry_t entry) {
return entry.filename[0] == '.' || entry.filename[1] == '.' || entry.attribute == 0 ||
(entry.attribute & (HIDDEN | SYSTEM | VOLUME_LABEL)) != 0;
}
char *get_file_name(directory_entry_t entry) {
char *full = malloc(sizeof(entry.filename) + 1 + sizeof(entry.extension) + 1);
assert(full != NULL);
size_t full_index = 0;
size_t filename_index = 0;
while (filename_index < sizeof(entry.filename)) {
char filename_char = entry.filename[filename_index++];
if (filename_char == ' ') {
break;
}
full[full_index++] = filename_char == DELETED ? '?' : filename_char;
}
if (entry.extension[0] != ' ') {
full[full_index++] = '.';
size_t extension_index = 0;
while (extension_index < sizeof(entry.extension)) {
char extension_char = entry.extension[extension_index++];
if (extension_char == ' ') {
break;
}
full[full_index++] = extension_char;
}
}
full[full_index] = '\0';
return full;
}