--- /dev/null
+/* Blue Sky: File Systems in the Cloud
+ *
+ * Copyright (C) 2009 The Regents of the University of California
+ * Written by Michael Vrable <mvrable@cs.ucsd.edu>
+ *
+ * TODO: Licensing
+ */
+
+#include <stdint.h>
+#include <glib.h>
+#include <string.h>
+
+#include "bluesky.h"
+
+/* Serialization of in-memory filesystem data structures to bytestrings which
+ * can be written to persistent storage. All data is stored in little-endian
+ * format. */
+
+/* Magic signature for serialized inodes. */
+
+#define INODE_MAGIC 0xa6832100943d71e5ULL
+
+struct serialized_inode {
+ uint64_t signature; /* INODE_MAGIC */
+ int32_t type;
+ uint32_t mode;
+ uint32_t uid, gid;
+ uint32_t nlink;
+ uint64_t inum;
+ uint64_t change_count;
+ int64_t atime;
+ int64_t ctime;
+ int64_t mtime;
+ int64_t ntime;
+} __attribute__((packed));
+
+void bluesky_serialize_inode(GString *out, BlueSkyInode *inode)
+{
+ struct serialized_inode buf;
+
+ buf.signature = GUINT64_TO_LE(INODE_MAGIC);
+ buf.type = GUINT32_TO_LE(inode->type);
+ buf.mode = GUINT32_TO_LE(inode->mode);
+ buf.uid = GUINT32_TO_LE(inode->uid);
+ buf.gid = GUINT32_TO_LE(inode->gid);
+ buf.nlink = GUINT32_TO_LE(inode->nlink);
+ buf.inum = GUINT64_TO_LE(inode->inum);
+ buf.change_count = GUINT64_TO_LE(inode->change_count);
+ buf.atime = GINT64_TO_LE(inode->atime);
+ buf.ctime = GINT64_TO_LE(inode->ctime);
+ buf.mtime = GINT64_TO_LE(inode->mtime);
+ buf.ntime = GINT64_TO_LE(inode->ntime);
+
+ g_string_append_len(out, (gchar *)&buf, sizeof(buf));
+
+ switch (inode->type) {
+ case BLUESKY_REGULAR:
+ for (int i = 0; i < inode->blocks->len; i++) {
+ BlueSkyBlock *b = &g_array_index(inode->blocks, BlueSkyBlock, i);
+ if (b->ref != NULL)
+ g_string_append(out, b->ref);
+ g_string_append_c(out, '\0');
+ }
+ break;
+ default:
+ g_warning("Serialization for inode type %d not implemented!\n",
+ inode->type);
+ }
+}
+
+BlueSkyInode *bluesky_deserialize_inode(BlueSkyFS *fs, const gchar *buf)
+{
+ struct serialized_inode *raw = (struct serialized_inode *)buf;
+
+ if (GUINT64_FROM_LE(raw->signature) != INODE_MAGIC)
+ return NULL;
+
+ BlueSkyInode *inode = bluesky_new_inode(GUINT64_FROM_LE(raw->inum),
+ fs, GUINT32_FROM_LE(raw->type));
+
+ inode->mode = GUINT32_FROM_LE(raw->mode);
+ inode->uid = GUINT32_FROM_LE(raw->uid);
+ inode->gid = GUINT32_FROM_LE(raw->gid);
+ inode->nlink = GUINT32_FROM_LE(raw->nlink);
+ inode->change_count = GUINT64_FROM_LE(raw->change_count);
+ inode->atime = GINT64_FROM_LE(raw->atime);
+ inode->ctime = GINT64_FROM_LE(raw->ctime);
+ inode->mtime = GINT64_FROM_LE(raw->mtime);
+ inode->ntime = GINT64_FROM_LE(raw->ntime);
+
+ buf += sizeof(struct serialized_inode);
+
+ switch (inode->type) {
+ case BLUESKY_REGULAR:
+ g_array_set_size(inode->blocks,
+ (inode->size + BLUESKY_BLOCK_SIZE - 1)
+ / BLUESKY_BLOCK_SIZE);
+ for (int i = 0; i < inode->blocks->len; i++) {
+ BlueSkyBlock *b = &g_array_index(inode->blocks, BlueSkyBlock, i);
+ b->type = BLUESKY_BLOCK_REF;
+ b->ref = g_strdup(buf);
+ buf += strlen(b->ref) + 1;
+ }
+ break;
+ default:
+ g_warning("Deserialization for inode type %d not implemented!\n",
+ inode->type);
+ }
+}