/* ntfs.c - NTFS filesystem */
/*
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 2007,2008,2009 Free Software Foundation, Inc.
 *
 *  This program 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.
 *
 *  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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#define grub_fshelp_node grub_ntfs_file 

#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/fshelp.h>
#include <grub/ntfs.h>
#include <grub/charset.h>

GRUB_MOD_LICENSE ("GPLv3+");

static grub_dl_t my_mod;

#define grub_fshelp_node grub_ntfs_file 

static inline grub_uint16_t
u16at (void *ptr, grub_size_t ofs)
{
  return grub_le_to_cpu16 (grub_get_unaligned16 ((char *) ptr + ofs));
}

static inline grub_uint32_t
u32at (void *ptr, grub_size_t ofs)
{
  return grub_le_to_cpu32 (grub_get_unaligned32 ((char *) ptr + ofs));
}

static inline grub_uint64_t
u64at (void *ptr, grub_size_t ofs)
{
  return grub_le_to_cpu64 (grub_get_unaligned64 ((char *) ptr + ofs));
}

grub_ntfscomp_func_t grub_ntfscomp_func;

static grub_err_t
fixup (grub_uint8_t *buf, grub_size_t len, const grub_uint8_t *magic)
{
  grub_uint16_t ss;
  grub_uint8_t *pu;
  grub_uint16_t us;

  COMPILE_TIME_ASSERT ((1 << GRUB_NTFS_BLK_SHR) == GRUB_DISK_SECTOR_SIZE);

  if (grub_memcmp (buf, magic, 4))
    return grub_error (GRUB_ERR_BAD_FS, "%s label not found", magic);

  ss = u16at (buf, 6) - 1;
  if (ss != len)
    return grub_error (GRUB_ERR_BAD_FS, "size not match");
  pu = buf + u16at (buf, 4);
  us = u16at (pu, 0);
  buf -= 2;
  while (ss > 0)
    {
      buf += GRUB_DISK_SECTOR_SIZE;
      pu += 2;
      if (u16at (buf, 0) != us)
	return grub_error (GRUB_ERR_BAD_FS, "fixup signature not match");
      buf[0] = pu[0];
      buf[1] = pu[1];
      ss--;
    }

  return 0;
}

static grub_err_t read_mft (struct grub_ntfs_data *data, grub_uint8_t *buf,
			    grub_uint64_t mftno);
static grub_err_t read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest,
			     grub_disk_addr_t ofs, grub_size_t len,
			     int cached,
			     grub_disk_read_hook_t read_hook,
			     void *read_hook_data);

static grub_err_t read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa,
			     grub_uint8_t *dest,
			     grub_disk_addr_t ofs, grub_size_t len,
			     int cached,
			     grub_disk_read_hook_t read_hook,
			     void *read_hook_data);

static void
init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft)
{
  at->mft = mft;
  at->flags = (mft == &mft->data->mmft) ? GRUB_NTFS_AF_MMFT : 0;
  at->attr_nxt = mft->buf + u16at (mft->buf, 0x14);
  at->attr_end = at->emft_buf = at->edat_buf = at->sbuf = NULL;
}

static void
free_attr (struct grub_ntfs_attr *at)
{
  grub_free (at->emft_buf);
  grub_free (at->edat_buf);
  grub_free (at->sbuf);
}

static grub_uint8_t *
find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
{
  if (at->flags & GRUB_NTFS_AF_ALST)
    {
    retry:
      while (at->attr_nxt < at->attr_end)
	{
	  at->attr_cur = at->attr_nxt;
	  at->attr_nxt += u16at (at->attr_cur, 4);
	  if ((*at->attr_cur == attr) || (attr == 0))
	    {
	      grub_uint8_t *new_pos;

	      if (at->flags & GRUB_NTFS_AF_MMFT)
		{
		  if ((grub_disk_read
		       (at->mft->data->disk, u32at (at->attr_cur, 0x10), 0,
			512, at->emft_buf))
		      ||
		      (grub_disk_read
		       (at->mft->data->disk, u32at (at->attr_cur, 0x14), 0,
			512, at->emft_buf + 512)))
		    return NULL;

		  if (fixup (at->emft_buf, at->mft->data->mft_size,
			     (const grub_uint8_t *) "FILE"))
		    return NULL;
		}
	      else
		{
		  if (read_mft (at->mft->data, at->emft_buf,
				u32at (at->attr_cur, 0x10)))
		    return NULL;
		}

	      new_pos = &at->emft_buf[u16at (at->emft_buf, 0x14)];
	      while (*new_pos != 0xFF)
		{
		  if ((*new_pos == *at->attr_cur)
		      && (u16at (new_pos, 0xE) == u16at (at->attr_cur, 0x18)))
		    {
		      return new_pos;
		    }
		  new_pos += u16at (new_pos, 4);
		}
	      grub_error (GRUB_ERR_BAD_FS,
			  "can\'t find 0x%X in attribute list",
			  (unsigned char) *at->attr_cur);
	      return NULL;
	    }
	}
      return NULL;
    }
  at->attr_cur = at->attr_nxt;
  while (*at->attr_cur != 0xFF)
    {
      at->attr_nxt += u16at (at->attr_cur, 4);
      if (*at->attr_cur == GRUB_NTFS_AT_ATTRIBUTE_LIST)
	at->attr_end = at->attr_cur;
      if ((*at->attr_cur == attr) || (attr == 0))
	return at->attr_cur;
      at->attr_cur = at->attr_nxt;
    }
  if (at->attr_end)
    {
      grub_uint8_t *pa;

      at->emft_buf = grub_malloc (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
      if (at->emft_buf == NULL)
	return NULL;

      pa = at->attr_end;
      if (pa[8])
	{
          grub_uint32_t n;

          n = ((u32at (pa, 0x30) + GRUB_DISK_SECTOR_SIZE - 1)
               & (~(GRUB_DISK_SECTOR_SIZE - 1)));
	  at->attr_cur = at->attr_end;
	  at->edat_buf = grub_malloc (n);
	  if (!at->edat_buf)
	    return NULL;
	  if (read_data (at, pa, at->edat_buf, 0, n, 0, 0, 0))
	    {
	      grub_error (GRUB_ERR_BAD_FS,
			  "fail to read non-resident attribute list");
	      return NULL;
	    }
	  at->attr_nxt = at->edat_buf;
	  at->attr_end = at->edat_buf + u32at (pa, 0x30);
	}
      else
	{
	  at->attr_nxt = at->attr_end + u16at (pa, 0x14);
	  at->attr_end = at->attr_end + u32at (pa, 4);
	}
      at->flags |= GRUB_NTFS_AF_ALST;
      while (at->attr_nxt < at->attr_end)
	{
	  if ((*at->attr_nxt == attr) || (attr == 0))
	    break;
	  at->attr_nxt += u16at (at->attr_nxt, 4);
	}
      if (at->attr_nxt >= at->attr_end)
	return NULL;

      if ((at->flags & GRUB_NTFS_AF_MMFT) && (attr == GRUB_NTFS_AT_DATA))
	{
	  at->flags |= GRUB_NTFS_AF_GPOS;
	  at->attr_cur = at->attr_nxt;
	  pa = at->attr_cur;
	  grub_set_unaligned32 ((char *) pa + 0x10,
				grub_cpu_to_le32 (at->mft->data->mft_start));
	  grub_set_unaligned32 ((char *) pa + 0x14,
				grub_cpu_to_le32 (at->mft->data->mft_start
						  + 1));
	  pa = at->attr_nxt + u16at (pa, 4);
	  while (pa < at->attr_end)
	    {
	      if (*pa != attr)
		break;
	      if (read_attr
		  (at, pa + 0x10,
		   u32at (pa, 0x10) * (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR),
		   at->mft->data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0, 0))
		return NULL;
	      pa += u16at (pa, 4);
	    }
	  at->attr_nxt = at->attr_cur;
	  at->flags &= ~GRUB_NTFS_AF_GPOS;
	}
      goto retry;
    }
  return NULL;
}

static grub_uint8_t *
locate_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft,
	     grub_uint8_t attr)
{
  grub_uint8_t *pa;

  init_attr (at, mft);
  pa = find_attr (at, attr);
  if (pa == NULL)
    return NULL;
  if ((at->flags & GRUB_NTFS_AF_ALST) == 0)
    {
      while (1)
	{
	  pa = find_attr (at, attr);
	  if (pa == NULL)
	    break;
	  if (at->flags & GRUB_NTFS_AF_ALST)
	    return pa;
	}
      grub_errno = GRUB_ERR_NONE;
      free_attr (at);
      init_attr (at, mft);
      pa = find_attr (at, attr);
    }
  return pa;
}

static grub_disk_addr_t
read_run_data (const grub_uint8_t *run, int nn, int sig)
{
  grub_uint64_t r = 0;

  if (sig && nn && (run[nn - 1] & 0x80))
    r = -1;

  grub_memcpy (&r, run, nn);

  return grub_le_to_cpu64 (r);
}

grub_err_t
grub_ntfs_read_run_list (struct grub_ntfs_rlst * ctx)
{
  grub_uint8_t c1, c2;
  grub_disk_addr_t val;
  grub_uint8_t *run;

  run = ctx->cur_run;
retry:
  c1 = ((*run) & 0x7);
  c2 = ((*run) >> 4) & 0x7;
  run++;
  if (!c1)
    {
      if ((ctx->attr) && (ctx->attr->flags & GRUB_NTFS_AF_ALST))
	{
	  grub_disk_read_hook_t save_hook;

	  save_hook = ctx->comp.disk->read_hook;
	  ctx->comp.disk->read_hook = 0;
	  run = find_attr (ctx->attr, *ctx->attr->attr_cur);
	  ctx->comp.disk->read_hook = save_hook;
	  if (run)
	    {
	      if (run[8] == 0)
		return grub_error (GRUB_ERR_BAD_FS,
				   "$DATA should be non-resident");

	      run += u16at (run, 0x20);
	      ctx->curr_lcn = 0;
	      goto retry;
	    }
	}
      return grub_error (GRUB_ERR_BAD_FS, "run list overflown");
    }
  ctx->curr_vcn = ctx->next_vcn;
  ctx->next_vcn += read_run_data (run, c1, 0);	/* length of current VCN */
  run += c1;
  val = read_run_data (run, c2, 1);	/* offset to previous LCN */
  run += c2;
  ctx->curr_lcn += val;
  if (val == 0)
    ctx->flags |= GRUB_NTFS_RF_BLNK;
  else
    ctx->flags &= ~GRUB_NTFS_RF_BLNK;
  ctx->cur_run = run;
  return 0;
}

