/*
 * Copyright 2018-2019, ttcoder of TTS LLC
 * Distributed under the terms of the MIT license.
 */

/*
WHAT:
	this implements BFS (BeOS/Haiku's Be File System) support in Genode

SETUP: Jamfile:
	just call "jam" or "jam bfs_fuse_fs"

SETUP: gmake:
	for gmake (target.mk) based building,
	make sure there is a genode/repos/libports/src/lib/bfs symlink
	pointing to the folder containing this (init.cc) file -- hence
	the reason why the folder is named "libports-src-lib-bfs", to
	give a hint as to where it comes in play.
	That way, the bfs-FUSE component will be built, just like
	ntfs-3g-FUSE ..etc.
 */


/* Genode includes */
#include <base/log.h>
#include <util/string.h>

#include <fuse.h>
#include <fuse_private.h>

/* libc includes */
#include <stdio.h>
#include <stdlib.h>


/* haiku */
#include "fssh_module.h"
#include "fssh_errors.h"  // FSSH_B_OK
#include "fssh_string.h"  // fssh_strerror()

// C++ imports
//
extern struct fuse_operations gFUSEOperations;  // defined in fuse.cpp

// C imports
//
extern "C" {
extern fssh_module_info *modules[];
struct fuse_chan *fc;
struct fuse      *fh;
extern int fssh_fuse_session(
	const char* device,
	const char* mntPoint,
	const char* fsName,
	struct fuse_args& fuseArgs
	);
}
namespace FSShell {
	extern "C" fssh_status_t  init_kernel();
}


bool Fuse::init_fs(void)
{
	if (!modules[0]) {
		fprintf(stderr, "Error: Couldn't find FS module!\n");
		return 1;
	}
	
	Genode::log("fuse_bfs: init_kernel()");
	
	// init "Haiku"
	//
	fssh_status_t error = FSShell::init_kernel();
	if (error != FSSH_B_OK) {
		fprintf(stderr, "Error: Initializing kernel failed: %s\n",
			fssh_strerror(error));
		return error;
	}
	
	Genode::log("fuse_bfs: try mounting /dev/blkdev...");
	
	// fssh_fuse_session()
	//
	struct fuse_args fuseArgs = FUSE_ARGS_INIT(0,NULL);//argc, argv);
	int err = fssh_fuse_session(
		"/dev/blkdev",
		"/" /*config.mntPoint*/,
		modules[0]->name,  //++ could we retrofit a partition name here? how to obtain that name ?
			///+++ looks like it can be obtained: LOG shows e.g. << mounted "SamBravo" >> ..etc
		fuseArgs
		);
	if (err)
	{
		Genode::error("fuse_bfs: could not mount /dev/blkdev; error: ", err);
		return false;
	}
	
	//Genode::log("fuse_bfs: calling fusenew..");
	fh = fuse_new(fc, NULL, &gFUSEOperations, sizeof (gFUSEOperations), NULL);
	if (fh == 0) {
		Genode::error("fuse_bfs: fuse_new() failed");
//		bfs_close();
		return false;
	}
	
	return true;
}


void Fuse::deinit_fs(void)
{
	Genode::error("fuse_bfs: unmount /dev/blkdev...");
//	bfs_close();

//	free(*bfs_fuse_ctx());
}


void Fuse::sync_fs(void)
{
	//Genode::warning("fuse_bfs: sync file system...");
//	bfs_device_sync((*bfs_fuse_ctx())->vol->dev);
}


bool Fuse::support_symlinks(void)
{
	return true;
}

