X-Git-Url: http://git.vrable.net/?a=blobdiff_plain;f=inode.c;h=aa822b76736ddb58bddbdc09302504dad47ac232;hb=19f316a185dc3d2a67fc3d3546f3989e45559d7c;hp=b9da798ca7ac773c1fad7b8bd1dc1469090d1803;hpb=8819789ef2264b26aebfae489932a447f6e0f65f;p=bluesky.git diff --git a/inode.c b/inode.c index b9da798..aa822b7 100644 --- a/inode.c +++ b/inode.c @@ -21,7 +21,19 @@ int64_t bluesky_get_current_time() { GTimeVal t; g_get_current_time(&t); - return t.tv_sec * 1000000 + t.tv_usec; + return (int64_t)t.tv_sec * 1000000 + t.tv_usec; +} + +/* Update an inode to indicate that a modification was made. This increases + * the change counter, updates the ctime to the current time, and optionally + * updates the mtime. */ +void bluesky_inode_update_ctime(BlueSkyInode *inode, gboolean update_mtime) +{ + int64_t now = bluesky_get_current_time(); + inode->change_count++; + inode->ctime = now; + if (update_mtime) + inode->mtime = now; } /* Unfortunately a glib hash table is only guaranteed to be able to store @@ -81,9 +93,12 @@ 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); + i->dirhash = g_hash_table_new(g_str_hash, g_str_equal); + break; case BLUESKY_BLOCK: case BLUESKY_CHARACTER: case BLUESKY_SYMLINK: @@ -116,3 +131,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++; +}