static grub_disk_addr_t
grub_ntfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t block)
{
  struct grub_ntfs_rlst *ctx;

  ctx = (struct grub_ntfs_rlst *) node;
  if (block >= ctx->next_vcn)
    {
      if (grub_ntfs_read_run_list (ctx))
	return -1;
      return ctx->curr_lcn;
    }
  else
    return (ctx->flags & GRUB_NTFS_RF_BLNK) ? 0 : (block -
					 ctx->curr_vcn + ctx->curr_lcn);
}

static grub_err_t
read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest,
	   grub_disk_addr_t ofs, grub_size_t len, int cached,
	   grub_disk_read_hook_t read_hook, void *read_hook_data)
{
  struct grub_ntfs_rlst cc, *ctx;

  if (len == 0)
    return 0;

  grub_memset (&cc, 0, sizeof (cc));
  ctx = &cc;
  ctx->attr = at;
  ctx->comp.log_spc = at->mft->data->log_spc;
  ctx->comp.disk = at->mft->data->disk;

  if (read_hook == grub_file_progress_hook)
    ctx->file = read_hook_data;

  if (pa[8] == 0)
    {
      if (ofs + len > u32at (pa, 0x10))
	return grub_error (GRUB_ERR_BAD_FS, "read out of range");
      grub_memcpy (dest, pa + u32at (pa, 0x14) + ofs, len);
      return 0;
    }

  ctx->cur_run = pa + u16at (pa, 0x20);

  ctx->next_vcn = u32at (pa, 0x10);
  ctx->curr_lcn = 0;

  if ((pa[0xC] & GRUB_NTFS_FLAG_COMPRESSED)
      && !(at->flags & GRUB_NTFS_AF_GPOS))
    {
      if (!cached)
	return grub_error (GRUB_ERR_BAD_FS, "attribute can\'t be compressed");

      return (grub_ntfscomp_func) ? grub_ntfscomp_func (dest, ofs, len, ctx)
	: grub_error (GRUB_ERR_BAD_FS, N_("module `%s' isn't loaded"),
		      "ntfscomp");
    }

  ctx->target_vcn = ofs >> (GRUB_NTFS_BLK_SHR + ctx->comp.log_spc);
  while (ctx->next_vcn <= ctx->target_vcn)
    {
      if (grub_ntfs_read_run_list (ctx))
	return grub_errno;
    }

  if (at->flags & GRUB_NTFS_AF_GPOS)
    {
      grub_disk_addr_t st0, st1;
      grub_uint64_t m;

      m = (ofs >> GRUB_NTFS_BLK_SHR) & ((1 << ctx->comp.log_spc) - 1);

      st0 =
	((ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn) << ctx->comp.log_spc) + m;
      st1 = st0 + 1;
      if (st1 ==
	  (ctx->next_vcn - ctx->curr_vcn + ctx->curr_lcn) << ctx->comp.log_spc)
	{
	  if (grub_ntfs_read_run_list (ctx))
	    return grub_errno;
	  st1 = ctx->curr_lcn << ctx->comp.log_spc;
	}
      grub_set_unaligned32 (dest, grub_cpu_to_le32 (st0));
      grub_set_unaligned32 (dest + 4, grub_cpu_to_le32 (st1));
      return 0;
    }

  grub_fshelp_read_file (ctx->comp.disk, (grub_fshelp_node_t) ctx,
			 read_hook, read_hook_data, ofs, len,
			 (char *) dest,
			 grub_ntfs_read_block, ofs + len,
			 ctx->comp.log_spc, 0);
  return grub_errno;
}

