4 * This file is part of BeRTOS.
6 * Bertos is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * As a special exception, you may use this file as part of a free software
21 * library without restriction. Specifically, if other files instantiate
22 * templates or use macros or inline functions from this file, or you compile
23 * this file and link it with other files to produce an executable, this
24 * file does not by itself cause the resulting executable to be covered by
25 * the GNU General Public License. This exception does not however
26 * invalidate any other reasons why the executable file might be covered by
27 * the GNU General Public License.
29 * Copyright 2007, 2008 Develer S.r.l. (http://www.develer.com/)
35 * \author Francesco Sacchi <batt@develer.com>
38 #include <fs/battfs.h>
40 #include <cfg/debug.h>
47 #define FILE_SIZE 32768
49 #define PAGE_COUNT FILE_SIZE / PAGE_SIZE
53 const char test_filename[]="battfs_disk.bin";
55 static uint8_t page_buffer[PAGE_SIZE];
57 static size_t disk_page_read(struct BattFsSuper *d, pgcnt_t page, pgaddr_t addr, void *buf, size_t size)
59 //TRACEMSG("page:%d, addr:%d, size:%d", page, addr, size);
60 FILE *fp = (FILE *)d->disk_ctx;
61 fseek(fp, page * d->page_size + addr, SEEK_SET);
62 return fread(buf, 1, size, fp);
65 static size_t disk_buffer_write(struct BattFsSuper *d, pgaddr_t addr, const void *buf, size_t size)
67 //TRACEMSG("addr:%d, size:%d", addr, size);
68 ASSERT(addr + size <= d->page_size);
69 memcpy(&page_buffer[addr], buf, size);
74 static size_t disk_buffer_read(struct BattFsSuper *d, pgaddr_t addr, void *buf, size_t size)
76 //TRACEMSG("addr:%d, size:%d", addr, size);
77 ASSERT(addr + size <= d->page_size);
78 memcpy(buf, &page_buffer[addr], size);
83 static bool disk_page_load(struct BattFsSuper *d, pgcnt_t page)
85 FILE *fp = (FILE *)d->disk_ctx;
86 //TRACEMSG("page:%d", page);
87 fseek(fp, page * d->page_size, SEEK_SET);
88 return fread(page_buffer, 1, d->page_size, fp) == d->page_size;
91 static bool disk_page_save(struct BattFsSuper *d, pgcnt_t page)
93 FILE *fp = (FILE *)d->disk_ctx;
94 //TRACEMSG("page:%d", page);
95 fseek(fp, page * d->page_size, SEEK_SET);
96 return fwrite(page_buffer, 1, d->page_size, fp) == d->page_size;
99 static bool disk_page_erase(struct BattFsSuper *d, pgcnt_t page)
101 FILE *fp = (FILE *)d->disk_ctx;
102 //TRACEMSG("page:%d", page);
103 fseek(fp, page * d->page_size, SEEK_SET);
105 for (int i = 0; i < d->page_size; i++)
106 if (fputc(0xff, fp) == EOF)
111 static bool disk_close(struct BattFsSuper *d)
113 FILE *fp = (FILE *)d->disk_ctx;
116 return (fclose(fp) != EOF);
119 static bool disk_open(struct BattFsSuper *d)
121 d->read = disk_page_read;
122 d->load = disk_page_load;
123 d->bufferWrite = disk_buffer_write;
124 d->bufferRead = disk_buffer_read;
125 d->save = disk_page_save;
126 d->erase = disk_page_erase;
127 d->close = disk_close;
129 FILE *fp = fopen(test_filename, "r+b");
132 fseek(fp, 0, SEEK_END);
133 d->page_size = PAGE_SIZE;
134 d->page_count = ftell(fp) / d->page_size;
135 d->page_array = malloc(d->page_count * sizeof(pgcnt_t));
136 //TRACEMSG("page_size:%d, page_count:%d\n", d->page_size, d->page_count);
137 return (fp && d->page_array);
140 static void testCheck(BattFsSuper *disk, pgcnt_t *reference)
142 ASSERT(disk_open(disk));
143 ASSERT(battfs_mount(disk));
144 ASSERT(battfs_fsck(disk));
146 for (int i = 0; i < disk->page_count; i++)
148 if (disk->page_array[i] != reference[i])
150 kprintf("Error at addr %d: page_array read", i);
151 for (pgcnt_t i = 0; i < disk->page_count; i++)
155 kprintf("%04d ", disk->page_array[i]);
158 kprintf("Expected:");
159 for (pgcnt_t i = 0; i < disk->page_count; i++)
163 kprintf("%04d ", reference[i]);
171 ASSERT(battfs_fsck(disk));
172 ASSERT(battfs_umount(disk));
175 static void diskNew(BattFsSuper *disk)
177 pgcnt_t ref[PAGE_COUNT];
178 TRACEMSG("1: disk new\n");
180 FILE *fpt = fopen(test_filename, "w+");
182 for (int i = 0; i < FILE_SIZE; i++)
185 for (int i = 0; i < PAGE_COUNT; i++)
188 testCheck(disk, ref);
189 TRACEMSG("1: passed\n");
192 static void disk1File(BattFsSuper *disk)
194 pgcnt_t ref[PAGE_COUNT];
195 TRACEMSG("2: disk full with 1 contiguos file\n");
198 FILE *fp = fopen(test_filename, "w+");
200 for (int i = 0; i < PAGE_COUNT; i++)
202 battfs_writeTestBlock(disk, i, 0, 0, disk->data_size, i);
207 testCheck(disk, ref);
208 TRACEMSG("2: passed\n");
212 static void diskHalfFile(BattFsSuper *disk)
214 pgcnt_t ref[PAGE_COUNT];
215 TRACEMSG("3: disk half full with 1 contiguos file, rest unformatted\n");
218 FILE *fp = fopen(test_filename, "w+");
220 for (int i = 0; i < PAGE_COUNT / 2; i++)
222 battfs_writeTestBlock(disk, i, 0, 0, disk->data_size, i);
225 fseek(fp, FILE_SIZE / 2, SEEK_SET);
226 for (int i = FILE_SIZE / 2; i < FILE_SIZE; i++)
230 for (int i = PAGE_COUNT / 2; i < PAGE_COUNT; i++)
236 testCheck(disk, ref);
237 TRACEMSG("3: passed\n");
241 static void oldSeq1(BattFsSuper *disk)
244 TRACEMSG("6: 1 file with 1 old seq num, 1 free block\n");
247 FILE *fp = fopen(test_filename, "w+");
248 // page, inode, seq, fill, pgoff
249 battfs_writeTestBlock(disk, 0, 0, 0, disk->data_size, 0);
250 battfs_writeTestBlock(disk, 1, 0, 0, disk->data_size, 1);
251 battfs_writeTestBlock(disk, 2, 0, 1, disk->data_size, 1);
252 disk->erase(disk, 3);
261 testCheck(disk, ref);
262 TRACEMSG("6: passed\n");
265 static void oldSeq2(BattFsSuper *disk)
268 TRACEMSG("7: 1 file with 1 old seq num, 1 free block\n");
271 FILE *fp = fopen(test_filename, "w+");
272 // page, inode, seq, fill, pgoff
273 battfs_writeTestBlock(disk, 0, 0, 0, disk->data_size, 0);
274 battfs_writeTestBlock(disk, 1, 0, 1, disk->data_size, 1);
275 battfs_writeTestBlock(disk, 2, 0, 0, disk->data_size, 1);
276 disk->erase(disk, 3);
284 testCheck(disk, ref);
285 TRACEMSG("7: passed\n");
288 static void oldSeq3(BattFsSuper *disk)
291 TRACEMSG("8: 1 file with 1 old seq num, 1 free block\n");
294 FILE *fp = fopen(test_filename, "w+");
296 // page, inode, seq, fill, pgoff
297 disk->erase(disk, 0);
298 battfs_writeTestBlock(disk, 1, 0, 0, disk->data_size, 0);
299 battfs_writeTestBlock(disk, 2, 0, 1, disk->data_size, 1);
300 battfs_writeTestBlock(disk, 3, 0, 0, disk->data_size, 1);
309 testCheck(disk, ref);
310 TRACEMSG("8: passed\n");
313 static void oldSeq2File(BattFsSuper *disk)
316 TRACEMSG("9: 2 file with old seq num, 2 free block\n");
319 FILE *fp = fopen(test_filename, "w+");
321 // page, inode, seq, fill, pgoff
322 disk->erase(disk, 0);
323 battfs_writeTestBlock(disk, 1, 0, 0, disk->data_size, 0);
324 battfs_writeTestBlock(disk, 2, 0, 3, disk->data_size, 1);
325 battfs_writeTestBlock(disk, 3, 0, 0, disk->data_size, 1);
326 disk->erase(disk, 4);
327 battfs_writeTestBlock(disk, 5, 4, 0, disk->data_size, 0);
328 battfs_writeTestBlock(disk, 6, 4, 1, disk->data_size, 1);
329 battfs_writeTestBlock(disk, 7, 4, 0, disk->data_size, 1);
342 testCheck(disk, ref);
343 TRACEMSG("9: passed\n");
346 static void openFile(BattFsSuper *disk)
350 TRACEMSG("10: open file test, inode 0 and inode 4\n");
352 FILE *fp = fopen(test_filename, "w+");
354 int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
357 inode_t INEXISTENT_INODE = 123;
358 unsigned int MODE = 0;
360 // page, inode, seq, fill, pgoff
361 disk->erase(disk, 0);
362 battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
363 battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
364 battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
365 disk->erase(disk, 4);
366 battfs_writeTestBlock(disk, 5, INODE2, 0, PAGE_FILL, 0);
367 battfs_writeTestBlock(disk, 6, INODE2, 1, PAGE_FILL, 1);
368 battfs_writeTestBlock(disk, 7, INODE2, 0, PAGE_FILL, 1);
372 ASSERT(disk_open(disk));
373 ASSERT(battfs_mount(disk));
374 ASSERT(battfs_fsck(disk));
375 ASSERT(!battfs_fileExists(disk, INEXISTENT_INODE));
377 ASSERT(battfs_fileExists(disk, INODE));
378 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
379 ASSERT(fd1.fd.size == PAGE_FILL * 2);
380 ASSERT(fd1.fd.seek_pos == 0);
381 ASSERT(fd1.mode == MODE);
382 ASSERT(fd1.inode == INODE);
383 ASSERT(fd1.start == &disk->page_array[0]);
384 ASSERT(fd1.disk == disk);
385 ASSERT(LIST_HEAD(&disk->file_opened_list) == &fd1.link);
387 ASSERT(kfile_reopen(&fd1.fd) == &fd1.fd);
388 ASSERT(fd1.fd.size == PAGE_FILL * 2);
389 ASSERT(fd1.fd.seek_pos == 0);
390 ASSERT(fd1.mode == MODE);
391 ASSERT(fd1.inode == INODE);
392 ASSERT(fd1.start == &disk->page_array[0]);
393 ASSERT(fd1.disk == disk);
394 ASSERT(LIST_HEAD(&disk->file_opened_list) == &fd1.link);
396 ASSERT(battfs_fileExists(disk, INODE2));
397 ASSERT(battfs_fileopen(disk, &fd2, INODE2, MODE));
398 ASSERT(fd2.fd.size == PAGE_FILL * 2);
399 ASSERT(fd2.fd.seek_pos == 0);
400 ASSERT(fd2.mode == MODE);
401 ASSERT(fd2.inode == INODE2);
402 ASSERT(fd2.start == &disk->page_array[2]);
403 ASSERT(fd2.disk == disk);
404 ASSERT(LIST_HEAD(&disk->file_opened_list)->succ == &fd2.link);
406 ASSERT(kfile_close(&fd1.fd) == 0);
407 ASSERT(kfile_error(&fd1.fd) == 0);
408 ASSERT(kfile_close(&fd2.fd) == 0);
409 ASSERT(kfile_error(&fd2.fd) == 0);
410 ASSERT(LIST_EMPTY(&disk->file_opened_list));
411 ASSERT(battfs_fsck(disk));
412 ASSERT(battfs_umount(disk));
414 TRACEMSG("10: passed\n");
417 static void readFile(BattFsSuper *disk)
422 TRACEMSG("11: read file test\n");
424 FILE *fp = fopen(test_filename, "w+");
426 unsigned int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
429 unsigned int MODE = 0;
431 disk->erase(disk, 0);
432 battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
433 battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
434 battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
435 disk->erase(disk, 4);
436 battfs_writeTestBlock(disk, 5, INODE2, 0, PAGE_FILL, 0);
437 battfs_writeTestBlock(disk, 6, INODE2, 1, PAGE_FILL, 1);
438 battfs_writeTestBlock(disk, 7, INODE2, 0, PAGE_FILL, 1);
442 ASSERT(disk_open(disk));
443 ASSERT(battfs_mount(disk));
444 ASSERT(battfs_fsck(disk));
445 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
446 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
447 ASSERT(fd1.fd.seek_pos == sizeof(buf));
448 for (size_t i = 0; i < sizeof(buf); i++)
449 ASSERT(buf[i] == 0xff);
451 ASSERT(kfile_close(&fd1.fd) == 0);
452 ASSERT(kfile_error(&fd1.fd) == 0);
453 ASSERT(battfs_fsck(disk));
454 ASSERT(battfs_umount(disk));
456 TRACEMSG("11: passed\n");
459 static void readAcross(BattFsSuper *disk)
463 TRACEMSG("12: read file test across page boundary and seek test\n");
465 FILE *fp = fopen(test_filename, "w+");
467 const unsigned int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
469 unsigned int MODE = 0;
470 uint8_t buf[PAGE_FILL + BATTFS_HEADER_LEN / 2];
472 disk->erase(disk, 0);
473 battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
474 battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
475 battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
476 disk->erase(disk, 4);
477 battfs_writeTestBlock(disk, 5, INODE, 0, PAGE_FILL, 2);
478 battfs_writeTestBlock(disk, 6, INODE, 1, PAGE_FILL, 3);
479 battfs_writeTestBlock(disk, 7, INODE, 0, PAGE_FILL, 3);
483 ASSERT(disk_open(disk));
484 ASSERT(battfs_mount(disk));
485 ASSERT(battfs_fsck(disk));
486 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
488 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
489 ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf));
490 for (size_t i = 0; i < sizeof(buf); i++)
491 ASSERT(buf[i] == 0xff);
493 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
494 ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf) * 2);
495 for (size_t i = 0; i < sizeof(buf); i++)
496 ASSERT(buf[i] == 0xff);
498 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
499 ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf) * 3);
500 for (size_t i = 0; i < sizeof(buf); i++)
501 ASSERT(buf[i] == 0xff);
503 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == PAGE_FILL * 4 - sizeof(buf) * 3);
504 ASSERT(fd1.fd.seek_pos == (kfile_off_t)fd1.fd.size);
505 for (size_t i = 0; i < PAGE_FILL * 4 - sizeof(buf) * 3; i++)
506 ASSERT(buf[i] == 0xff);
508 ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
509 ASSERT(fd1.fd.seek_pos == 0);
511 ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_END) == (kfile_off_t)fd1.fd.size);
512 ASSERT(fd1.fd.seek_pos = (kfile_off_t)fd1.fd.size);
514 ASSERT(kfile_close(&fd1.fd) == 0);
515 ASSERT(kfile_error(&fd1.fd) == 0);
516 ASSERT(battfs_fsck(disk));
517 ASSERT(battfs_umount(disk));
519 TRACEMSG("12: passed\n");
523 static void writeFile(BattFsSuper *disk)
526 uint8_t buf[PAGE_SIZE - BATTFS_HEADER_LEN];
528 TRACEMSG("13: write file test\n");
530 FILE *fp = fopen(test_filename, "w+");
532 unsigned int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
535 unsigned int MODE = 0;
537 disk->erase(disk, 0);
538 battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
539 battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
540 battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
541 disk->erase(disk, 4);
542 battfs_writeTestBlock(disk, 5, INODE2, 0, PAGE_FILL, 0);
543 battfs_writeTestBlock(disk, 6, INODE2, 1, PAGE_FILL, 1);
544 battfs_writeTestBlock(disk, 7, INODE2, 0, PAGE_FILL, 1);
548 for (size_t i = 0; i < sizeof(buf); i++)
551 ASSERT(disk_open(disk));
552 ASSERT(battfs_mount(disk));
553 ASSERT(battfs_fsck(disk));
554 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
555 ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
556 ASSERT(fd1.fd.seek_pos == sizeof(buf));
557 ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
558 ASSERT(fd1.fd.seek_pos == 0);
560 memset(buf, 0, sizeof(buf));
561 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
562 for (size_t i = 0; i < sizeof(buf); i++)
565 ASSERT(kfile_close(&fd1.fd) == 0);
566 ASSERT(kfile_error(&fd1.fd) == 0);
567 ASSERT(battfs_fsck(disk));
568 ASSERT(battfs_umount(disk));
570 TRACEMSG("13: passed\n");
573 static void writeAcross(BattFsSuper *disk)
577 TRACEMSG("14: write file test across page boundary and seek test\n");
579 FILE *fp = fopen(test_filename, "w+");
581 const unsigned int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
583 unsigned int MODE = 0;
584 uint8_t buf[PAGE_FILL + BATTFS_HEADER_LEN / 2];
586 disk->erase(disk, 0);
587 battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
588 battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
589 battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
590 disk->erase(disk, 4);
591 battfs_writeTestBlock(disk, 5, INODE, 0, PAGE_FILL, 2);
592 battfs_writeTestBlock(disk, 6, INODE, 1, PAGE_FILL, 3);
593 battfs_writeTestBlock(disk, 7, INODE, 0, PAGE_FILL, 3);
597 ASSERT(disk_open(disk));
598 ASSERT(battfs_mount(disk));
599 ASSERT(battfs_fsck(disk));
600 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
603 for (size_t i = 0; i < sizeof(buf); i++)
605 ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
606 ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf));
608 for (size_t i = 0; i < sizeof(buf); i++)
610 ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
611 ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf) * 2);
613 for (size_t i = 0; i < sizeof(buf); i++)
615 ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
616 ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf) * 3);
618 ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
619 ASSERT(fd1.fd.seek_pos == 0);
622 memset(buf, 0, sizeof(buf));
623 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
624 for (size_t i = 0; i < sizeof(buf); i++)
625 ASSERT(buf[i] == val++);
627 memset(buf, 0, sizeof(buf));
628 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
629 for (size_t i = 0; i < sizeof(buf); i++)
630 ASSERT(buf[i] == val++);
632 memset(buf, 0, sizeof(buf));
633 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
634 for (size_t i = 0; i < sizeof(buf); i++)
635 ASSERT(buf[i] == val++);
637 ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf) * 3);
639 ASSERT(kfile_close(&fd1.fd) == 0);
640 ASSERT(kfile_error(&fd1.fd) == 0);
641 ASSERT(battfs_fsck(disk));
642 ASSERT(battfs_umount(disk));
644 TRACEMSG("14: passed\n");
647 static void createFile(BattFsSuper *disk)
649 TRACEMSG("15: file creation on new disk\n");
651 FILE *fpt = fopen(test_filename, "w+");
653 for (int i = 0; i < FILE_SIZE; i++)
659 unsigned int MODE = BATTFS_CREATE;
661 ASSERT(disk_open(disk));
662 ASSERT(battfs_mount(disk));
663 ASSERT(battfs_fsck(disk));
664 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
665 for (int i = 0; i < FILE_SIZE / 2; i++)
666 ASSERT(kfile_putc(i, &fd1.fd) != EOF);
668 ASSERT(fd1.fd.seek_pos == FILE_SIZE / 2);
669 ASSERT(fd1.fd.size == FILE_SIZE / 2);
670 ASSERT(kfile_close(&fd1.fd) == 0);
671 ASSERT(kfile_error(&fd1.fd) == 0);
672 ASSERT(battfs_fsck(disk));
673 ASSERT(battfs_umount(disk));
675 ASSERT(disk_open(disk));
676 ASSERT(battfs_mount(disk));
677 ASSERT(battfs_fsck(disk));
678 ASSERT(battfs_fileopen(disk, &fd1, INODE, 0));
679 ASSERT(fd1.fd.size == FILE_SIZE / 2);
680 ASSERT(fd1.fd.seek_pos == 0);
682 uint8_t buf[FILE_SIZE / 2];
683 memset(buf, 0, sizeof(buf));
684 ASSERT(kfile_read(&fd1.fd, buf, FILE_SIZE / 2) == FILE_SIZE / 2);
686 for (int i = 0; i < FILE_SIZE / 2; i++)
687 ASSERT(buf[i] == (i & 0xff));
689 ASSERT(fd1.fd.seek_pos == FILE_SIZE / 2);
690 ASSERT(kfile_close(&fd1.fd) == 0);
691 ASSERT(kfile_error(&fd1.fd) == 0);
692 ASSERT(battfs_fsck(disk));
693 ASSERT(battfs_umount(disk));
696 TRACEMSG("15: passed\n");
699 static void multipleWrite(BattFsSuper *disk)
701 TRACEMSG("16: multiple write on file\n");
703 FILE *fpt = fopen(test_filename, "w+");
705 for (int i = 0; i < FILE_SIZE; i++)
711 unsigned int MODE = BATTFS_CREATE;
714 ASSERT(disk_open(disk));
715 ASSERT(battfs_mount(disk));
716 ASSERT(battfs_fsck(disk));
717 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
720 for (j = 1; j < 1013; j++)
722 for (unsigned i = 0; i < sizeof(buf); i++)
725 ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
726 ASSERT(fd1.fd.seek_pos == sizeof(buf));
727 ASSERT(fd1.fd.size == sizeof(buf));
728 ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
729 memset(buf, 0, sizeof(buf));
730 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
731 ASSERT(fd1.fd.seek_pos == sizeof(buf));
732 for (unsigned i = 0; i < sizeof(buf); i++)
733 ASSERT(buf[i] == ((j+i) & 0xff));
734 ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
735 ASSERT(disk->free_bytes == disk->disk_size - sizeof(buf));
737 ASSERT(kfile_close(&fd1.fd) == 0);
738 ASSERT(kfile_error(&fd1.fd) == 0);
739 ASSERT(battfs_fsck(disk));
740 ASSERT(battfs_umount(disk));
742 ASSERT(disk_open(disk));
743 ASSERT(battfs_mount(disk));
744 ASSERT(battfs_fsck(disk));
745 ASSERT(disk->free_bytes == disk->disk_size - sizeof(buf));
746 ASSERT(battfs_fileopen(disk, &fd1, INODE, 0));
747 ASSERT(fd1.fd.size == sizeof(buf));
748 memset(buf, 0, sizeof(buf));
749 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
750 for (unsigned i = 0; i < sizeof(buf); i++)
751 ASSERT(buf[i] == ((j-1+i) & 0xff));
752 ASSERT(kfile_close(&fd1.fd) == 0);
753 ASSERT(kfile_error(&fd1.fd) == 0);
754 ASSERT(battfs_fsck(disk));
755 ASSERT(battfs_umount(disk));
758 TRACEMSG("16: passed\n");
761 static void increaseFile(BattFsSuper *disk)
763 TRACEMSG("17: increasing dimension of a file with multiple open files.\n");
765 FILE *fpt = fopen(test_filename, "w+");
767 for (int i = 0; i < FILE_SIZE / 10; i++)
772 inode_t INODE1 = 1, INODE2 = 2;
773 unsigned int MODE = BATTFS_CREATE;
776 ASSERT(disk_open(disk));
777 ASSERT(battfs_mount(disk));
778 ASSERT(battfs_fsck(disk));
779 ASSERT(battfs_fileopen(disk, &fd1, INODE1, MODE));
780 ASSERT(battfs_fileopen(disk, &fd2, INODE2, MODE));
781 for (unsigned i = 0; i < sizeof(buf); i++)
782 ASSERT(kfile_putc(i, &fd2.fd) != EOF);
783 ASSERT(kfile_seek(&fd2.fd, 0, KSM_SEEK_SET) == 0);
784 memset(buf, 0, sizeof(buf));
785 ASSERT(kfile_read(&fd2.fd, buf, sizeof(buf)) == sizeof(buf));
787 for (unsigned i = 0; i < sizeof(buf); i++)
788 ASSERT(buf[i] == (i & 0xff));
789 ASSERT(kfile_seek(&fd2.fd, 0, KSM_SEEK_SET) == 0);
791 for (unsigned i = 0; i < sizeof(buf); i++)
792 ASSERT(kfile_putc(i, &fd1.fd) != EOF);
794 memset(buf, 0, sizeof(buf));
795 ASSERT(kfile_read(&fd2.fd, buf, sizeof(buf)) == sizeof(buf));
797 for (unsigned i = 0; i < sizeof(buf); i++)
798 ASSERT(buf[i] == (i & 0xff));
800 ASSERT(kfile_close(&fd1.fd) == 0);
801 ASSERT(kfile_error(&fd1.fd) == 0);
802 ASSERT(kfile_close(&fd2.fd) == 0);
803 ASSERT(kfile_error(&fd2.fd) == 0);
804 ASSERT(battfs_fsck(disk));
805 ASSERT(battfs_umount(disk));
807 TRACEMSG("17: passed\n");
810 static void readEOF(BattFsSuper *disk)
815 TRACEMSG("18: reading over EOF test\n");
817 FILE *fp = fopen(test_filename, "w+");
819 unsigned int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
822 unsigned int MODE = 0;
824 disk->erase(disk, 0);
825 battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
826 battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
827 battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
828 disk->erase(disk, 4);
829 battfs_writeTestBlock(disk, 5, INODE2, 0, PAGE_FILL, 0);
830 battfs_writeTestBlock(disk, 6, INODE2, 1, PAGE_FILL, 1);
831 battfs_writeTestBlock(disk, 7, INODE2, 0, PAGE_FILL, 1);
835 ASSERT(disk_open(disk));
836 ASSERT(battfs_mount(disk));
837 ASSERT(battfs_fsck(disk));
838 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
839 ASSERT(kfile_seek(&fd1.fd, fd1.fd.size + 10, SEEK_SET) == fd1.fd.size + 10);
840 ASSERT(fd1.fd.seek_pos == fd1.fd.size + 10);
841 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == 0);
843 ASSERT(kfile_close(&fd1.fd) == 0);
844 ASSERT(kfile_error(&fd1.fd) == 0);
845 ASSERT(battfs_fsck(disk));
846 ASSERT(battfs_umount(disk));
848 TRACEMSG("18: passed\n");
851 static void writeEOF(BattFsSuper *disk)
853 TRACEMSG("19: writing over EOF test\n");
855 FILE *fpt = fopen(test_filename, "w+");
857 for (int i = 0; i < FILE_SIZE / 5; i++)
863 unsigned int MODE = BATTFS_CREATE;
864 uint8_t buf[FILE_SIZE / 13];
866 for (int i = 0; i < 2; i++)
869 ASSERT(disk_open(disk));
870 ASSERT(battfs_mount(disk));
871 ASSERT(battfs_fsck(disk));
872 disk_size_t prev_free = disk->free_bytes;
873 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
874 ASSERT(fd1.fd.size == 0);
876 ASSERT(kfile_seek(&fd1.fd, 2, KSM_SEEK_END) == 2);
877 ASSERT(kfile_write(&fd1.fd, buf, 2));
878 ASSERT(fd1.fd.seek_pos == 4);
879 ASSERT(fd1.fd.size == 4);
880 ASSERT(disk->free_bytes == prev_free - 4);
881 ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
883 ASSERT(kfile_read(&fd1.fd, buf, 2) == 2);
884 for (int i = 0; i < 2; i++)
888 ASSERT(kfile_read(&fd1.fd, buf, 2) == 2);
889 for (int i = 0; i < 2; i++)
890 ASSERT(buf[i] == (i & 0xff));
892 ASSERT(kfile_seek(&fd1.fd, sizeof(buf), KSM_SEEK_END) == sizeof(buf) + 4);
893 for (unsigned i = 0; i < sizeof(buf); i++)
895 ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)));
896 ASSERT(fd1.fd.seek_pos == sizeof(buf) * 2 + 4);
897 ASSERT(fd1.fd.size == sizeof(buf) * 2 + 4);
898 ASSERT(disk->free_bytes == prev_free - sizeof(buf) * 2 - 4);
900 ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
903 ASSERT(kfile_read(&fd1.fd, buf, 2) == 2);
904 ASSERT(fd1.fd.seek_pos == 2);
905 for (int i = 0; i < 2; i++)
909 ASSERT(kfile_read(&fd1.fd, buf, 2) == 2);
910 ASSERT(fd1.fd.seek_pos == 4);
911 for (int i = 0; i < 2; i++)
912 ASSERT(buf[i] == (i & 0xff));
915 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
916 ASSERT(fd1.fd.seek_pos == sizeof(buf) + 4);
917 for (unsigned i = 0; i < sizeof(buf); i++)
920 memset(buf, 0, sizeof(buf));
921 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
922 for (unsigned i = 0; i < sizeof(buf); i++)
923 ASSERT(buf[i] == (i & 0xff));
925 ASSERT(kfile_close(&fd1.fd) == 0);
926 ASSERT(kfile_error(&fd1.fd) == 0);
927 ASSERT(battfs_fsck(disk));
928 ASSERT(battfs_umount(disk));
930 TRACEMSG("19: passed\n");
934 static void endOfSpace(BattFsSuper *disk)
936 TRACEMSG("20: what happens when disk space is over?\n");
938 uint8_t buf[(PAGE_SIZE - BATTFS_HEADER_LEN) * 5];
940 FILE *fp = fopen(test_filename, "w+");
942 unsigned int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
944 unsigned int MODE = BATTFS_CREATE;
946 disk->erase(disk, 0);
947 disk->erase(disk, 1);
948 disk->erase(disk, 2);
949 disk->erase(disk, 3);
952 ASSERT(disk_open(disk));
953 ASSERT(battfs_mount(disk));
954 ASSERT(battfs_fsck(disk));
955 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
956 ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)) == PAGE_FILL * 4);
957 ASSERT(fd1.fd.size == (kfile_off_t)(PAGE_FILL * 4));
958 ASSERT(fd1.fd.seek_pos == (kfile_off_t)(PAGE_FILL * 4));
959 ASSERT(disk->free_bytes == 0);
961 ASSERT(kfile_close(&fd1.fd) == 0);
962 ASSERT(kfile_error(&fd1.fd) == BATTFS_DISK_GETNEWPAGE_ERR);
963 ASSERT(battfs_fsck(disk));
964 ASSERT(battfs_umount(disk));
966 TRACEMSG("20: passed\n");
970 static void multipleFilesRW(BattFsSuper *disk)
972 TRACEMSG("21: multiple files read/write test\n");
974 FILE *fpt = fopen(test_filename, "w+");
976 for (int i = 0; i < FILE_SIZE; i++)
982 unsigned int MODE = BATTFS_CREATE;
983 uint32_t buf[FILE_SIZE / (4 * N_FILES * sizeof(uint32_t))];
985 ASSERT(disk_open(disk));
986 ASSERT(battfs_mount(disk));
987 ASSERT(battfs_fsck(disk));
988 for (inode_t i = 0; i < N_FILES; i++)
989 ASSERT(battfs_fileopen(disk, &fd[i], i, MODE));
991 for (int i = N_FILES - 1; i >= 0; i--)
993 for (uint32_t j = 0; j < countof(buf); j++)
996 ASSERT(kfile_write(&fd[i].fd, buf, sizeof(buf)) == sizeof(buf));
997 ASSERT(fd[i].fd.size == sizeof(buf));
998 ASSERT(fd[i].fd.seek_pos == sizeof(buf));
999 ASSERT(kfile_seek(&fd[i].fd, 0, SEEK_SET) == 0);
1002 for (inode_t i = 0; i < N_FILES; i++)
1004 memset(buf, 0, sizeof(buf));
1005 ASSERT(kfile_read(&fd[i].fd, buf, sizeof(buf)) == sizeof(buf));
1007 for (uint32_t j = 0; j < countof(buf); j++)
1008 ASSERT(buf[j] == j+i);
1010 ASSERT(fd[i].fd.size == sizeof(buf));
1011 ASSERT(fd[i].fd.seek_pos == sizeof(buf));
1012 ASSERT(kfile_seek(&fd[i].fd, 0, SEEK_SET) == 0);
1015 for (inode_t i = 0; i < N_FILES; i++)
1017 ASSERT(kfile_close(&fd[i].fd) == 0);
1018 ASSERT(kfile_error(&fd[i].fd) == 0);
1021 ASSERT(battfs_fsck(disk));
1022 ASSERT(battfs_umount(disk));
1024 ASSERT(disk_open(disk));
1025 ASSERT(battfs_mount(disk));
1026 ASSERT(battfs_fsck(disk));
1028 for (inode_t i = 0; i < N_FILES; i++)
1029 ASSERT(battfs_fileopen(disk, &fd[i], i, 0));
1031 for (inode_t i = 0; i < N_FILES; i++)
1033 memset(buf, 0, sizeof(buf));
1034 ASSERT(kfile_read(&fd[i].fd, buf, sizeof(buf)) == sizeof(buf));
1036 for (uint32_t j = 0; j < countof(buf); j++)
1037 ASSERT(buf[j] == j+i);
1039 ASSERT(fd[i].fd.size == sizeof(buf));
1040 ASSERT(fd[i].fd.seek_pos == sizeof(buf));
1041 ASSERT(kfile_seek(&fd[i].fd, 0, SEEK_SET) == 0);
1044 for (inode_t i = 0; i < N_FILES; i++)
1046 ASSERT(kfile_close(&fd[i].fd) == 0);
1047 ASSERT(kfile_error(&fd[i].fd) == 0);
1050 ASSERT(battfs_umount(disk));
1051 TRACEMSG("21: passed\n");
1055 static void openAllFiles(BattFsSuper *disk)
1057 TRACEMSG("22: try to open a lot of files\n");
1059 FILE *fpt = fopen(test_filename, "w+");
1061 for (int i = 0; i < FILE_SIZE; i++)
1065 BattFs fd[BATTFS_MAX_FILES];
1066 unsigned int MODE = BATTFS_CREATE;
1068 ASSERT(disk_open(disk));
1069 ASSERT(battfs_mount(disk));
1070 ASSERT(battfs_fsck(disk));
1071 for (unsigned i = 0; i < countof(fd); i++)
1072 ASSERT(battfs_fileopen(disk, &fd[i], i, MODE));
1074 ASSERT(battfs_fsck(disk));
1076 for (unsigned i = 0; i < countof(fd); i++)
1078 ASSERT(kfile_close(&fd[i].fd) == 0);
1079 ASSERT(kfile_error(&fd[i].fd) == 0);
1082 ASSERT(battfs_fsck(disk));
1083 ASSERT(battfs_umount(disk));
1085 ASSERT(disk_open(disk));
1086 ASSERT(battfs_mount(disk));
1087 ASSERT(battfs_fsck(disk));
1090 for (unsigned i = 0; i < countof(fd); i++)
1091 ASSERT(battfs_fileopen(disk, &fd[i], i, MODE));
1093 ASSERT(battfs_fsck(disk));
1095 for (unsigned i = 0; i < countof(fd); i++)
1097 ASSERT(kfile_close(&fd[i].fd) == 0);
1098 ASSERT(kfile_error(&fd[i].fd) == 0);
1101 ASSERT(battfs_fsck(disk));
1102 ASSERT(battfs_umount(disk));
1103 TRACEMSG("22: passed\n");
1107 int battfs_testRun(void)
1113 diskHalfFile(&disk);
1124 multipleWrite(&disk);
1125 increaseFile(&disk);
1129 multipleFilesRW(&disk);
1130 openAllFiles(&disk);
1132 kprintf("All tests passed!\n");
1137 int battfs_testSetup(void)
1142 int battfs_testTearDown(void)