-/* Mark a given block dirty and make sure that data is faulted in so that it
- * can be written to. */
-void bluesky_block_touch(BlueSkyInode *inode, uint64_t i)
-{
- g_return_if_fail(i < inode->blocks->len);
- BlueSkyBlock *block = &g_array_index(inode->blocks, BlueSkyBlock, i);
-
- switch (block->type) {
- case BLUESKY_BLOCK_ZERO:
- block->data = bluesky_string_new(g_malloc0(BLUESKY_BLOCK_SIZE),
- BLUESKY_BLOCK_SIZE);
- break;
- case BLUESKY_BLOCK_REF:
- bluesky_block_fetch(inode->fs, block);
- g_assert(block->type == BLUESKY_BLOCK_CACHED);
- /* Fall through */
- case BLUESKY_BLOCK_CACHED:
- case BLUESKY_BLOCK_DIRTY:
- block->data = bluesky_string_dup(block->data);
- break;
- }
-
- block->type = BLUESKY_BLOCK_DIRTY;
-}
-
-/* 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_BLOCK_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);
- bluesky_string_unref(b->data);
- }
- g_array_set_size(inode->blocks, blocks);
- }
-
- /* If the file size is being decreased, ensure that any trailing data in
- * the last block is zeroed. */
- if (size < inode->size) {
- BlueSkyBlock *b = &g_array_index(inode->blocks, BlueSkyBlock,
- blocks - 1);
- if (b->type != BLUESKY_BLOCK_ZERO) {
- bluesky_block_touch(inode, blocks - 1);
- int end_offset = size % BLUESKY_BLOCK_SIZE;
- if (end_offset > 0) {
- memset(&b->data->data[end_offset], 0,
- BLUESKY_BLOCK_SIZE - end_offset);
- }
- }
- }
-
- inode->size = size;
- bluesky_inode_update_ctime(inode, 1);
-}
-
-void bluesky_file_write(BlueSkyInode *inode, uint64_t offset,
- const char *data, gint len)
-{
- g_return_if_fail(inode->type == BLUESKY_REGULAR);
- g_return_if_fail(offset < inode->size);
- g_return_if_fail(len <= inode->size - offset);
-
- if (len == 0)
- return;
-
- while (len > 0) {
- uint64_t block_num = offset / BLUESKY_BLOCK_SIZE;
- gint block_offset = offset % BLUESKY_BLOCK_SIZE;
- gint bytes = MIN(BLUESKY_BLOCK_SIZE - block_offset, len);
-
- bluesky_block_touch(inode, block_num);
- BlueSkyBlock *b = &g_array_index(inode->blocks, BlueSkyBlock,
- block_num);
- memcpy(&b->data->data[block_offset], data, bytes);
- bluesky_block_flush(inode->fs, b);
-
- offset += bytes;
- data += bytes;
- len -= bytes;
- }
-
- bluesky_inode_update_ctime(inode, 1);
-}
-
-void bluesky_file_read(BlueSkyInode *inode, uint64_t offset,
- char *buf, gint len)