-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathstdio.c
130 lines (117 loc) · 4.27 KB
/
stdio.c
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include "stddef.h"
#include "stdio.h"
#include "fat32.h"
#include "common.h"
typedef struct FILE {
//struct dir_entry file_ent;
uint32_t curr_cluster;
uint32_t file_size; // total file size
uint32_t fptr; // index into the file
uint32_t buffptr; // index into currbuf
uint8_t currbuf[]; // flexible member for current cluster
} FILE;
//static inline void dump_dir(struct directory *dir) {
// for(int entryi = 0; entryi < dir->num_entries; entryi++) {
// printf("\t%s\n", dir->entries[entryi]);
// }
//}
static inline int entry_for_path(const char *path, struct dir_entry *entry) {
struct directory dir;
populate_root_dir(master_fs, &dir);
int found_file = 0;
if(path[0] != '/') {
return found_file;
}
char *cutpath = strdup(path);
char *tokstate = NULL;
char *next_dir = strtok_r(cutpath, "/", &tokstate);
struct dir_entry *currentry = NULL;
entry->name = NULL;
while (next_dir) {
int found = 0;
for(int entryi = 0; entryi < dir.num_entries; entryi++) {
currentry = &dir.entries[entryi];
if(strcmp(currentry->name, next_dir) == 0) {
if(entry->name) kfree(entry->name);
*entry = *currentry;
// TODO: Make sure this doesn't leak. Very dangerous:
entry->name = strdup(currentry->name);
uint32_t cluster = currentry->first_cluster;
free_directory(master_fs, &dir);
populate_dir(master_fs, &dir, cluster);
found = 1;
break;
}
}
if(!found) {
kfree(cutpath);
free_directory(master_fs, &dir);
return 0;
}
next_dir = strtok_r(NULL, "/", &tokstate);
}
free_directory(master_fs, &dir);
kfree(cutpath);
return 1;
}
FILE *fopen(const char *pathname, const char *mode) {
struct dir_entry entry;
if(!entry_for_path(pathname, &entry)) {
kfree(entry.name);
return NULL;
}
// printf("Got entry: %s [%d]\n", entry.name, entry.first_cluster);
kfree(entry.name);
FILE *f = kmalloc(sizeof (FILE) + master_fs->cluster_size);
f->curr_cluster = entry.first_cluster;
f->file_size = entry.file_size;
f->fptr = 0;
f->buffptr = 0;
getCluster(master_fs, f->currbuf, f->curr_cluster);
return f;
}
FILE *fdopen(int fd, const char *mode);
FILE *freopen(const char *pathname, const char *mode, FILE *stream);
int fclose(FILE *stream) {
kfree(stream);
}
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) {
size_t bytes_to_read = size * nmemb;
size_t bytes_read = 0;
if(stream->fptr + bytes_to_read > stream->file_size) {
bytes_to_read = stream->file_size - stream->fptr;
}
//printf("Reading %d bytes.\n", bytes_to_read);
while(bytes_to_read > 0) {
if(stream->buffptr + bytes_to_read > master_fs->cluster_size) {
// Need to read at least 1 more cluster
size_t to_read_in_this_cluster = master_fs->cluster_size - stream->buffptr;
memcpy(ptr + bytes_read, stream->currbuf + stream->buffptr, to_read_in_this_cluster);
bytes_read += to_read_in_this_cluster;
//printf("buffptr = 0\n");
stream->buffptr = 0;
//printf("Getting next cluster.\n");
stream->curr_cluster = get_next_cluster_id(master_fs, stream->curr_cluster);
//printf("Next cluster: %x\n", stream->curr_cluster);
if(stream->curr_cluster >= EOC) {
//printf("Returning.\n");
stream->fptr += bytes_read;
return bytes_read;
}
//printf("getting next cluster.\n");
getCluster(master_fs, stream->currbuf, stream->curr_cluster);
bytes_to_read -= to_read_in_this_cluster;
}
else {
//printf("buffptr: %d\n", stream->buffptr);
memcpy(ptr + bytes_read, stream->currbuf + stream->buffptr, bytes_to_read);
bytes_read += bytes_to_read;
stream->buffptr += bytes_to_read;
bytes_to_read = 0;
}
}
//printf("Returning.\n");
stream->fptr += bytes_read;
return bytes_read;
}
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);