static grub_err_t
read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest, grub_disk_addr_t ofs,
	   grub_size_t len, int cached,
	   grub_disk_read_hook_t read_hook, void *read_hook_data)
{
  grub_uint8_t *save_cur;
  grub_uint8_t attr;
  grub_uint8_t *pp;
  grub_err_t ret;

  save_cur = at->attr_cur;
  at->attr_nxt = at->attr_cur;
  attr = *at->attr_nxt;
  if (at->flags & GRUB_NTFS_AF_ALST)
    {
      grub_uint8_t *pa;
      grub_disk_addr_t vcn;

      /* If compression is possible make sure that we include possible
	 compressed block size.  */
      if (GRUB_NTFS_LOG_COM_SEC >= at->mft->data->log_spc)
	vcn = ((ofs >> GRUB_NTFS_COM_LOG_LEN)
	       << (GRUB_NTFS_LOG_COM_SEC - at->mft->data->log_spc)) & ~0xFULL;
      else
	vcn = ofs >> (at->mft->data->log_spc + GRUB_NTFS_BLK_SHR);
      pa = at->attr_nxt + u16at (at->attr_nxt, 4);
      while (pa < at->attr_end)
	{
	  if (*pa != attr)
	    break;
	  if (u32at (pa, 8) > vcn)
	    break;
	  at->attr_nxt = pa;
	  pa += u16at (pa, 4);
	}
    }
  pp = find_attr (at, attr);
  if (pp)
    ret = read_data (at, pp, dest, ofs, len, cached,
		     read_hook, read_hook_data);
  else
    ret =
      (grub_errno) ? grub_errno : grub_error (GRUB_ERR_BAD_FS,
					      "attribute not found");
  at->attr_cur = save_cur;
  return ret;
}

