From d97247ffe0f18083e0494260ee53910111e6732c Mon Sep 17 00:00:00 2001
From: Gary Talent <gtalent2@gmail.com>
Date: Mon, 30 Jul 2018 21:28:16 -0500
Subject: [PATCH] [ox/fs] Fix initial root dir inode

---
 deps/ox/src/ox/fs/filesystem2/filesystem.hpp | 245 +++++++++++++++++++
 1 file changed, 245 insertions(+)
 create mode 100644 deps/ox/src/ox/fs/filesystem2/filesystem.hpp

diff --git a/deps/ox/src/ox/fs/filesystem2/filesystem.hpp b/deps/ox/src/ox/fs/filesystem2/filesystem.hpp
new file mode 100644
index 00000000..7a615b50
--- /dev/null
+++ b/deps/ox/src/ox/fs/filesystem2/filesystem.hpp
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2015 - 2018 gtalent2@gmail.com
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <ox/fs/filestore/filestoretemplate.hpp>
+#include <ox/fs/filesystem/filesystem.hpp>
+
+#include "directory.hpp"
+
+namespace ox::fs {
+
+template<typename InodeId_t>
+class FileSystemTemplate {
+	private:
+		static constexpr InodeId_t InodeFsData = 2;
+
+		struct __attribute__((packed)) FileSystemData {
+			LittleEndian<InodeId_t> rootDirInode;
+		};
+
+		FileStore *m_fs = nullptr;
+
+	public:
+		FileSystemTemplate(FileStore *fs);
+
+		~FileSystemTemplate();
+
+		Error format();
+
+		Error mkdir(const char *path, bool recursive = false);
+
+		/**
+		 * Moves an entry from one directory to another.
+		 * @param src the path to the file
+		 * @param dest the path of the destination directory
+		 */
+		Error move(const char *src, const char *dest);
+
+		Error read(const char *path, void *buffer, std::size_t buffSize);
+
+		Error read(uint64_t inode, void *buffer, std::size_t size);
+
+		Error read(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size);
+
+		Error remove(const char *path, bool recursive = false);
+
+		void resize(uint64_t size = 0);
+
+		Error write(const char *path, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile);
+
+		Error write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile);
+
+		FileStat stat(uint64_t inode);
+
+		FileStat stat(const char *path);
+
+		uint64_t spaceNeeded(uint64_t size);
+
+		uint64_t available();
+
+		uint64_t size();
+
+		uint8_t *buff();
+
+		void walk(int(*cb)(const char*, uint64_t, uint64_t));
+
+		bool valid() const;
+
+	private:
+		ValErr<FileSystemData> fileSystemData();
+
+};
+
+template<typename InodeId_t>
+FileSystemTemplate<InodeId_t>::FileSystemTemplate(FileStore *fs) {
+	m_fs = fs;
+}
+
+template<typename InodeId_t>
+FileSystemTemplate<InodeId_t>::~FileSystemTemplate() {
+}
+
+template<typename InodeId_t>
+Error FileSystemTemplate<InodeId_t>::format() {
+	oxReturnError(m_fs->format());
+
+	constexpr auto rootDirInode = MaxValue<InodeId_t> / 2;
+	auto rootDir = ox_malloca(sizeof(ox::fs::Directory<InodeId_t>), ox::fs::Directory<InodeId_t>, m_fs, rootDirInode);
+	oxReturnError(rootDir->init());
+
+	FileSystemData fd;
+	fd.rootDirInode = rootDirInode;
+	oxTrace("ox::fs::FileSystemTemplate::format") << "rootDirInode:" << fd.rootDirInode;
+	oxReturnError(m_fs->write(InodeFsData, &fd, sizeof(fd)));
+
+	if (m_fs->read(fd.rootDirInode).valid()) {
+		oxTrace("ox::fs::FileSystemTemplate::format::error") << "FileSystemTemplate::format did not correctly create root directory";
+	}
+
+	return OxError(0);
+}
+
+template<typename InodeId_t>
+Error FileSystemTemplate<InodeId_t>::mkdir(const char *path, bool recursive) {
+	auto fd = fileSystemData();
+	if (fd.ok()) {
+		oxTrace("ox::fs::FileSystemTemplate::mkdir") << "rootDirInode:" << fd.value.rootDirInode;
+		auto rootDir = ox_malloca(sizeof(ox::fs::Directory<InodeId_t>), ox::fs::Directory<InodeId_t>, m_fs, fd.value.rootDirInode);
+		return rootDir->mkdir(path, recursive);
+	} else {
+		oxLogError(fd.error);
+		return fd.error;
+	}
+}
+
+template<typename InodeId_t>
+Error FileSystemTemplate<InodeId_t>::move(const char *src, const char *dest) {
+	auto fd = fileSystemData();
+	if (fd.ok()) {
+		auto rootDir = ox_malloca(sizeof(ox::fs::Directory<InodeId_t>), ox::fs::Directory<InodeId_t>, m_fs, fd.value.rootDirInode);
+		auto inode = rootDir->find(src);
+		oxReturnError(inode.error);
+		oxReturnError(rootDir->write(dest, inode));
+		oxReturnError(rootDir->remove(src));
+		return OxError(0);
+	} else {
+		return fd.error;
+	}
+}
+
+template<typename InodeId_t>
+Error FileSystemTemplate<InodeId_t>::read(const char *path, void *buffer, std::size_t buffSize) {
+	auto fd = fileSystemData();
+	if (fd.ok()) {
+		auto rootDir = ox_malloca(sizeof(ox::fs::Directory<InodeId_t>), ox::fs::Directory<InodeId_t>, m_fs, fd.value.rootDirInode);
+		auto inode = rootDir->find(path);
+		oxReturnError(inode.error);
+		return read(inode, buffer, buffSize);
+	} else {
+		return fd.error;
+	}
+}
+
+template<typename InodeId_t>
+Error FileSystemTemplate<InodeId_t>::read(uint64_t inode, void *buffer, std::size_t buffSize) {
+	return m_fs->read(inode, buffer, buffSize);
+}
+
+template<typename InodeId_t>
+Error FileSystemTemplate<InodeId_t>::read(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) {
+	return m_fs->read(inode, readStart, readSize, buffer, size);
+}
+
+template<typename InodeId_t>
+Error FileSystemTemplate<InodeId_t>::remove(const char *path, bool recursive) {
+	auto fd = fileSystemData();
+	if (fd.ok()) {
+		auto rootDir = ox_malloca(sizeof(ox::fs::Directory<InodeId_t>), ox::fs::Directory<InodeId_t>, m_fs, fd.value.rootDirInode);
+		auto inode = rootDir->find(path);
+		oxReturnError(inode.error);
+		if (auto err = rootDir->remove(path)) {
+			// removal failed, try putting the index back
+			oxLogError(rootDir->write(path, inode));
+			return err;
+		}
+		return OxError(0);
+	} else {
+		return fd.error;
+	}
+}
+
+template<typename InodeId_t>
+void FileSystemTemplate<InodeId_t>::resize(uint64_t size) {
+}
+
+template<typename InodeId_t>
+Error FileSystemTemplate<InodeId_t>::write(const char *path, void *buffer, uint64_t size, uint8_t fileType) {
+	return OxError(0);
+}
+
+template<typename InodeId_t>
+Error FileSystemTemplate<InodeId_t>::write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType) {
+	return OxError(0);
+}
+
+template<typename InodeId_t>
+FileStat FileSystemTemplate<InodeId_t>::stat(uint64_t inode) {
+	return {};
+}
+
+template<typename InodeId_t>
+FileStat FileSystemTemplate<InodeId_t>::stat(const char *path) {
+	return {};
+}
+
+template<typename InodeId_t>
+uint64_t FileSystemTemplate<InodeId_t>::spaceNeeded(uint64_t size) {
+	return 0;
+}
+
+template<typename InodeId_t>
+uint64_t FileSystemTemplate<InodeId_t>::available() {
+	return 0;
+}
+
+template<typename InodeId_t>
+uint64_t FileSystemTemplate<InodeId_t>::size() {
+	return 0;
+}
+
+template<typename InodeId_t>
+uint8_t *FileSystemTemplate<InodeId_t>::buff() {
+	return nullptr;
+}
+
+template<typename InodeId_t>
+void FileSystemTemplate<InodeId_t>::walk(int(*cb)(const char*, uint64_t, uint64_t)) {
+}
+
+template<typename InodeId_t>
+ValErr<typename FileSystemTemplate<InodeId_t>::FileSystemData> FileSystemTemplate<InodeId_t>::fileSystemData() {
+	FileSystemData fd;
+	auto err = m_fs->read(InodeFsData, &fd, sizeof(fd));
+	if (err != 0) {
+		return {fd, err};
+	}
+	return fd;
+}
+
+extern template class Directory<uint16_t>;
+extern template class Directory<uint32_t>;
+
+extern template class FileSystemTemplate<uint16_t>;
+extern template class FileSystemTemplate<uint32_t>;
+
+using FileSystem16 = FileSystemTemplate<uint16_t>;
+using FileSystem32 = FileSystemTemplate<uint32_t>;
+
+}