X-Git-Url: http://git.vrable.net/?a=blobdiff_plain;f=inode.c;fp=inode.c;h=95afc0a9cf7916da1352c64244fc2b501ed8deb2;hb=f48181d57295355b68dffdd8fad5729bf952ba7a;hp=4437c04bf03731da09f8c79c0bcfd5a4a4ad1f8c;hpb=9bf82653d36b735f835d78112c067030de77c9c5;p=bluesky.git diff --git a/inode.c b/inode.c index 4437c04..95afc0a 100644 --- a/inode.c +++ b/inode.c @@ -81,9 +81,11 @@ BlueSkyInode *bluesky_new_inode(uint64_t inum, BlueSkyFileType type) switch (type) { case BLUESKY_REGULAR: + i->blocks = g_array_new(FALSE, TRUE, sizeof(BlueSkyBlock)); break; case BLUESKY_DIRECTORY: i->dirents = g_sequence_new(bluesky_dirent_destroy); + break; case BLUESKY_BLOCK: case BLUESKY_CHARACTER: case BLUESKY_SYMLINK: @@ -116,3 +118,35 @@ void bluesky_insert_inode(BlueSkyFS *fs, BlueSkyInode *inode) g_hash_table_insert(fs->inodes, &inode->inum, inode); g_mutex_unlock(fs->lock); } + +/* Set the size of a file. This will truncate or extend the file as needed. + * Newly-allocated bytes are zeroed. */ +void bluesky_file_truncate(BlueSkyInode *inode, uint64_t size) +{ + g_return_if_fail(size <= BLUESKY_MAX_FILE_SIZE); + + if (size == inode->size) + return; + + uint64_t blocks = (size + BLUESKY_BLOCK_SIZE - 1) / BLUESKY_MAX_FILE_SIZE; + + if (blocks > inode->blocks->len) { + /* Need to add new blocks to the end of a file. New block structures + * are automatically zeroed, which initializes them to be pointers to + * zero blocks so we don't need to do any more work. */ + g_array_set_size(inode->blocks, blocks); + } else if (blocks < inode->blocks->len) { + /* Delete blocks from a file. Must reclaim memory. */ + for (guint i = inode->blocks->len; i < blocks; i++) { + BlueSkyBlock *b = &g_array_index(inode->blocks, BlueSkyBlock, i); + g_free(b->ref); + g_free(b->data); + } + g_array_set_size(inode->blocks, blocks); + } + + /* TODO: Zero out partial blocks if needed? */ + + inode->size = size; + inode->change_count++; +}