static grub_err_t
read_mft (struct grub_ntfs_data *data, grub_uint8_t *buf, grub_uint64_t mftno)
{
  if (read_attr
      (&data->mmft.attr, buf, mftno * ((grub_disk_addr_t) data->mft_size << GRUB_NTFS_BLK_SHR),
       data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0, 0))
    return grub_error (GRUB_ERR_BAD_FS, "read MFT 0x%llx fails", (unsigned long long) mftno);
  return fixup (buf, data->mft_size, (const grub_uint8_t *) "FILE");
}

static grub_err_t
init_file (struct grub_ntfs_file *mft, grub_uint64_t mftno)
{
  unsigned short flag;

  mft->inode_read = 1;

  mft->buf = grub_malloc (mft->data->mft_size << GRUB_NTFS_BLK_SHR);
  if (mft->buf == NULL)
    return grub_errno;

  if (read_mft (mft->data, mft->buf, mftno))
    return grub_errno;

  flag = u16at (mft->buf, 0x16);
  if ((flag & 1) == 0)
    return grub_error (GRUB_ERR_BAD_FS, "MFT 0x%llx is not in use",
		       (unsigned long long) mftno);

  if ((flag & 2) == 0)
    {
      grub_uint8_t *pa;

      pa = locate_attr (&mft->attr, mft, GRUB_NTFS_AT_DATA);
      if (pa == NULL)
	return grub_error (GRUB_ERR_BAD_FS, "no $DATA in MFT 0x%llx",
			   (unsigned long long) mftno);

      if (!pa[8])
	mft->size = u32at (pa, 0x10);
      else
	mft->size = u64at (pa, 0x30);

      if ((mft->attr.flags & GRUB_NTFS_AF_ALST) == 0)
	mft->attr.attr_end = 0;	/*  Don't jump to attribute list */
    }
  else
    init_attr (&mft->attr, mft);

  return 0;
}

static void
free_file (struct grub_ntfs_file *mft)
{
  free_attr (&mft->attr);
  grub_free (mft->buf);
}

static char *
get_utf8 (grub_uint8_t *in, grub_size_t len)
{
  grub_uint8_t *buf;
  grub_uint16_t *tmp;
  grub_size_t i;

  buf = grub_calloc (len, GRUB_MAX_UTF8_PER_UTF16 + 1);
  tmp = grub_calloc (len, sizeof (tmp[0]));
  if (!buf || !tmp)
    {
      grub_free (buf);
      grub_free (tmp);
      return NULL;
    }
  for (i = 0; i < len; i++)
    tmp[i] = grub_le_to_cpu16 (grub_get_unaligned16 (in + 2 * i));
  *grub_utf16_to_utf8 (buf, tmp, len) = '\0';
  grub_free (tmp);
  return (char *) buf;
}

