/*
 * COPYRIGHT:        See COPYING in the top level directory
 * PROJECT:          ReactOS kernel
 * FILE:             services/fs/minix/minix.c
 * PURPOSE:          Minix FSD
 * PROGRAMMER:       David Welch (welch@mcmail.com)
 * UPDATE HISTORY:
 */

/* INCLUDES *****************************************************************/

#include <ntddk.h>
#include <string.h>
#include "bitops.h"
#include <ntifs.h>

#define NDEBUG
#include <debug.h>

#include "minix.h"

/* FUNCTIONS ****************************************************************/

NTSTATUS MinixDeleteInode(PDEVICE_OBJECT Volume,
			  MINIX_DEVICE_EXTENSION* DeviceExt,
			  ULONG ino)
{
   PULONG Buffer;
   ULONG off;

   Buffer = ExAllocatePool(NonPagedPool,BLOCKSIZE);
   MinixReadSector(Volume, (ino / 8192)+2, (PVOID)Buffer);
   off = ino % 8192;
   clear_bit(off%32,&Buffer[off/32]);
   MinixWriteSector(Volume, (ino / 8192)+2, (PVOID)Buffer);
   return(STATUS_SUCCESS);
}

static ULONG MinixAllocateInode(PDEVICE_OBJECT Volume,
				MINIX_DEVICE_EXTENSION* DeviceExt)
{
   ULONG i;
   PULONG Buffer;
   ULONG ino;

   Buffer = ExAllocatePool(NonPagedPool,BLOCKSIZE);
   for (i=0; i<DeviceExt->sb->s_imap_blocks; i++)
     {
	MinixReadSector(Volume,i + 2,Buffer);
	ino = find_first_zero_bit(Buffer,8192);
	if (ino < 8192)
	  {
	     set_bit(ino%32,&Buffer[32]);
	     MinixWriteSector(Volume,i + 2,Buffer);
	     ExFreePool(Buffer);
	     return(ino + (i*8192));
	  }
     }
   ExFreePool(Buffer);
   return(0);
}

ULONG MinixNewInode(PDEVICE_OBJECT Volume,
		    MINIX_DEVICE_EXTENSION* DeviceExt,
		    struct minix_inode* new_inode)
{
   ULONG ino;

   ino = MinixAllocateInode(Volume,DeviceExt);
   if (ino == 0)
     {
	return(0);
     }
   MinixWriteInode(Volume,DeviceExt,ino,new_inode);
   return(ino);
}

NTSTATUS MinixWriteInode(PDEVICE_OBJECT Volume,
			 MINIX_DEVICE_EXTENSION* DeviceExt,
			 ULONG ino,
			 struct minix_inode* result)
{
   int block;
   char* buffer;
   struct minix_inode* inodes;

   DPRINT("MinixWriteInode(ino %x, result %x)\n",ino,result);

   buffer = ExAllocatePool(NonPagedPool,1024);
   inodes = (struct minix_inode *)buffer;

   block = 2 + DeviceExt->sb->s_imap_blocks + DeviceExt->sb->s_zmap_blocks
           + ((ino-1) / MINIX_INODES_PER_BLOCK);
   MinixReadSector(Volume,block,buffer);
   memcpy(&inodes[(ino-1)%MINIX_INODES_PER_BLOCK],result,
	  sizeof(struct minix_inode));
   MinixWriteSector(Volume,block,buffer);

   ExFreePool(buffer);
   return(STATUS_SUCCESS);
}

NTSTATUS MinixReadInode(PDEVICE_OBJECT DeviceObject,
			MINIX_DEVICE_EXTENSION* DeviceExt,
			ULONG ino,
			struct minix_inode* result)
{
   int block;
   struct minix_inode* inodes;
   PVOID BaseAddress;

   DPRINT("MinixReadInode(ino %x, result %x)\n",ino,result);

   block = 2 + DeviceExt->sb->s_imap_blocks + DeviceExt->sb->s_zmap_blocks
           + ((ino-1) / MINIX_INODES_PER_BLOCK);
   DPRINT("Reading block %x offset %x\n",block,block*BLOCKSIZE);
   DPRINT("Index %x\n",(ino-1)%MINIX_INODES_PER_BLOCK);

   BaseAddress = ExAllocatePool(NonPagedPool, PAGE_SIZE);

   MinixReadPage(DeviceObject,
		 block,
		 BaseAddress);

   inodes = (struct minix_inode *)(BaseAddress + ((block % 4) * 512));

   memcpy(result,
	  &inodes[(ino-1)%MINIX_INODES_PER_BLOCK],
	  sizeof(struct minix_inode));
   DPRINT("result->i_uid %x\n",result->i_uid);
   DPRINT("result->i_size %x\n",result->i_size);

   ExFreePool(BaseAddress);

   return(STATUS_SUCCESS);
}
