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]);
170 ASSERT(battfs_fsck(disk));
174 static void diskNew(BattFsSuper *disk)
176 pgcnt_t ref[PAGE_COUNT];
177 TRACEMSG("1: disk new\n");
179 FILE *fpt = fopen(test_filename, "w+");
181 for (int i = 0; i < FILE_SIZE; i++)
184 for (int i = 0; i < PAGE_COUNT; i++)
187 testCheck(disk, ref);
188 TRACEMSG("1: passed\n");
191 static void disk1File(BattFsSuper *disk)
193 pgcnt_t ref[PAGE_COUNT];
194 TRACEMSG("2: disk full with 1 contiguos file\n");
197 FILE *fp = fopen(test_filename, "w+");
199 for (int i = 0; i < PAGE_COUNT; i++)
201 battfs_writeTestBlock(disk, i, 0, 0, disk->data_size, i);
206 testCheck(disk, ref);
207 TRACEMSG("2: passed\n");
211 static void diskHalfFile(BattFsSuper *disk)
213 pgcnt_t ref[PAGE_COUNT];
214 TRACEMSG("3: disk half full with 1 contiguos file, rest unformatted\n");
217 FILE *fp = fopen(test_filename, "w+");
219 for (int i = 0; i < PAGE_COUNT / 2; i++)
221 battfs_writeTestBlock(disk, i, 0, 0, disk->data_size, i);
224 fseek(fp, FILE_SIZE / 2, SEEK_SET);
225 for (int i = FILE_SIZE / 2; i < FILE_SIZE; i++)
229 for (int i = PAGE_COUNT / 2; i < PAGE_COUNT; i++)
235 testCheck(disk, ref);
236 TRACEMSG("3: passed\n");
240 static void oldSeq1(BattFsSuper *disk)
243 TRACEMSG("6: 1 file with 1 old seq num, 1 free block\n");
246 FILE *fp = fopen(test_filename, "w+");
247 // page, inode, seq, fill, pgoff
248 battfs_writeTestBlock(disk, 0, 0, 0, disk->data_size, 0);
249 battfs_writeTestBlock(disk, 1, 0, 0, disk->data_size, 1);
250 battfs_writeTestBlock(disk, 2, 0, 1, disk->data_size, 1);
251 disk->erase(disk, 3);
260 testCheck(disk, ref);
261 TRACEMSG("6: passed\n");
264 static void oldSeq2(BattFsSuper *disk)
267 TRACEMSG("7: 1 file with 1 old seq num, 1 free block\n");
270 FILE *fp = fopen(test_filename, "w+");
271 // page, inode, seq, fill, pgoff
272 battfs_writeTestBlock(disk, 0, 0, 0, disk->data_size, 0);
273 battfs_writeTestBlock(disk, 1, 0, 1, disk->data_size, 1);
274 battfs_writeTestBlock(disk, 2, 0, 0, disk->data_size, 1);
275 disk->erase(disk, 3);
283 testCheck(disk, ref);
284 TRACEMSG("7: passed\n");
287 static void oldSeq3(BattFsSuper *disk)
290 TRACEMSG("8: 1 file with 1 old seq num, 1 free block\n");
293 FILE *fp = fopen(test_filename, "w+");
295 // page, inode, seq, fill, pgoff
296 disk->erase(disk, 0);
297 battfs_writeTestBlock(disk, 1, 0, 0, disk->data_size, 0);
298 battfs_writeTestBlock(disk, 2, 0, 1, disk->data_size, 1);
299 battfs_writeTestBlock(disk, 3, 0, 0, disk->data_size, 1);
308 testCheck(disk, ref);
309 TRACEMSG("8: passed\n");
312 static void oldSeq2File(BattFsSuper *disk)
315 TRACEMSG("9: 2 file with old seq num, 2 free block\n");
318 FILE *fp = fopen(test_filename, "w+");
320 // page, inode, seq, fill, pgoff
321 disk->erase(disk, 0);
322 battfs_writeTestBlock(disk, 1, 0, 0, disk->data_size, 0);
323 battfs_writeTestBlock(disk, 2, 0, 3, disk->data_size, 1);
324 battfs_writeTestBlock(disk, 3, 0, 0, disk->data_size, 1);
325 disk->erase(disk, 4);
326 battfs_writeTestBlock(disk, 5, 4, 0, disk->data_size, 0);
327 battfs_writeTestBlock(disk, 6, 4, 1, disk->data_size, 1);
328 battfs_writeTestBlock(disk, 7, 4, 0, disk->data_size, 1);
341 testCheck(disk, ref);
342 TRACEMSG("9: passed\n");
345 static void openFile(BattFsSuper *disk)
349 TRACEMSG("10: open file test, inode 0 and inode 4\n");
351 FILE *fp = fopen(test_filename, "w+");
353 int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
356 inode_t INEXISTENT_INODE = 123;
357 unsigned int MODE = 0;
359 // page, inode, seq, fill, pgoff
360 disk->erase(disk, 0);
361 battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
362 battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
363 battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
364 disk->erase(disk, 4);
365 battfs_writeTestBlock(disk, 5, INODE2, 0, PAGE_FILL, 0);
366 battfs_writeTestBlock(disk, 6, INODE2, 1, PAGE_FILL, 1);
367 battfs_writeTestBlock(disk, 7, INODE2, 0, PAGE_FILL, 1);
371 ASSERT(disk_open(disk));
372 ASSERT(battfs_mount(disk));
373 ASSERT(battfs_fsck(disk));
374 ASSERT(!battfs_fileExists(disk, INEXISTENT_INODE));
376 ASSERT(battfs_fileExists(disk, INODE));
377 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
378 ASSERT(fd1.fd.size == PAGE_FILL * 2);
379 ASSERT(fd1.fd.seek_pos == 0);
380 ASSERT(fd1.mode == MODE);
381 ASSERT(fd1.inode == INODE);
382 ASSERT(fd1.start == &disk->page_array[0]);
383 ASSERT(fd1.disk == disk);
384 ASSERT(LIST_HEAD(&disk->file_opened_list) == &fd1.link);
386 ASSERT(kfile_reopen(&fd1.fd) == &fd1.fd);
387 ASSERT(fd1.fd.size == PAGE_FILL * 2);
388 ASSERT(fd1.fd.seek_pos == 0);
389 ASSERT(fd1.mode == MODE);
390 ASSERT(fd1.inode == INODE);
391 ASSERT(fd1.start == &disk->page_array[0]);
392 ASSERT(fd1.disk == disk);
393 ASSERT(LIST_HEAD(&disk->file_opened_list) == &fd1.link);
395 ASSERT(battfs_fileExists(disk, INODE2));
396 ASSERT(battfs_fileopen(disk, &fd2, INODE2, MODE));
397 ASSERT(fd2.fd.size == PAGE_FILL * 2);
398 ASSERT(fd2.fd.seek_pos == 0);
399 ASSERT(fd2.mode == MODE);
400 ASSERT(fd2.inode == INODE2);
401 ASSERT(fd2.start == &disk->page_array[2]);
402 ASSERT(fd2.disk == disk);
403 ASSERT(LIST_HEAD(&disk->file_opened_list)->succ == &fd2.link);
405 ASSERT(kfile_close(&fd1.fd) == 0);
406 ASSERT(kfile_error(&fd1.fd) == 0);
407 ASSERT(kfile_close(&fd2.fd) == 0);
408 ASSERT(kfile_error(&fd2.fd) == 0);
409 ASSERT(LIST_EMPTY(&disk->file_opened_list));
410 ASSERT(battfs_fsck(disk));
411 ASSERT(battfs_umount(disk));
413 TRACEMSG("10: passed\n");
416 static void readFile(BattFsSuper *disk)
421 TRACEMSG("11: read file test\n");
423 FILE *fp = fopen(test_filename, "w+");
425 unsigned int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
428 unsigned int MODE = 0;
430 disk->erase(disk, 0);
431 battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
432 battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
433 battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
434 disk->erase(disk, 4);
435 battfs_writeTestBlock(disk, 5, INODE2, 0, PAGE_FILL, 0);
436 battfs_writeTestBlock(disk, 6, INODE2, 1, PAGE_FILL, 1);
437 battfs_writeTestBlock(disk, 7, INODE2, 0, PAGE_FILL, 1);
441 ASSERT(disk_open(disk));
442 ASSERT(battfs_mount(disk));
443 ASSERT(battfs_fsck(disk));
444 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
445 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
446 ASSERT(fd1.fd.seek_pos == sizeof(buf));
447 for (size_t i = 0; i < sizeof(buf); i++)
448 ASSERT(buf[i] == 0xff);
450 ASSERT(kfile_close(&fd1.fd) == 0);
451 ASSERT(kfile_error(&fd1.fd) == 0);
452 ASSERT(battfs_fsck(disk));
453 ASSERT(battfs_umount(disk));
455 TRACEMSG("11: passed\n");
458 static void readAcross(BattFsSuper *disk)
462 TRACEMSG("12: read file test across page boundary and seek test\n");
464 FILE *fp = fopen(test_filename, "w+");
466 const unsigned int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
468 unsigned int MODE = 0;
469 uint8_t buf[PAGE_FILL + BATTFS_HEADER_LEN / 2];
471 disk->erase(disk, 0);
472 battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
473 battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
474 battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
475 disk->erase(disk, 4);
476 battfs_writeTestBlock(disk, 5, INODE, 0, PAGE_FILL, 2);
477 battfs_writeTestBlock(disk, 6, INODE, 1, PAGE_FILL, 3);
478 battfs_writeTestBlock(disk, 7, INODE, 0, PAGE_FILL, 3);
482 ASSERT(disk_open(disk));
483 ASSERT(battfs_mount(disk));
484 ASSERT(battfs_fsck(disk));
485 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
487 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
488 ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf));
489 for (size_t i = 0; i < sizeof(buf); i++)
490 ASSERT(buf[i] == 0xff);
492 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
493 ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf) * 2);
494 for (size_t i = 0; i < sizeof(buf); i++)
495 ASSERT(buf[i] == 0xff);
497 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
498 ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf) * 3);
499 for (size_t i = 0; i < sizeof(buf); i++)
500 ASSERT(buf[i] == 0xff);
502 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == PAGE_FILL * 4 - sizeof(buf) * 3);
503 ASSERT(fd1.fd.seek_pos == (kfile_off_t)fd1.fd.size);
504 for (size_t i = 0; i < PAGE_FILL * 4 - sizeof(buf) * 3; i++)
505 ASSERT(buf[i] == 0xff);
507 ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
508 ASSERT(fd1.fd.seek_pos == 0);
510 ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_END) == (kfile_off_t)fd1.fd.size);
511 ASSERT(fd1.fd.seek_pos = (kfile_off_t)fd1.fd.size);
513 ASSERT(kfile_close(&fd1.fd) == 0);
514 ASSERT(kfile_error(&fd1.fd) == 0);
515 ASSERT(battfs_fsck(disk));
516 ASSERT(battfs_umount(disk));
518 TRACEMSG("12: passed\n");
522 static void writeFile(BattFsSuper *disk)
525 uint8_t buf[PAGE_SIZE - BATTFS_HEADER_LEN];
527 TRACEMSG("13: write file test\n");
529 FILE *fp = fopen(test_filename, "w+");
531 unsigned int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
534 unsigned int MODE = 0;
536 disk->erase(disk, 0);
537 battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
538 battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
539 battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
540 disk->erase(disk, 4);
541 battfs_writeTestBlock(disk, 5, INODE2, 0, PAGE_FILL, 0);
542 battfs_writeTestBlock(disk, 6, INODE2, 1, PAGE_FILL, 1);
543 battfs_writeTestBlock(disk, 7, INODE2, 0, PAGE_FILL, 1);
547 for (size_t i = 0; i < sizeof(buf); i++)
550 ASSERT(disk_open(disk));
551 ASSERT(battfs_mount(disk));
552 ASSERT(battfs_fsck(disk));
553 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
554 ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
555 ASSERT(fd1.fd.seek_pos == sizeof(buf));
556 ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
557 ASSERT(fd1.fd.seek_pos == 0);
559 memset(buf, 0, sizeof(buf));
560 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
561 for (size_t i = 0; i < sizeof(buf); i++)
564 ASSERT(kfile_close(&fd1.fd) == 0);
565 ASSERT(kfile_error(&fd1.fd) == 0);
566 ASSERT(battfs_fsck(disk));
567 ASSERT(battfs_umount(disk));
569 TRACEMSG("13: passed\n");
572 static void writeAcross(BattFsSuper *disk)
576 TRACEMSG("14: write file test across page boundary and seek test\n");
578 FILE *fp = fopen(test_filename, "w+");
580 const unsigned int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
582 unsigned int MODE = 0;
583 uint8_t buf[PAGE_FILL + BATTFS_HEADER_LEN / 2];
585 disk->erase(disk, 0);
586 battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
587 battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
588 battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
589 disk->erase(disk, 4);
590 battfs_writeTestBlock(disk, 5, INODE, 0, PAGE_FILL, 2);
591 battfs_writeTestBlock(disk, 6, INODE, 1, PAGE_FILL, 3);
592 battfs_writeTestBlock(disk, 7, INODE, 0, PAGE_FILL, 3);
596 ASSERT(disk_open(disk));
597 ASSERT(battfs_mount(disk));
598 ASSERT(battfs_fsck(disk));
599 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
602 for (size_t i = 0; i < sizeof(buf); i++)
604 ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
605 ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf));
607 for (size_t i = 0; i < sizeof(buf); i++)
609 ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
610 ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf) * 2);
612 for (size_t i = 0; i < sizeof(buf); i++)
614 ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
615 ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf) * 3);
617 ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
618 ASSERT(fd1.fd.seek_pos == 0);
621 memset(buf, 0, sizeof(buf));
622 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
623 for (size_t i = 0; i < sizeof(buf); i++)
624 ASSERT(buf[i] == val++);
626 memset(buf, 0, sizeof(buf));
627 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
628 for (size_t i = 0; i < sizeof(buf); i++)
629 ASSERT(buf[i] == val++);
631 memset(buf, 0, sizeof(buf));
632 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
633 for (size_t i = 0; i < sizeof(buf); i++)
634 ASSERT(buf[i] == val++);
636 ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf) * 3);
638 ASSERT(kfile_close(&fd1.fd) == 0);
639 ASSERT(kfile_error(&fd1.fd) == 0);
640 ASSERT(battfs_fsck(disk));
641 ASSERT(battfs_umount(disk));
643 TRACEMSG("14: passed\n");
646 static void createFile(BattFsSuper *disk)
648 TRACEMSG("15: file creation on new disk\n");
650 FILE *fpt = fopen(test_filename, "w+");
652 for (int i = 0; i < FILE_SIZE; i++)
658 unsigned int MODE = BATTFS_CREATE;
660 ASSERT(disk_open(disk));
661 ASSERT(battfs_mount(disk));
662 ASSERT(battfs_fsck(disk));
663 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
664 for (int i = 0; i < FILE_SIZE / 2; i++)
665 ASSERT(kfile_putc(i, &fd1.fd) != EOF);
667 ASSERT(fd1.fd.seek_pos == FILE_SIZE / 2);
668 ASSERT(fd1.fd.size == FILE_SIZE / 2);
669 ASSERT(kfile_close(&fd1.fd) == 0);
670 ASSERT(kfile_error(&fd1.fd) == 0);
671 ASSERT(battfs_fsck(disk));
672 ASSERT(battfs_umount(disk));
674 ASSERT(disk_open(disk));
675 ASSERT(battfs_mount(disk));
676 ASSERT(battfs_fsck(disk));
677 ASSERT(battfs_fileopen(disk, &fd1, INODE, 0));
678 ASSERT(fd1.fd.size == FILE_SIZE / 2);
679 ASSERT(fd1.fd.seek_pos == 0);
681 uint8_t buf[FILE_SIZE / 2];
682 memset(buf, 0, sizeof(buf));
683 ASSERT(kfile_read(&fd1.fd, buf, FILE_SIZE / 2) == FILE_SIZE / 2);
685 for (int i = 0; i < FILE_SIZE / 2; i++)
686 ASSERT(buf[i] == (i & 0xff));
688 ASSERT(fd1.fd.seek_pos == FILE_SIZE / 2);
689 ASSERT(kfile_close(&fd1.fd) == 0);
690 ASSERT(kfile_error(&fd1.fd) == 0);
691 ASSERT(battfs_fsck(disk));
692 ASSERT(battfs_umount(disk));
695 TRACEMSG("15: passed\n");
698 static void multipleWrite(BattFsSuper *disk)
700 TRACEMSG("16: multiple write on file\n");
702 FILE *fpt = fopen(test_filename, "w+");
704 for (int i = 0; i < FILE_SIZE; i++)
710 unsigned int MODE = BATTFS_CREATE;
713 ASSERT(disk_open(disk));
714 ASSERT(battfs_mount(disk));
715 ASSERT(battfs_fsck(disk));
716 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
719 for (j = 1; j < 1013; j++)
721 for (unsigned i = 0; i < sizeof(buf); i++)
724 ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
725 ASSERT(fd1.fd.seek_pos == sizeof(buf));
726 ASSERT(fd1.fd.size == sizeof(buf));
727 ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
728 memset(buf, 0, sizeof(buf));
729 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
730 ASSERT(fd1.fd.seek_pos == sizeof(buf));
731 for (unsigned i = 0; i < sizeof(buf); i++)
732 ASSERT(buf[i] == ((j+i) & 0xff));
733 ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
734 ASSERT(disk->free_bytes == disk->disk_size - sizeof(buf));
736 ASSERT(kfile_close(&fd1.fd) == 0);
737 ASSERT(kfile_error(&fd1.fd) == 0);
738 ASSERT(battfs_fsck(disk));
739 ASSERT(battfs_umount(disk));
741 ASSERT(disk_open(disk));
742 ASSERT(battfs_mount(disk));
743 ASSERT(battfs_fsck(disk));
744 ASSERT(disk->free_bytes == disk->disk_size - sizeof(buf));
745 ASSERT(battfs_fileopen(disk, &fd1, INODE, 0));
746 ASSERT(fd1.fd.size == sizeof(buf));
747 memset(buf, 0, sizeof(buf));
748 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
749 for (unsigned i = 0; i < sizeof(buf); i++)
750 ASSERT(buf[i] == ((j-1+i) & 0xff));
751 ASSERT(kfile_close(&fd1.fd) == 0);
752 ASSERT(kfile_error(&fd1.fd) == 0);
753 ASSERT(battfs_fsck(disk));
754 ASSERT(battfs_umount(disk));
757 TRACEMSG("16: passed\n");
760 static void increaseFile(BattFsSuper *disk)
762 TRACEMSG("17: increasing dimension of a file with multiple open files.\n");
764 FILE *fpt = fopen(test_filename, "w+");
766 for (int i = 0; i < FILE_SIZE / 10; i++)
771 inode_t INODE1 = 1, INODE2 = 2;
772 unsigned int MODE = BATTFS_CREATE;
775 ASSERT(disk_open(disk));
776 ASSERT(battfs_mount(disk));
777 ASSERT(battfs_fsck(disk));
778 ASSERT(battfs_fileopen(disk, &fd1, INODE1, MODE));
779 ASSERT(battfs_fileopen(disk, &fd2, INODE2, MODE));
780 for (unsigned i = 0; i < sizeof(buf); i++)
781 ASSERT(kfile_putc(i, &fd2.fd) != EOF);
782 ASSERT(kfile_seek(&fd2.fd, 0, KSM_SEEK_SET) == 0);
783 memset(buf, 0, sizeof(buf));
784 ASSERT(kfile_read(&fd2.fd, buf, sizeof(buf)) == sizeof(buf));
786 for (unsigned i = 0; i < sizeof(buf); i++)
787 ASSERT(buf[i] == (i & 0xff));
788 ASSERT(kfile_seek(&fd2.fd, 0, KSM_SEEK_SET) == 0);
790 for (unsigned i = 0; i < sizeof(buf); i++)
791 ASSERT(kfile_putc(i, &fd1.fd) != EOF);
793 memset(buf, 0, sizeof(buf));
794 ASSERT(kfile_read(&fd2.fd, buf, sizeof(buf)) == sizeof(buf));
796 for (unsigned i = 0; i < sizeof(buf); i++)
797 ASSERT(buf[i] == (i & 0xff));
799 ASSERT(kfile_close(&fd1.fd) == 0);
800 ASSERT(kfile_error(&fd1.fd) == 0);
801 ASSERT(kfile_close(&fd2.fd) == 0);
802 ASSERT(kfile_error(&fd2.fd) == 0);
803 ASSERT(battfs_fsck(disk));
804 ASSERT(battfs_umount(disk));
806 TRACEMSG("17: passed\n");
809 static void readEOF(BattFsSuper *disk)
814 TRACEMSG("18: reading over EOF test\n");
816 FILE *fp = fopen(test_filename, "w+");
818 unsigned int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
821 unsigned int MODE = 0;
823 disk->erase(disk, 0);
824 battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
825 battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
826 battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
827 disk->erase(disk, 4);
828 battfs_writeTestBlock(disk, 5, INODE2, 0, PAGE_FILL, 0);
829 battfs_writeTestBlock(disk, 6, INODE2, 1, PAGE_FILL, 1);
830 battfs_writeTestBlock(disk, 7, INODE2, 0, PAGE_FILL, 1);
834 ASSERT(disk_open(disk));
835 ASSERT(battfs_mount(disk));
836 ASSERT(battfs_fsck(disk));
837 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
838 ASSERT(kfile_seek(&fd1.fd, fd1.fd.size + 10, SEEK_SET) == fd1.fd.size + 10);
839 ASSERT(fd1.fd.seek_pos == fd1.fd.size + 10);
840 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == 0);
842 ASSERT(kfile_close(&fd1.fd) == 0);
843 ASSERT(kfile_error(&fd1.fd) == 0);
844 ASSERT(battfs_fsck(disk));
845 ASSERT(battfs_umount(disk));
847 TRACEMSG("18: passed\n");
850 static void writeEOF(BattFsSuper *disk)
852 TRACEMSG("19: writing over EOF test\n");
854 FILE *fpt = fopen(test_filename, "w+");
856 for (int i = 0; i < FILE_SIZE / 5; i++)
862 unsigned int MODE = BATTFS_CREATE;
863 uint8_t buf[FILE_SIZE / 13];
865 for (int i = 0; i < 2; i++)
868 ASSERT(disk_open(disk));
869 ASSERT(battfs_mount(disk));
870 ASSERT(battfs_fsck(disk));
871 disk_size_t prev_free = disk->free_bytes;
872 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
873 ASSERT(fd1.fd.size == 0);
875 ASSERT(kfile_seek(&fd1.fd, 2, KSM_SEEK_END) == 2);
876 ASSERT(kfile_write(&fd1.fd, buf, 2));
877 ASSERT(fd1.fd.seek_pos == 4);
878 ASSERT(fd1.fd.size == 4);
879 ASSERT(disk->free_bytes == prev_free - 4);
880 ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
882 ASSERT(kfile_read(&fd1.fd, buf, 2) == 2);
883 for (int i = 0; i < 2; i++)
887 ASSERT(kfile_read(&fd1.fd, buf, 2) == 2);
888 for (int i = 0; i < 2; i++)
889 ASSERT(buf[i] == (i & 0xff));
891 ASSERT(kfile_seek(&fd1.fd, sizeof(buf), KSM_SEEK_END) == sizeof(buf) + 4);
892 for (unsigned i = 0; i < sizeof(buf); i++)
894 ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)));
895 ASSERT(fd1.fd.seek_pos == sizeof(buf) * 2 + 4);
896 ASSERT(fd1.fd.size == sizeof(buf) * 2 + 4);
897 ASSERT(disk->free_bytes == prev_free - sizeof(buf) * 2 - 4);
899 ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
902 ASSERT(kfile_read(&fd1.fd, buf, 2) == 2);
903 ASSERT(fd1.fd.seek_pos == 2);
904 for (int i = 0; i < 2; i++)
908 ASSERT(kfile_read(&fd1.fd, buf, 2) == 2);
909 ASSERT(fd1.fd.seek_pos == 4);
910 for (int i = 0; i < 2; i++)
911 ASSERT(buf[i] == (i & 0xff));
914 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
915 ASSERT(fd1.fd.seek_pos == sizeof(buf) + 4);
916 for (unsigned i = 0; i < sizeof(buf); i++)
919 memset(buf, 0, sizeof(buf));
920 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
921 for (unsigned i = 0; i < sizeof(buf); i++)
922 ASSERT(buf[i] == (i & 0xff));
924 ASSERT(kfile_close(&fd1.fd) == 0);
925 ASSERT(kfile_error(&fd1.fd) == 0);
926 ASSERT(battfs_fsck(disk));
927 ASSERT(battfs_umount(disk));
929 TRACEMSG("19: passed\n");
933 static void endOfSpace(BattFsSuper *disk)
935 TRACEMSG("20: what happens when disk space is over?\n");
937 uint8_t buf[(PAGE_SIZE - BATTFS_HEADER_LEN) * 5];
939 FILE *fp = fopen(test_filename, "w+");
941 unsigned int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
943 unsigned int MODE = BATTFS_CREATE;
945 disk->erase(disk, 0);
946 disk->erase(disk, 1);
947 disk->erase(disk, 2);
948 disk->erase(disk, 3);
951 ASSERT(disk_open(disk));
952 ASSERT(battfs_mount(disk));
953 ASSERT(battfs_fsck(disk));
954 ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
955 ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)) == PAGE_FILL * 4);
956 ASSERT(fd1.fd.size == (kfile_off_t)(PAGE_FILL * 4));
957 ASSERT(fd1.fd.seek_pos == (kfile_off_t)(PAGE_FILL * 4));
958 ASSERT(disk->free_bytes == 0);
960 ASSERT(kfile_close(&fd1.fd) == 0);
961 ASSERT(kfile_error(&fd1.fd) == BATTFS_DISK_GETNEWPAGE_ERR);
962 ASSERT(battfs_fsck(disk));
963 ASSERT(battfs_umount(disk));
965 TRACEMSG("20: passed\n");
969 static void multipleFilesRW(BattFsSuper *disk)
971 TRACEMSG("21: multiple files read/write test\n");
973 FILE *fpt = fopen(test_filename, "w+");
975 for (int i = 0; i < FILE_SIZE; i++)
981 unsigned int MODE = BATTFS_CREATE;
982 uint32_t buf[FILE_SIZE / (4 * N_FILES * sizeof(uint32_t))];
984 ASSERT(disk_open(disk));
985 ASSERT(battfs_mount(disk));
986 ASSERT(battfs_fsck(disk));
987 for (inode_t i = 0; i < N_FILES; i++)
988 ASSERT(battfs_fileopen(disk, &fd[i], i, MODE));
990 for (int i = N_FILES - 1; i >= 0; i--)
992 for (uint32_t j = 0; j < countof(buf); j++)
995 ASSERT(kfile_write(&fd[i].fd, buf, sizeof(buf)) == sizeof(buf));
996 ASSERT(fd[i].fd.size == sizeof(buf));
997 ASSERT(fd[i].fd.seek_pos == sizeof(buf));
998 ASSERT(kfile_seek(&fd[i].fd, 0, SEEK_SET) == 0);
1001 for (inode_t i = 0; i < N_FILES; i++)
1003 memset(buf, 0, sizeof(buf));
1004 ASSERT(kfile_read(&fd[i].fd, buf, sizeof(buf)) == sizeof(buf));
1006 for (uint32_t j = 0; j < countof(buf); j++)
1007 ASSERT(buf[j] == j+i);
1009 ASSERT(fd[i].fd.size == sizeof(buf));
1010 ASSERT(fd[i].fd.seek_pos == sizeof(buf));
1011 ASSERT(kfile_seek(&fd[i].fd, 0, SEEK_SET) == 0);
1014 for (inode_t i = 0; i < N_FILES; i++)
1016 ASSERT(kfile_close(&fd[i].fd) == 0);
1017 ASSERT(kfile_error(&fd[i].fd) == 0);
1020 ASSERT(battfs_fsck(disk));
1021 ASSERT(battfs_umount(disk));
1023 ASSERT(disk_open(disk));
1024 ASSERT(battfs_mount(disk));
1025 ASSERT(battfs_fsck(disk));
1027 for (inode_t i = 0; i < N_FILES; i++)
1028 ASSERT(battfs_fileopen(disk, &fd[i], i, 0));
1030 for (inode_t i = 0; i < N_FILES; i++)
1032 memset(buf, 0, sizeof(buf));
1033 ASSERT(kfile_read(&fd[i].fd, buf, sizeof(buf)) == sizeof(buf));
1035 for (uint32_t j = 0; j < countof(buf); j++)
1036 ASSERT(buf[j] == j+i);
1038 ASSERT(fd[i].fd.size == sizeof(buf));
1039 ASSERT(fd[i].fd.seek_pos == sizeof(buf));
1040 ASSERT(kfile_seek(&fd[i].fd, 0, SEEK_SET) == 0);
1043 for (inode_t i = 0; i < N_FILES; i++)
1045 ASSERT(kfile_close(&fd[i].fd) == 0);
1046 ASSERT(kfile_error(&fd[i].fd) == 0);
1049 ASSERT(battfs_umount(disk));
1050 TRACEMSG("21: passed\n");
1054 int battfs_testRun(void)
1060 diskHalfFile(&disk);
1071 multipleWrite(&disk);
1072 increaseFile(&disk);
1076 multipleFilesRW(&disk);
1078 kprintf("All tests passed!\n");
1083 int battfs_testSetup(void)
1088 int battfs_testTearDown(void)
1095 #include <fs/battfs.c>
1096 #include <kern/kfile.c>
1097 #include <drv/kdebug.c>
1098 #include <mware/formatwr.c>
1099 #include <mware/hex.c>