static int
list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos,
	   grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
{
  grub_uint8_t *np;
  int ns;

  while (1)
    {
      grub_uint8_t namespace;
      char *ustr;

      if (pos[0xC] & 2)		/* end signature */
	break;

      np = pos + 0x50;
      ns = *(np++);
      namespace = *(np++);

      /*
       *  Ignore files in DOS namespace, as they will reappear as Win32
       *  names.
       */
      if ((ns) && (namespace != 2))
	{
	  enum grub_fshelp_filetype type;
	  struct grub_ntfs_file *fdiro;
	  grub_uint32_t attr;

	  attr = u32at (pos, 0x48);
	  if (attr & GRUB_NTFS_ATTR_REPARSE)
	    type = GRUB_FSHELP_SYMLINK;
	  else if (attr & GRUB_NTFS_ATTR_DIRECTORY)
	    type = GRUB_FSHELP_DIR;
	  else
	    type = GRUB_FSHELP_REG;

	  fdiro = grub_zalloc (sizeof (struct grub_ntfs_file));
	  if (!fdiro)
	    return 0;

	  fdiro->data = diro->data;
	  fdiro->ino = u64at (pos, 0) & 0xffffffffffffULL;
	  fdiro->mtime = u64at (pos, 0x20);

	  ustr = get_utf8 (np, ns);
	  if (ustr == NULL)
	    {
	      grub_free (fdiro);
	      return 0;
	    }
          if (namespace)
            type |= GRUB_FSHELP_CASE_INSENSITIVE;

	  if (hook (ustr, type, fdiro, hook_data))
	    {
	      grub_free (ustr);
	      return 1;
	    }

	  grub_free (ustr);
	}
      pos += u16at (pos, 8);
    }
  return 0;
}

struct symlink_descriptor
{
  grub_uint32_t type;
  grub_uint32_t total_len;
  grub_uint16_t off1;
  grub_uint16_t len1;
  grub_uint16_t off2;
  grub_uint16_t len2;
} GRUB_PACKED;

static char *
grub_ntfs_read_symlink (grub_fshelp_node_t node)
{
  struct grub_ntfs_file *mft;
  struct symlink_descriptor symdesc;
  grub_err_t err;
  grub_uint8_t *buf16;
  char *buf, *end;
  grub_size_t len;
  grub_uint8_t *pa;
  grub_size_t off;

  mft = (struct grub_ntfs_file *) node;

  mft->buf = grub_malloc (mft->data->mft_size << GRUB_NTFS_BLK_SHR);
  if (mft->buf == NULL)
    return NULL;

  if (read_mft (mft->data, mft->buf, mft->ino))
    return NULL;

  pa = locate_attr (&mft->attr, mft, GRUB_NTFS_AT_SYMLINK);
  if (pa == NULL)
    {
      grub_error (GRUB_ERR_BAD_FS, "no $SYMLINK in MFT 0x%llx",
		  (unsigned long long) mft->ino);
      return NULL;
    }

  err = read_attr (&mft->attr, (grub_uint8_t *) &symdesc, 0,
		   sizeof (struct symlink_descriptor), 1, 0, 0);
  if (err)
    return NULL;

  switch (grub_cpu_to_le32 (symdesc.type))
    {
    case 0xa000000c:
      off = (sizeof (struct symlink_descriptor) + 4
	     + grub_cpu_to_le32 (symdesc.off1));
      len = grub_cpu_to_le32 (symdesc.len1);
      break;
    case 0xa0000003:
      off = (sizeof (struct symlink_descriptor)
	     + grub_cpu_to_le32 (symdesc.off1));
      len = grub_cpu_to_le32 (symdesc.len1);
      break;
    default:
      grub_error (GRUB_ERR_BAD_FS, "symlink type invalid (%x)",
		  grub_cpu_to_le32 (symdesc.type));
      return NULL;
    }

  buf16 = grub_malloc (len);
  if (!buf16)
    return NULL;

  err = read_attr (&mft->attr, buf16, off, len, 1, 0, 0);
  if (err)
    return NULL;

  buf = get_utf8 (buf16, len / 2);
  if (!buf)
    {
      grub_free (buf16);
      return NULL;
    }
  grub_free (buf16);

  for (end = buf; *end; end++)
    if (*end == '\\')
      *end = '/';

  /* Split the sequence to avoid GCC thinking that this is a trigraph.  */
  if (grub_memcmp (buf, "/?" "?/", 4) == 0 && buf[5] == ':' && buf[6] == '/'
      && grub_isalpha (buf[4]))
    {
      grub_memmove (buf, buf + 6, end - buf + 1 - 6);
      end -= 6; 
    }
  return buf;
}

