/*
 * filesystem.h
 *
 * Copyright (C) 2016 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef _FILESYSTEM_H_
#define _FILESYSTEM_H_

#include <common.h>
#include <object.h>
#include <sdk/list.h>
#include <clock.h>
#include <lock.h>
#include <sdk/filesystem.h>
#include <pipe.h>

typedef struct mounted_volume mounted_volume_t;
typedef struct file file_t;
typedef struct file_instance file_instance_t;

typedef dword_t (*fs_mount_proc_t)(const char *device, const char *mountpoint, dword_t flags);
typedef dword_t (*fs_unmount_proc_t)(mounted_volume_t *volume);
typedef dword_t (*fs_load_proc_t)(file_t **file);
typedef dword_t (*fs_unload_proc_t)(file_t *file);
typedef dword_t (*fs_open_proc_t)(file_instance_t **instance);
typedef dword_t (*fs_close_proc_t)(file_instance_t *instance);
typedef dword_t (*fs_delete_proc_t)(mounted_volume_t *volume, const char *path, bool_t purge);
typedef dword_t (*fs_read_proc_t)(file_instance_t *file, void *buffer, qword_t offset, size_t length, size_t *bytes_read);
typedef dword_t (*fs_write_proc_t)(file_instance_t *file, const void *buffer, qword_t offset, size_t length, size_t *bytes_written);
typedef dword_t (*fs_list_dir_proc_t)(file_instance_t *directory, char *filename, bool_t continue_scan);
typedef dword_t (*fs_set_proc_t)(file_t *file, dword_t info_type, const void *buffer, size_t size);

typedef struct
{
    list_entry_t list;
    char name[16];
    fs_mount_proc_t mount;
    fs_unmount_proc_t unmount;
    fs_load_proc_t load_file;
    fs_unload_proc_t unload_file;
    fs_open_proc_t open_file;
    fs_close_proc_t close_file;
    fs_delete_proc_t delete_file;
    fs_read_proc_t read_file;
    fs_write_proc_t write_file;
    fs_list_dir_proc_t list_dir;
    fs_set_proc_t set_file;
} fs_driver_t;

typedef struct
{
    list_entry_t list;
    pipe_t pipe;
    dword_t event_mask;
    file_instance_t *directory; /* weak reference */
} event_watch_entry_t;

struct file
{
    object_t header;
    mounted_volume_t *volume;
    char *path;
    dword_t global_mode;
    dword_t attributes;
    qword_t size;
    dword_t owner_uid;
};

struct file_instance
{
    object_t header;
    file_t *global; /* strong reference */
    dword_t mode;
    event_watch_entry_t *watch;
};

#include <device.h>

struct mounted_volume
{
    list_entry_t list;
    char *mountpoint;
    dword_t flags;
    lock_t lock;
    device_t *device;
    qword_t open_files;
    fs_driver_t *driver;
    list_entry_t event_watch_list;
    lock_t event_watch_list_lock;
};

void register_filesystem_driver(fs_driver_t *driver);
bool_t unregister_filesystem_driver(fs_driver_t *driver);
dword_t register_mounted_volume(mounted_volume_t *volume);
dword_t unregister_mounted_volume(mounted_volume_t *volume);
dword_t normalize_path(const char *path, char *normalized_path);
dword_t open_file_internal(const char *path, file_instance_t **instance, dword_t mode, dword_t attributes);
void report_filesystem_event(const char *path, dword_t type);

#endif
