/*
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 2013  Free Software Foundation, Inc.
 *
 *  GRUB is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  GRUB 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <grub/procfs.h>
#include <grub/disk.h>
#include <grub/fs.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/dl.h>
#include <grub/archelp.h>

GRUB_MOD_LICENSE ("GPLv3+");

struct grub_procfs_entry *grub_procfs_entries;

static int
grub_procdev_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
			 grub_disk_pull_t pull)
{
  if (pull != GRUB_DISK_PULL_NONE)
    return 0;

  return hook ("proc", hook_data);
}

static grub_err_t
grub_procdev_open (const char *name, grub_disk_t disk)
{
  if (grub_strcmp (name, "proc"))
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a procfs disk");

  disk->total_sectors = 0;
  disk->id = 0;

  disk->data = 0;

  return GRUB_ERR_NONE;
}

static void
grub_procdev_close (grub_disk_t disk __attribute((unused)))
{
}

static grub_err_t
grub_procdev_read (grub_disk_t disk __attribute((unused)),
		grub_disk_addr_t sector __attribute((unused)),
		grub_size_t size __attribute((unused)),
		char *buf __attribute((unused)))
{
  return GRUB_ERR_OUT_OF_RANGE;
}

static grub_err_t
grub_procdev_write (grub_disk_t disk __attribute ((unused)),
		       grub_disk_addr_t sector __attribute ((unused)),
		       grub_size_t size __attribute ((unused)),
		       const char *buf __attribute ((unused)))
{
  return GRUB_ERR_OUT_OF_RANGE;
}

struct grub_archelp_data
{
  struct grub_procfs_entry *entry, *next_entry;
};

static void
grub_procfs_rewind (struct grub_archelp_data *data)
{
  data->entry = NULL;
  data->next_entry = grub_procfs_entries;
}

static grub_err_t
grub_procfs_find_file (struct grub_archelp_data *data, char **name,
		     grub_int32_t *mtime,
		     grub_uint32_t *mode)
{
  data->entry = data->next_entry;
  if (!data->entry)
    {
      *mode = GRUB_ARCHELP_ATTR_END;
      return GRUB_ERR_NONE;
    }
  data->next_entry = data->entry->next;
  *mode = GRUB_ARCHELP_ATTR_FILE | GRUB_ARCHELP_ATTR_NOTIME;
  *name = grub_strdup (data->entry->name);
  *mtime = 0;
  if (!*name)
    return grub_errno;
  return GRUB_ERR_NONE;
}

static struct grub_archelp_ops arcops =
  {
    .find_file = grub_procfs_find_file,
    .rewind = grub_procfs_rewind
  };

static grub_ssize_t
grub_procfs_read (grub_file_t file, char *buf, grub_size_t len)
{
  char *data = file->data;

  grub_memcpy (buf, data + file->offset, len);

  return len;
}

static grub_err_t
grub_procfs_close (grub_file_t file)
{
  char *data;

  data = file->data;
  grub_free (data);

  return GRUB_ERR_NONE;
}

static grub_err_t
grub_procfs_dir (grub_device_t device, const char *path,
		 grub_fs_dir_hook_t hook, void *hook_data)
{
  struct grub_archelp_data data;

  /* Check if the disk is our dummy disk.  */
  if (grub_strcmp (device->disk->name, "proc"))
    return grub_error (GRUB_ERR_BAD_FS, "not a procfs");

  grub_procfs_rewind (&data);

  return grub_archelp_dir (&data, &arcops,
			   path, hook, hook_data);
}

static grub_err_t
grub_procfs_open (struct grub_file *file, const char *path)
{
  grub_err_t err;
  struct grub_archelp_data data;
  grub_size_t sz;

  grub_procfs_rewind (&data);

  err = grub_archelp_open (&data, &arcops, path);
  if (err)
    return err;
  file->data = data.entry->get_contents (&sz);
  if (!file->data)
    return grub_errno;
  file->size = sz;
  return GRUB_ERR_NONE;
}

static struct grub_disk_dev grub_procfs_dev = {
  .name = "proc",
  .id = GRUB_DISK_DEVICE_PROCFS_ID,
  .iterate = grub_procdev_iterate,
  .open = grub_procdev_open,
  .close = grub_procdev_close,
  .read = grub_procdev_read,
  .write = grub_procdev_write,
  .next = 0
};

static struct grub_fs grub_procfs_fs =
  {
    .name = "procfs",
    .dir = grub_procfs_dir,
    .open = grub_procfs_open,
    .read = grub_procfs_read,
    .close = grub_procfs_close,
    .next = 0
  };

GRUB_MOD_INIT (procfs)
{
  grub_disk_dev_register (&grub_procfs_dev);
  grub_fs_register (&grub_procfs_fs);
}

GRUB_MOD_FINI (procfs)
{
  grub_disk_dev_unregister (&grub_procfs_dev);
  grub_fs_unregister (&grub_procfs_fs);
}