static int
grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
		       grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
{
  grub_uint8_t *bitmap;
  struct grub_ntfs_attr attr, *at;
  grub_uint8_t *cur_pos, *indx, *bmp;
  int ret = 0;
  grub_size_t bitmap_len;
  struct grub_ntfs_file *mft;

  mft = (struct grub_ntfs_file *) dir;

  if (!mft->inode_read)
    {
      if (init_file (mft, mft->ino))
	return 0;
    }

  indx = NULL;
  bmp = NULL;

  at = &attr;
  init_attr (at, mft);
  while (1)
    {
      cur_pos = find_attr (at, GRUB_NTFS_AT_INDEX_ROOT);
      if (cur_pos == NULL)
	{
	  grub_error (GRUB_ERR_BAD_FS, "no $INDEX_ROOT");
	  goto done;
	}

      /* Resident, Namelen=4, Offset=0x18, Flags=0x00, Name="$I30" */
      if ((u32at (cur_pos, 8) != 0x180400) ||
	  (u32at (cur_pos, 0x18) != 0x490024) ||
	  (u32at (cur_pos, 0x1C) != 0x300033))
	continue;
      cur_pos += u16at (cur_pos, 0x14);
      if (*cur_pos != 0x30)	/* Not filename index */
	continue;
      break;
    }

  cur_pos += 0x10;		/* Skip index root */
  ret = list_file (mft, cur_pos + u16at (cur_pos, 0), hook, hook_data);
  if (ret)
    goto done;

  bitmap = NULL;
  bitmap_len = 0;
  free_attr (at);
  init_attr (at, mft);
  while ((cur_pos = find_attr (at, GRUB_NTFS_AT_BITMAP)) != NULL)
    {
      int ofs;

      ofs = cur_pos[0xA];
      /* Namelen=4, Name="$I30" */
      if ((cur_pos[9] == 4) &&
	  (u32at (cur_pos, ofs) == 0x490024) &&
	  (u32at (cur_pos, ofs + 4) == 0x300033))
	{
          int is_resident = (cur_pos[8] == 0);

          bitmap_len = ((is_resident) ? u32at (cur_pos, 0x10) :
                        u32at (cur_pos, 0x28));

          bmp = grub_malloc (bitmap_len);
          if (bmp == NULL)
            goto done;

	  if (is_resident)
	    {
              grub_memcpy (bmp, cur_pos + u16at (cur_pos, 0x14),
                           bitmap_len);
	    }
          else
            {
              if (read_data (at, cur_pos, bmp, 0, bitmap_len, 0, 0, 0))
                {
                  grub_error (GRUB_ERR_BAD_FS,
                              "fails to read non-resident $BITMAP");
                  goto done;
                }
              bitmap_len = u32at (cur_pos, 0x30);
            }

          bitmap = bmp;
	  break;
	}
    }

  free_attr (at);
  cur_pos = locate_attr (at, mft, GRUB_NTFS_AT_INDEX_ALLOCATION);
  while (cur_pos != NULL)
    {
      /* Non-resident, Namelen=4, Offset=0x40, Flags=0, Name="$I30" */
      if ((u32at (cur_pos, 8) == 0x400401) &&
	  (u32at (cur_pos, 0x40) == 0x490024) &&
	  (u32at (cur_pos, 0x44) == 0x300033))
	break;
      cur_pos = find_attr (at, GRUB_NTFS_AT_INDEX_ALLOCATION);
    }

  if ((!cur_pos) && (bitmap))
    {
      grub_error (GRUB_ERR_BAD_FS, "$BITMAP without $INDEX_ALLOCATION");
      goto done;
    }

  if (bitmap)
    {
      grub_disk_addr_t i;
      grub_uint8_t v;

      indx = grub_malloc (mft->data->idx_size << GRUB_NTFS_BLK_SHR);
      if (indx == NULL)
	goto done;

      v = 1;
      for (i = 0; i < (grub_disk_addr_t)bitmap_len * 8; i++)
	{
	  if (*bitmap & v)
	    {
	      if ((read_attr
		   (at, indx, i * (mft->data->idx_size << GRUB_NTFS_BLK_SHR),
		    (mft->data->idx_size << GRUB_NTFS_BLK_SHR), 0, 0, 0))
		  || (fixup (indx, mft->data->idx_size,
			     (const grub_uint8_t *) "INDX")))
		goto done;
	      ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)],
			       hook, hook_data);
	      if (ret)
		goto done;
	    }
	  v <<= 1;
	  if (!v)
	    {
	      v = 1;
	      bitmap++;
	    }
	}
    }

done:
  free_attr (at);
  grub_free (indx);
  grub_free (bmp);

  return ret;
}

