#include <inttypes.h>
#include <glib.h>
-#include "bluesky.h"
+#include "bluesky-private.h"
/* Core filesystem: handling of directories. */
return d->inum;
}
+/* Iterate through a directory listing. This returns one directory entry at a
+ * time, finding the first entry with a directory cookie value larger than the
+ * supplied one. Use a cookie of 0 to start reading from the start of a
+ * directory. */
+BlueSkyDirent *bluesky_directory_read(BlueSkyInode *dir, uint32_t cookie)
+{
+ BlueSkyDirent start = {NULL, NULL, cookie, 0};
+ GSequenceIter *i = g_sequence_search(dir->dirents, &start,
+ bluesky_dirent_compare, NULL);
+
+ if (g_sequence_iter_is_end(i))
+ return NULL;
+ else
+ return g_sequence_get(i);
+}
+
/* Insert a new entry into a directory. Should be called with the inode lock
* already held. */
-gboolean bluesky_directory_insert(BlueSkyInode *dir, gchar *name, uint64_t inum)
+gboolean bluesky_directory_insert(BlueSkyInode *dir,
+ const gchar *name, uint64_t inum)
{
g_return_val_if_fail(dir->type == BLUESKY_DIRECTORY, FALSE);
g_hash_table_insert(dir->dirhash_folded, d->name_folded, d);
bluesky_inode_update_ctime(dir, 1);
- bluesky_inode_flush(dir->fs, dir);
+ //bluesky_inode_do_sync(dir); // TODO: Needed?
return TRUE;
}
-/* Remove an from a directory. Should be called with the inode lock already
- * held. */
+/* Remove an entry from a directory. Should be called with the inode lock
+ * already held. */
gboolean bluesky_directory_remove(BlueSkyInode *dir, gchar *name)
{
g_return_val_if_fail(dir->type == BLUESKY_DIRECTORY, FALSE);
g_sequence_remove(i);
bluesky_inode_update_ctime(dir, 1);
- bluesky_inode_flush(dir->fs, dir);
+
+ return TRUE;
+}
+
+/* Rename a file. If desired (if overwrite is true) and if the target already
+ * exists, it will be unlinked first. */
+gboolean bluesky_rename(BlueSkyInode *dir1, gchar *name1,
+ BlueSkyInode *dir2, gchar *name2,
+ gboolean case_sensitive,
+ gboolean overwrite)
+{
+ g_return_val_if_fail(dir1->type == BLUESKY_DIRECTORY, FALSE);
+ g_return_val_if_fail(dir2->type == BLUESKY_DIRECTORY, FALSE);
+
+ BlueSkyDirent *d1, *d2;
+
+ d1 = g_hash_table_lookup(case_sensitive ? dir1->dirhash
+ : dir1->dirhash_folded, name1);
+ d2 = g_hash_table_lookup(case_sensitive ? dir2->dirhash
+ : dir2->dirhash_folded, name2);
+
+ if (d1 == NULL)
+ return FALSE;
+
+ uint64_t inum = d1->inum;
+
+ /* Check that this rename does not cause a directory to be moved into one
+ * of its descendants, as that would create a loop of directories
+ * disconnected from the root. */
+ /* TODO */
+
+ if (d2 != NULL) {
+ if (!overwrite)
+ return FALSE;
+
+ bluesky_directory_remove(dir2, name2);
+
+ // TODO: Drop inode reference
+ }
+
+ bluesky_directory_remove(dir1, name1);
+ bluesky_directory_insert(dir2, name2, inum);
return TRUE;
}