diff options
author | Bad Diode <bd@badd10de.dev> | 2021-05-24 18:32:58 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-05-24 18:32:58 +0200 |
commit | f4dd03dd800d7cf2d42169b6f30c10585c5a78c4 (patch) | |
tree | b01cfad554fc82b9b2466b46a63b48eb44151c77 /src | |
parent | 3410761714c70480c063112e5a184c93cae39bb3 (diff) | |
download | uxngba-f4dd03dd800d7cf2d42169b6f30c10585c5a78c4.tar.gz uxngba-f4dd03dd800d7cf2d42169b6f30c10585c5a78c4.zip |
Update filesystem for writing with offset
Diffstat (limited to 'src')
-rw-r--r-- | src/filesystem.c | 138 |
1 files changed, 86 insertions, 52 deletions
diff --git a/src/filesystem.c b/src/filesystem.c index 4a55818..cac2805 100644 --- a/src/filesystem.c +++ b/src/filesystem.c | |||
@@ -62,18 +62,20 @@ typedef struct FileSystem { | |||
62 | FileIndex files[FILE_INDEX_NUM]; | 62 | FileIndex files[FILE_INDEX_NUM]; |
63 | } FileSystem; | 63 | } FileSystem; |
64 | 64 | ||
65 | #define FILE_BLOCK_CAPACITY (FILE_BLOCK_SIZE - sizeof(FileBlock)) | ||
66 | |||
65 | EWRAM_BSS | 67 | EWRAM_BSS |
66 | static FileSystem filesystem; | 68 | static FileSystem filesystem; |
67 | 69 | ||
68 | void | 70 | void |
69 | _fs_read(u8 *dst, size_t pos, size_t n_bytes) { | 71 | _fs_read(u8 *dst, u16 pos, u16 n_bytes) { |
70 | for (size_t i = 0; i < n_bytes; ++i) { | 72 | for (size_t i = 0; i < n_bytes; ++i) { |
71 | dst[i] = SRAM[pos + i]; | 73 | dst[i] = SRAM[pos + i]; |
72 | } | 74 | } |
73 | } | 75 | } |
74 | 76 | ||
75 | void | 77 | void |
76 | _fs_write(u8 *src, size_t pos, size_t n_bytes) { | 78 | _fs_write(u8 *src, u16 pos, u16 n_bytes) { |
77 | for (size_t i = 0; i < n_bytes; ++i) { | 79 | for (size_t i = 0; i < n_bytes; ++i) { |
78 | SRAM[pos + i] = src[i]; | 80 | SRAM[pos + i] = src[i]; |
79 | } | 81 | } |
@@ -96,7 +98,7 @@ fs_init(void) { | |||
96 | .prev_block = FS_NULL, | 98 | .prev_block = FS_NULL, |
97 | }; | 99 | }; |
98 | for (size_t i = 0; i < FILE_INDEX_NUM; ++i) { | 100 | for (size_t i = 0; i < FILE_INDEX_NUM; ++i) { |
99 | size_t block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * i; | 101 | u16 block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * i; |
100 | _fs_write(&block, block_pos, sizeof(FileBlock)); | 102 | _fs_write(&block, block_pos, sizeof(FileBlock)); |
101 | } | 103 | } |
102 | 104 | ||
@@ -112,12 +114,12 @@ fs_init(void) { | |||
112 | } | 114 | } |
113 | } | 115 | } |
114 | 116 | ||
115 | void inline | 117 | void |
116 | _fs_update_filesystem_header(void) { | 118 | _fs_update_filesystem_header(void) { |
117 | _fs_write(&filesystem, 0, offsetof(FileSystem, files)); | 119 | _fs_write(&filesystem, 0, offsetof(FileSystem, files)); |
118 | }; | 120 | }; |
119 | 121 | ||
120 | void inline | 122 | void |
121 | _fs_update_file_index(u16 index) { | 123 | _fs_update_file_index(u16 index) { |
122 | _fs_write(&filesystem.files[index], | 124 | _fs_write(&filesystem.files[index], |
123 | offsetof(FileSystem, files) + index * sizeof(FileIndex), | 125 | offsetof(FileSystem, files) + index * sizeof(FileIndex), |
@@ -132,7 +134,7 @@ typedef enum { | |||
132 | 134 | ||
133 | typedef struct File { | 135 | typedef struct File { |
134 | u8 index; | 136 | u8 index; |
135 | u16 cur; | 137 | u16 offset; |
136 | OpenMode mode; | 138 | OpenMode mode; |
137 | } File; | 139 | } File; |
138 | 140 | ||
@@ -152,8 +154,8 @@ fs_open_file(char *name, OpenMode mode) { | |||
152 | 154 | ||
153 | // Create a new file if there is space. | 155 | // Create a new file if there is space. |
154 | if (filesystem.num_files < FILE_INDEX_NUM) { | 156 | if (filesystem.num_files < FILE_INDEX_NUM) { |
155 | size_t index = filesystem.num_files++; | 157 | u16 index = filesystem.num_files++; |
156 | size_t k = 0; | 158 | u16 k = 0; |
157 | while(*name) { | 159 | while(*name) { |
158 | filesystem.files[index].name[k++] = *name++; | 160 | filesystem.files[index].name[k++] = *name++; |
159 | } | 161 | } |
@@ -167,6 +169,20 @@ fs_open_file(char *name, OpenMode mode) { | |||
167 | return (File){FS_NULL, 0, mode}; | 169 | return (File){FS_NULL, 0, mode}; |
168 | } | 170 | } |
169 | 171 | ||
172 | u16 | ||
173 | fs_file_size(File *file) { | ||
174 | u16 size = 0; | ||
175 | FileBlock block; | ||
176 | u16 blk_id = filesystem.files[file->index].first_block; | ||
177 | while (blk_id != FS_NULL) { | ||
178 | u16 block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * blk_id; | ||
179 | _fs_read(&block, block_pos, sizeof(FileBlock)); | ||
180 | size += block.size; | ||
181 | blk_id = block.next_block; | ||
182 | } | ||
183 | return size; | ||
184 | } | ||
185 | |||
170 | u8 | 186 | u8 |
171 | _fs_init_new_block(void) { | 187 | _fs_init_new_block(void) { |
172 | // Find free block. | 188 | // Find free block. |
@@ -188,18 +204,18 @@ _fs_init_new_block(void) { | |||
188 | 204 | ||
189 | #include "text.h" | 205 | #include "text.h" |
190 | 206 | ||
191 | // Recursively free blocks starting at block_id. To improve performance, the | 207 | // Recursively free blocks starting at blk_id. To improve performance, the |
192 | // filesystem header is updated in memory but not written to disk. It is | 208 | // filesystem header is updated in memory but not written to disk. It is |
193 | // responsability of the caller to perform the filesystem update. | 209 | // responsability of the caller to perform the filesystem update. |
194 | void | 210 | void |
195 | _fs_free_blocks(u8 block_id) { | 211 | _fs_free_blocks(u8 blk_id) { |
196 | if (block_id == FS_NULL) { | 212 | if (blk_id == FS_NULL) { |
197 | return; | 213 | return; |
198 | } | 214 | } |
199 | 215 | ||
200 | // Read block. | 216 | // Read block. |
201 | FileBlock block; | 217 | FileBlock block; |
202 | size_t block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * block_id; | 218 | u16 block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * blk_id; |
203 | _fs_read(&block, block_pos, sizeof(FileBlock)); | 219 | _fs_read(&block, block_pos, sizeof(FileBlock)); |
204 | 220 | ||
205 | // Update block. | 221 | // Update block. |
@@ -213,34 +229,31 @@ _fs_free_blocks(u8 block_id) { | |||
213 | 229 | ||
214 | // Update dirty and busy blocks. | 230 | // Update dirty and busy blocks. |
215 | filesystem.busy_blocks--; | 231 | filesystem.busy_blocks--; |
216 | filesystem.used_blocks[block_id / 8] &= ~(1 << (block_id % 8)); | 232 | filesystem.used_blocks[blk_id / 8] &= ~(1 << (blk_id % 8)); |
217 | 233 | ||
218 | _fs_free_blocks(next_block); | 234 | _fs_free_blocks(next_block); |
219 | } | 235 | } |
220 | 236 | ||
221 | // Write to block as a new file. | 237 | // Write to block as a new file. |
222 | void | 238 | void |
223 | _fs_write_to_block(u8 *src, size_t n_bytes, u8 block_id, u8 prev_block) { | 239 | _fs_write_to_block(u8 *src, u16 n_bytes, u16 blk_offset, u8 blk_id, u8 prev_blk) { |
224 | // Read initial block. | 240 | // Read initial block. |
225 | FileBlock block; | 241 | FileBlock block; |
226 | size_t block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * block_id; | 242 | u16 block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * blk_id; |
227 | _fs_read(&block, block_pos, sizeof(FileBlock)); | 243 | _fs_read(&block, block_pos, sizeof(FileBlock)); |
228 | u16 block_capacity = (FILE_BLOCK_SIZE - sizeof(FileBlock)); | 244 | u16 block_capacity = FILE_BLOCK_CAPACITY - blk_offset; |
229 | 245 | ||
230 | // Write capacity. | 246 | // Write capacity. |
231 | u16 block_bytes = MIN(block_capacity, n_bytes); | 247 | u16 block_bytes = MIN(block_capacity, n_bytes); |
232 | _fs_write(src, block_pos + sizeof(FileBlock), block_bytes); | 248 | _fs_write(src, block_pos + sizeof(FileBlock) + blk_offset, block_bytes); |
233 | 249 | ||
234 | if (n_bytes > block_capacity) { | 250 | if (n_bytes > block_capacity) { |
235 | if (block.next_block == FS_NULL) { | 251 | if (block.next_block == FS_NULL) { |
236 | // Find new available block and initialize it. | 252 | // Find new available block and initialize it. |
237 | block.next_block = _fs_init_new_block(); | 253 | block.next_block = _fs_init_new_block(); |
238 | } | 254 | } |
239 | _fs_write_to_block( | 255 | _fs_write_to_block(src + block_capacity, n_bytes - block_capacity, 0, |
240 | src + block_capacity, | 256 | block.next_block, blk_id); |
241 | n_bytes - block_capacity, | ||
242 | block.next_block, | ||
243 | block_id); | ||
244 | } else if (block.next_block != FS_NULL){ | 257 | } else if (block.next_block != FS_NULL){ |
245 | // Recursively free unused blocks. | 258 | // Recursively free unused blocks. |
246 | _fs_free_blocks(block.next_block); | 259 | _fs_free_blocks(block.next_block); |
@@ -249,18 +262,18 @@ _fs_write_to_block(u8 *src, size_t n_bytes, u8 block_id, u8 prev_block) { | |||
249 | } | 262 | } |
250 | 263 | ||
251 | // Update block header. | 264 | // Update block header. |
252 | if (prev_block != FS_NULL) { | 265 | if (prev_blk != FS_NULL) { |
253 | block.prev_block = prev_block; | 266 | block.prev_block = prev_blk; |
254 | } | 267 | } |
255 | block.size = block_bytes; | 268 | block.size = block_bytes; |
256 | _fs_write(&block, block_pos, sizeof(FileBlock)); | 269 | _fs_write(&block, block_pos, sizeof(FileBlock)); |
257 | } | 270 | } |
258 | 271 | ||
259 | // void | 272 | // void |
260 | // _fs_append_to_block(u8 *src, size_t n_bytes, u8 block_id, u8 prev_block) { | 273 | // _fs_append_to_block(u8 *src, u16 n_bytes, u8 blk_id, u8 prev_block) { |
261 | // // Read initial block. | 274 | // // Read initial block. |
262 | // FileBlock block; | 275 | // FileBlock block; |
263 | // size_t block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * block_id; | 276 | // size_t block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * blk_id; |
264 | // _fs_read(&block, block_pos, sizeof(FileBlock)); | 277 | // _fs_read(&block, block_pos, sizeof(FileBlock)); |
265 | // u16 block_capacity = (FILE_BLOCK_SIZE - sizeof(FileBlock)) - block.size; | 278 | // u16 block_capacity = (FILE_BLOCK_SIZE - sizeof(FileBlock)) - block.size; |
266 | 279 | ||
@@ -270,7 +283,7 @@ _fs_write_to_block(u8 *src, size_t n_bytes, u8 block_id, u8 prev_block) { | |||
270 | 283 | ||
271 | // // txt_printf("cap: %d\n", block_capacity); | 284 | // // txt_printf("cap: %d\n", block_capacity); |
272 | // // txt_printf("bytes: %d\n", n_bytes); | 285 | // // txt_printf("bytes: %d\n", n_bytes); |
273 | // // txt_printf("id: %d\n", block_id); | 286 | // // txt_printf("id: %d\n", blk_id); |
274 | // if (n_bytes > block_capacity) { | 287 | // if (n_bytes > block_capacity) { |
275 | // if (block.next_block == FS_NULL) { | 288 | // if (block.next_block == FS_NULL) { |
276 | // // Find new available block and initialize it. | 289 | // // Find new available block and initialize it. |
@@ -282,62 +295,83 @@ _fs_write_to_block(u8 *src, size_t n_bytes, u8 block_id, u8 prev_block) { | |||
282 | // src + block_capacity, | 295 | // src + block_capacity, |
283 | // n_bytes - block_capacity, | 296 | // n_bytes - block_capacity, |
284 | // block.next_block, | 297 | // block.next_block, |
285 | // block_id); | 298 | // blk_id); |
286 | // } | 299 | // } |
287 | 300 | ||
288 | // // Update block header. | 301 | // // Update block header. |
289 | // if (prev_block != FS_NULL) { | 302 | // if (prev_block != FS_NULL) { |
290 | // block.prev_block = prev_block; | 303 | // block.prev_block = prev_bloc7f8k; |
291 | // } | 304 | // } |
292 | // block.size += block_bytes; | 305 | // block.size += block_bytes; |
293 | // _fs_write(&block, block_pos, sizeof(FileBlock)); | 306 | // _fs_write(&block, block_pos, sizeof(FileBlock)); |
294 | // } | 307 | // } |
295 | 308 | ||
296 | size_t | 309 | u16 |
297 | fs_write(u8 *src, size_t n_bytes, u16 offset, bool append, File *file) { | 310 | fs_write(u8 *src, u16 n_bytes, File *file) { |
311 | if (file->mode != FS_OPEN_WRITE && file->mode != FS_OPEN_APPEND) { | ||
312 | return 0; | ||
313 | } | ||
314 | |||
298 | FileIndex *file_idx = &filesystem.files[file->index]; | 315 | FileIndex *file_idx = &filesystem.files[file->index]; |
299 | // TODO: Account for offset. | ||
300 | 316 | ||
301 | // If this is a new file. | 317 | u8 blk_id = FS_NULL; |
318 | u16 offset = file->offset; | ||
302 | if (file_idx->first_block == FS_NULL) { | 319 | if (file_idx->first_block == FS_NULL) { |
303 | // Check how many blocks will this write require and if we have enough | 320 | // Check how many blocks will this write requires and if we have enough |
304 | // available. | 321 | // available. |
305 | u16 blocks_required = n_bytes / (FILE_BLOCK_SIZE - sizeof(FileBlock)); | 322 | u16 blocks_required = n_bytes / FILE_BLOCK_CAPACITY; |
306 | u16 blocks_available = FILE_N_BLOCKS - filesystem.busy_blocks; | 323 | u16 blocks_available = FILE_N_BLOCKS - filesystem.busy_blocks; |
307 | if (blocks_required > blocks_available) { | 324 | if (blocks_required > blocks_available) { |
308 | return 0; | 325 | return 0; |
309 | } | 326 | } |
310 | 327 | ||
311 | // Find the first available block. | 328 | // Find the first available block. |
312 | u8 block_id = _fs_init_new_block(); | 329 | blk_id = _fs_init_new_block(); |
313 | file_idx->first_block = block_id; | 330 | file_idx->first_block = blk_id; |
314 | 331 | ||
315 | // Update file index on SRAM. | 332 | // Update file index on SRAM. |
316 | _fs_update_file_index(file->index); | 333 | _fs_update_file_index(file->index); |
317 | } else { | 334 | } else { |
318 | // TODO: Check how many blocks will this write require and if we have | 335 | // Check how many blocks will this write requires and if we have |
319 | // enough available. | 336 | // enough available. |
337 | u16 file_size = fs_file_size(file); | ||
338 | u16 blocks_in_file = file_size / FILE_BLOCK_SIZE; | ||
339 | u16 blocks_available = FILE_N_BLOCKS - filesystem.busy_blocks + blocks_in_file; | ||
340 | u16 blocks_required = (n_bytes + offset) / FILE_BLOCK_CAPACITY; | ||
341 | if (blocks_required > blocks_available) { | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | blk_id = file_idx->first_block; | ||
346 | |||
347 | // If there is an offset find the block index and relative offset. | ||
348 | if (offset >= FILE_BLOCK_CAPACITY) { | ||
349 | u16 n_blocks_offset = offset / FILE_BLOCK_CAPACITY; | ||
350 | for (size_t i = 0; i < n_blocks_offset; ++i) { | ||
351 | FileBlock block; | ||
352 | u16 block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * blk_id; | ||
353 | _fs_read(&block, block_pos, sizeof(FileBlock)); | ||
354 | blk_id = block.next_block; | ||
355 | if (blk_id == FS_NULL) { | ||
356 | return 0; | ||
357 | } | ||
358 | } | ||
359 | offset = offset % FILE_BLOCK_CAPACITY; | ||
360 | } | ||
320 | } | 361 | } |
321 | // txt_printf("id: %d", file_idx->first_block); | ||
322 | 362 | ||
323 | // Write to block. | 363 | // Write to block. |
324 | _fs_write_to_block(src, n_bytes, file_idx->first_block, FS_NULL); | 364 | if (file->mode == FS_OPEN_WRITE) { |
325 | 365 | _fs_write_to_block(src, n_bytes, offset, blk_id, FS_NULL); | |
326 | // // Update file index. | 366 | } else { |
327 | // if (append) { | 367 | // TODO: Append... |
328 | // if (offset + n_bytes > file->size) { | 368 | } |
329 | // file->size = offset + n_bytes; | ||
330 | // } | ||
331 | // } else { | ||
332 | // file->size = offset + n_bytes; | ||
333 | // } | ||
334 | // _fs_write(file, FILE_INDEX_OFFSET + file_index * sizeof(File), sizeof(File)); | ||
335 | 369 | ||
336 | return n_bytes; | 370 | return n_bytes; |
337 | } | 371 | } |
338 | 372 | ||
339 | size_t | 373 | u16 |
340 | fs_read(u8 *dst, size_t n_bytes, u16 offset, File *file) { | 374 | fs_read(u8 *dst, u16 n_bytes, u16 offset, File *file) { |
341 | // File *file = &filesystem.files[file_index]; | 375 | // File *file = &filesystem.files[file_index]; |
342 | 376 | ||
343 | // // Check if the offset is within limits. | 377 | // // Check if the offset is within limits. |