From 661b0df2a780f14694463915ae6103e58a69cd12 Mon Sep 17 00:00:00 2001 From: batt Date: Thu, 25 Sep 2008 13:59:37 +0000 Subject: [PATCH] Add support for writing far over the EOF. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@1844 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/fs/battfs.c | 65 +++++++++++++++++++++++++++++---- bertos/fs/battfs_test.c | 80 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+), 7 deletions(-) diff --git a/bertos/fs/battfs.c b/bertos/fs/battfs.c index 11908590..ca13600c 100644 --- a/bertos/fs/battfs.c +++ b/bertos/fs/battfs.c @@ -418,7 +418,7 @@ static bool flushBuffer(struct BattFsSuper *disk) static bool loadPage(struct BattFsSuper *disk, pgcnt_t new_page, BattFsPageHeader *new_hdr) { if (disk->curr_page == new_page) - return true; + return getBufferHdr(disk, new_hdr); LOG_INFO("Loading page %d\n", new_page); @@ -494,12 +494,12 @@ bool battfs_init(struct BattFsSuper *disk) LOG_ERR("filling page array\n"); return false; } - #if LOG_LEVEL > LOG_LVL_INFO - dumpPageArray(disk) + #if LOG_LEVEL >= LOG_LVL_INFO + dumpPageArray(disk); #endif #warning TODO: shuffle free blocks //#if LOG_LEVEL > LOG_LVL_INFO - // dumpPageArray(disk) + // dumpPageArray(disk); //#endif /* Init list for opened files. */ LIST_INIT(&disk->file_opened_list); @@ -582,12 +582,59 @@ static size_t battfs_write(struct KFile *fd, const void *_buf, size_t size) pgoff_t pg_offset; pgaddr_t addr_offset; pgaddr_t wr_len; - BattFsPageHeader curr_hdr; - if (!getBufferHdr(fdb->disk, &curr_hdr)) + + if (fd->seek_pos < 0) return total_write; - #warning TODO seek_pos > size? + if ((fd->seek_pos / (fdb->disk->page_size - BATTFS_HEADER_LEN)) > fdb->max_off) + { + /* + * Handle writing when seek pos if far over EOF, + * We need to allocate the missing pages first. + */ + pgoff_t missing_pages = fd->seek_pos / (fdb->disk->page_size - BATTFS_HEADER_LEN) - fdb->max_off; + + LOG_INFO("missing pages: %d\n", missing_pages); + if (!loadPage(fdb->disk, fdb->start[fdb->max_off], &curr_hdr)) + { + #warning TODO set error? + return total_write; + } + + uint8_t dummy = 0xff; + /* Add missing pages to reach current seek_pos */ + while (missing_pages--) + { + /* Update size and free space left */ + fd->size += (fdb->disk->page_size - BATTFS_HEADER_LEN) - curr_hdr.fill; + fdb->disk->free_bytes -= (fdb->disk->page_size - BATTFS_HEADER_LEN) - curr_hdr.fill; + + /* Fill empty space with 0xFF */ + for (addr_offset = curr_hdr.fill; addr_offset < (fdb->disk->page_size - BATTFS_HEADER_LEN); addr_offset++) + { + if (fdb->disk->bufferWrite(fdb->disk, addr_offset, &dummy, 1) != 1) + { + #warning TODO set error? + } + } + curr_hdr.fill = (fdb->disk->page_size - BATTFS_HEADER_LEN); + setBufferHdr(fdb->disk, &curr_hdr); + + /* Get the new page needed */ + if (!getNewPage(fdb->disk, (fdb->start - fdb->disk->page_array) + fdb->max_off + 1, fdb->inode, fdb->max_off + 1, &curr_hdr)) + return total_write; + + fdb->max_off++; + } + /* Fix sizes for the last new page (could be only partially full) */ + curr_hdr.fill = fd->seek_pos % (fdb->disk->page_size - BATTFS_HEADER_LEN); + setBufferHdr(fdb->disk, &curr_hdr); + fd->size += curr_hdr.fill; + fdb->disk->free_bytes -= curr_hdr.fill; + } + else if (!getBufferHdr(fdb->disk, &curr_hdr)) + return total_write; while (size) { @@ -665,6 +712,9 @@ static size_t battfs_read(struct KFile *fd, void *_buf, size_t size) pgaddr_t addr_offset; pgaddr_t read_len; + if (fd->seek_pos < 0) + return total_read; + size = MIN((kfile_off_t)size, MAX(fd->size - fd->seek_pos, 0)); while (size) @@ -673,6 +723,7 @@ static size_t battfs_read(struct KFile *fd, void *_buf, size_t size) addr_offset = fd->seek_pos % (fdb->disk->page_size - BATTFS_HEADER_LEN); read_len = MIN(size, (size_t)(fdb->disk->page_size - BATTFS_HEADER_LEN - addr_offset)); + //LOG_INFO("reading from page %d, offset %d, size %d\n", fdb->start[pg_offset], addr_offset, read_len); /* Read from disk */ if (diskRead(fdb->disk, fdb->start[pg_offset], addr_offset, buf, read_len) != read_len) { diff --git a/bertos/fs/battfs_test.c b/bertos/fs/battfs_test.c index c1cd89e6..0df504cd 100644 --- a/bertos/fs/battfs_test.c +++ b/bertos/fs/battfs_test.c @@ -785,6 +785,85 @@ static void readEOF(BattFsSuper *disk) TRACEMSG("18: passed\n"); } +static void writeEOF(BattFsSuper *disk) +{ + TRACEMSG("19: writing over EOF test\n"); + + FILE *fpt = fopen(test_filename, "w+"); + + for (int i = 0; i < FILE_SIZE / 5; i++) + fputc(0xff, fpt); + fclose(fpt); + + BattFs fd1; + inode_t INODE = 0; + unsigned int MODE = BATTFS_CREATE; + uint8_t buf[FILE_SIZE / 13]; + + for (int i = 0; i < 2; i++) + buf[i] = i; + + ASSERT(battfs_init(disk)); + disk_size_t prev_free = disk->free_bytes; + ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE)); + ASSERT(fd1.fd.size == 0); + + ASSERT(kfile_seek(&fd1.fd, 2, KSM_SEEK_END) == 2); + ASSERT(kfile_write(&fd1.fd, buf, 2)); + ASSERT(fd1.fd.seek_pos == 4); + ASSERT(fd1.fd.size == 4); + ASSERT(disk->free_bytes == prev_free - 4); + ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0); + memset(buf, 0, 2); + ASSERT(kfile_read(&fd1.fd, buf, 2) == 2); + for (int i = 0; i < 2; i++) + ASSERT(buf[i] == 0xff); + + memset(buf, 0, 2); + ASSERT(kfile_read(&fd1.fd, buf, 2) == 2); + for (int i = 0; i < 2; i++) + ASSERT(buf[i] == (i & 0xff)); + + ASSERT(kfile_seek(&fd1.fd, sizeof(buf), KSM_SEEK_END) == sizeof(buf) + 4); + for (int i = 0; i < sizeof(buf); i++) + buf[i] = i; + ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf))); + ASSERT(fd1.fd.seek_pos == sizeof(buf) * 2 + 4); + ASSERT(fd1.fd.size == sizeof(buf) * 2 + 4); + ASSERT(disk->free_bytes == prev_free - sizeof(buf) * 2 - 4); + + ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0); + + memset(buf, 0, 2); + ASSERT(kfile_read(&fd1.fd, buf, 2) == 2); + ASSERT(fd1.fd.seek_pos == 2); + for (int i = 0; i < 2; i++) + ASSERT(buf[i] == 0xff); + + memset(buf, 0, 2); + ASSERT(kfile_read(&fd1.fd, buf, 2) == 2); + ASSERT(fd1.fd.seek_pos == 4); + for (int i = 0; i < 2; i++) + ASSERT(buf[i] == (i & 0xff)); + + memset(buf, 0, 4); + ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf)); + ASSERT(fd1.fd.seek_pos == sizeof(buf) + 4); + for (int i = 0; i < sizeof(buf); i++) + ASSERT(buf[i] == 0xff); + + memset(buf, 0, sizeof(buf)); + ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf)); + for (int i = 0; i < sizeof(buf); i++) + ASSERT(buf[i] == (i & 0xff)); + + ASSERT(kfile_close(&fd1.fd) == 0); + ASSERT(battfs_close(disk)); + + TRACEMSG("19: passed\n"); + +} + int battfs_testRun(void) { @@ -815,6 +894,7 @@ int battfs_testRun(void) multipleWrite(&disk); increaseFile(&disk); readEOF(&disk); + writeEOF(&disk); kprintf("All tests passed!\n"); -- 2.25.1