static struct grub_ntfs_data *
grub_ntfs_mount (grub_disk_t disk)
{
  struct grub_ntfs_bpb bpb;
  struct grub_ntfs_data *data = 0;
  grub_uint32_t spc;

  if (!disk)
    goto fail;

  data = (struct grub_ntfs_data *) grub_zalloc (sizeof (*data));
  if (!data)
    goto fail;

  data->disk = disk;

  /* Read the BPB.  */
  if (grub_disk_read (disk, 0, 0, sizeof (bpb), &bpb))
    goto fail;

  if (grub_memcmp ((char *) &bpb.oem_name, "NTFS", 4) != 0
      || bpb.sectors_per_cluster == 0
      || (bpb.sectors_per_cluster & (bpb.sectors_per_cluster - 1)) != 0
      || bpb.bytes_per_sector == 0
      || (bpb.bytes_per_sector & (bpb.bytes_per_sector - 1)) != 0)
    goto fail;

  spc = (((grub_uint32_t) bpb.sectors_per_cluster
	  * (grub_uint32_t) grub_le_to_cpu16 (bpb.bytes_per_sector))
	 >> GRUB_NTFS_BLK_SHR);
  if (spc == 0)
    goto fail;

  for (data->log_spc = 0; (1U << data->log_spc) < spc; data->log_spc++);

  if (bpb.clusters_per_mft > 0)
    data->mft_size = ((grub_disk_addr_t) bpb.clusters_per_mft) << data->log_spc;
  else if (-bpb.clusters_per_mft < GRUB_NTFS_BLK_SHR || -bpb.clusters_per_mft >= 31)
    goto fail;
  else
    data->mft_size = 1ULL << (-bpb.clusters_per_mft - GRUB_NTFS_BLK_SHR);

  if (bpb.clusters_per_index > 0)
    data->idx_size = (((grub_disk_addr_t) bpb.clusters_per_index)
		      << data->log_spc);
  else if (-bpb.clusters_per_index < GRUB_NTFS_BLK_SHR || -bpb.clusters_per_index >= 31)
    goto fail;
  else
    data->idx_size = 1ULL << (-bpb.clusters_per_index - GRUB_NTFS_BLK_SHR);

  data->mft_start = grub_le_to_cpu64 (bpb.mft_lcn) << data->log_spc;

  if ((data->mft_size > GRUB_NTFS_MAX_MFT) || (data->idx_size > GRUB_NTFS_MAX_IDX))
    goto fail;

  data->mmft.data = data;
  data->cmft.data = data;

  data->mmft.buf = grub_malloc (data->mft_size << GRUB_NTFS_BLK_SHR);
  if (!data->mmft.buf)
    goto fail;

  if (grub_disk_read
      (disk, data->mft_start, 0, data->mft_size << GRUB_NTFS_BLK_SHR, data->mmft.buf))
    goto fail;

  data->uuid = grub_le_to_cpu64 (bpb.num_serial);

  if (fixup (data->mmft.buf, data->mft_size, (const grub_uint8_t *) "FILE"))
    goto fail;

  if (!locate_attr (&data->mmft.attr, &data->mmft, GRUB_NTFS_AT_DATA))
    goto fail;

  if (init_file (&data->cmft, GRUB_NTFS_FILE_ROOT))
    goto fail;

  return data;

fail:
  grub_error (GRUB_ERR_BAD_FS, "not an ntfs filesystem");

  if (data)
    {
      free_file (&data->mmft);
      free_file (&data->cmft);
      grub_free (data);
    }
  return 0;
}

/* Context for grub_ntfs_dir.  */
struct grub_ntfs_dir_ctx
{
  grub_fs_dir_hook_t hook;
  void *hook_data;
};

/* Helper for grub_ntfs_dir.  */
static int
grub_ntfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
		    grub_fshelp_node_t node, void *data)
{
  struct grub_ntfs_dir_ctx *ctx = data;
  struct grub_dirhook_info info;

  grub_memset (&info, 0, sizeof (info));
  info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
  info.mtimeset = 1;
  info.mtime = grub_divmod64 (node->mtime, 10000000, 0) 
    - 86400ULL * 365 * (1970 - 1601)
    - 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100);
  grub_free (node);
  return ctx->hook (filename, &info, ctx->hook_data);
}

static grub_err_t
grub_ntfs_dir (grub_device_t device, const char *path,
	       grub_fs_dir_hook_t hook, void *hook_data)
{
  struct grub_ntfs_dir_ctx ctx = { hook, hook_data };
  struct grub_ntfs_data *data = 0;
  struct grub_fshelp_node *fdiro = 0;

  grub_dl_ref (my_mod);

  data = grub_ntfs_mount (device->disk);
  if (!data)
    goto fail;

  grub_fshelp_find_file (path, &data->cmft, &fdiro, grub_ntfs_iterate_dir,
			 grub_ntfs_read_symlink, GRUB_FSHELP_DIR);

  if (grub_errno)
    goto fail;

  grub_ntfs_iterate_dir (fdiro, grub_ntfs_dir_iter, &ctx);

fail:
  if ((fdiro) && (fdiro != &data->cmft))
    {
      free_file (fdiro);
      grub_free (fdiro);
    }
  if (data)
    {
      free_file (&data->mmft);
      free_file (&data->cmft);
      grub_free (data);
    }

  grub_dl_unref (my_mod);

  return grub_errno;
}

static grub_err_t
grub_ntfs_open (grub_file_t file, const char *name)
{
  struct grub_ntfs_data *data = 0;
  struct grub_fshelp_node *mft = 0;

  grub_dl_ref (my_mod);

  data = grub_ntfs_mount (file->device->disk);
  if (!data)
    goto fail;

  grub_fshelp_find_file (name, &data->cmft, &mft, grub_ntfs_iterate_dir,
			 grub_ntfs_read_symlink, GRUB_FSHELP_REG);

  if (grub_errno)
    goto fail;

  if (mft != &data->cmft)
    {
      free_file (&data->cmft);
      grub_memcpy (&data->cmft, mft, sizeof (*mft));
      grub_free (mft);
      if (!data->cmft.inode_read)
	{
	  if (init_file (&data->cmft, data->cmft.ino))
	    goto fail;
	}
    }

  file->size = data->cmft.size;
  file->data = data;
  file->offset = 0;

  return 0;

fail:
  if (data)
    {
      free_file (&data->mmft);
      free_file (&data->cmft);
      grub_free (data);
    }

  grub_dl_unref (my_mod);

  return grub_errno;
}

static grub_ssize_t
grub_ntfs_read (grub_file_t file, char *buf, grub_size_t len)
{
  struct grub_ntfs_file *mft;

  mft = &((struct grub_ntfs_data *) file->data)->cmft;
  if (file->read_hook)
    mft->attr.save_pos = 1;

  read_attr (&mft->attr, (grub_uint8_t *) buf, file->offset, len, 1,
	     file->read_hook, file->read_hook_data);
  return (grub_errno) ? -1 : (grub_ssize_t) len;
}

static grub_err_t
grub_ntfs_close (grub_file_t file)
{
  struct grub_ntfs_data *data;

  data = file->data;

  if (data)
    {
      free_file (&data->mmft);
      free_file (&data->cmft);
      grub_free (data);
    }

  grub_dl_unref (my_mod);

  return grub_errno;
}

static grub_err_t
grub_ntfs_label (grub_device_t device, char **label)
{
  struct grub_ntfs_data *data = 0;
  struct grub_fshelp_node *mft = 0;
  grub_uint8_t *pa;

  grub_dl_ref (my_mod);

  *label = 0;

  data = grub_ntfs_mount (device->disk);
  if (!data)
    goto fail;

  grub_fshelp_find_file ("/$Volume", &data->cmft, &mft, grub_ntfs_iterate_dir,
			 0, GRUB_FSHELP_REG);

  if (grub_errno)
    goto fail;

  if (!mft->inode_read)
    {
      mft->buf = grub_malloc (mft->data->mft_size << GRUB_NTFS_BLK_SHR);
      if (mft->buf == NULL)
	goto fail;

      if (read_mft (mft->data, mft->buf, mft->ino))
	goto fail;
    }

  init_attr (&mft->attr, mft);
  pa = find_attr (&mft->attr, GRUB_NTFS_AT_VOLUME_NAME);
  if ((pa) && (pa[8] == 0) && (u32at (pa, 0x10)))
    {
      int len;

      len = u32at (pa, 0x10) / 2;
      pa += u16at (pa, 0x14);
      *label = get_utf8 (pa, len);
    }

fail:
  if ((mft) && (mft != &data->cmft))
    {
      free_file (mft);
      grub_free (mft);
    }
  if (data)
    {
      free_file (&data->mmft);
      free_file (&data->cmft);
      grub_free (data);
    }

  grub_dl_unref (my_mod);

  return grub_errno;
}

static grub_err_t
grub_ntfs_uuid (grub_device_t device, char **uuid)
{
  struct grub_ntfs_data *data;
  grub_disk_t disk = device->disk;

  grub_dl_ref (my_mod);

  data = grub_ntfs_mount (disk);
  if (data)
    {
      char *ptr;
      *uuid = grub_xasprintf ("%016llx", (unsigned long long) data->uuid);
      if (*uuid)
	for (ptr = *uuid; *ptr; ptr++)
	  *ptr = grub_toupper (*ptr);
      free_file (&data->mmft);
      free_file (&data->cmft);
      grub_free (data);
    }
  else
    *uuid = NULL;

  grub_dl_unref (my_mod);

  return grub_errno;
}

static struct grub_fs grub_ntfs_fs =
  {
    .name = "ntfs",
    .dir = grub_ntfs_dir,
    .open = grub_ntfs_open,
    .read = grub_ntfs_read,
    .close = grub_ntfs_close,
    .label = grub_ntfs_label,
    .uuid = grub_ntfs_uuid,
#ifdef GRUB_UTIL
    .reserved_first_sector = 1,
    .blocklist_install = 1,
#endif
    .next = 0
};

GRUB_MOD_INIT (ntfs)
{
  grub_fs_register (&grub_ntfs_fs);
  my_mod = mod;
}

GRUB_MOD_FINI (ntfs)
{
  grub_fs_unregister (&grub_ntfs_fs);
}
