+ if( Page < 0 ) return NULL;
+
+ if( Page < RAMFS_NDIRECT )
+ {
+ if( File->PagesDirect[Page] )
+ page_id = File->PagesDirect[Page];
+ }
+ else if( Page - RAMFS_NDIRECT < PAGE_SIZE/4 )
+ {
+ ofs = Page - RAMFS_NDIRECT;
+ if( File->Indirect1Page == 0 ) {
+ if( !bCanAlloc )
+ return NULL;
+ else
+ File->Indirect1Page = RAMFS_int_AllocatePage(File->Inode.Disk) + 1;
+ }
+ page_in_1 = MM_MapTemp( File->Inode.Disk->PhysPages[File->Indirect1Page-1] );
+ page_id = page_in_1[ofs];
+ }
+ else if( Page - RAMFS_NDIRECT - PAGE_SIZE/4 < (PAGE_SIZE/4)*(PAGE_SIZE/4) )
+ {
+ block = (Page - RAMFS_NDIRECT - PAGE_SIZE/4) / (PAGE_SIZE/4);
+ ofs = (Page - RAMFS_NDIRECT - PAGE_SIZE/4) % (PAGE_SIZE/4);
+ if( File->Indirect2Page == 0 ){
+ if( !bCanAlloc )
+ return NULL;
+ else
+ File->Indirect2Page = RAMFS_int_AllocatePage(File->Inode.Disk) + 1;
+ }
+
+ page_in_2 = MM_MapTemp( File->Inode.Disk->PhysPages[File->Indirect2Page-1] );
+ if( page_in_2[block] == 0 ) {
+ if( !bCanAlloc )
+ return NULL;
+ else
+ page_in_2[block] = RAMFS_int_AllocatePage(File->Inode.Disk) + 1;
+ }
+
+ page_in_1 = MM_MapTemp( File->Inode.Disk->PhysPages[page_in_2[block] - 1] );
+ page_id = page_in_1[ofs];
+ }
+
+ if( page_id == 0 )
+ {
+ if( !bCanAlloc )
+ return NULL;
+
+ page_id = RAMFS_int_AllocatePage(File->Inode.Disk) + 1;
+ if(page_in_1)
+ page_in_1[ofs] = page_id;
+ else
+ File->PagesDirect[Page] = page_id;
+ }
+
+ MM_FreeTemp( page_in_1 );
+ MM_FreeTemp( page_in_2 );
+
+ return MM_MapTemp( File->Inode.Disk->PhysPages[page_id - 1] );
+}
+
+void RAMFS_int_DropPage(void *Page)
+{
+ MM_FreeTemp( Page );
+}
+
+Uint32 RAMFS_int_AllocatePage(tRAMDisk *Disk)
+{
+ int i, j;
+
+ // Quick check
+ if( Disk->nUsedPages == Disk->MaxPages )
+ return 0;
+
+ // Find a chunk with at least one free page
+ for( i = 0; i < Disk->MaxPages / 32; i ++ )
+ {
+ if( Disk->Bitmap[i] != -1 )
+ break;
+ }
+ if( i == Disk->MaxPages / 32 ) {
+ Log_Error("RAMFS", "Bookkeeping error, count and bitmap disagree");
+ return 0;
+ }
+
+ // Find the exact page
+ for( j = 0; j < 32; j ++ )
+ {
+ if( !(Disk->Bitmap[i] & (1U << j)) )
+ break ;
+ }
+ ASSERT(j < 32);
+
+ return i * 32 + j;
+}
+
+void RAMFS_int_RefFile(tRAMFS_Inode *Inode)
+{
+ Inode->nLink ++;
+}
+
+void RAMFS_int_DerefFile(tRAMFS_Inode *Inode)
+{
+ Inode->nLink --;
+ if( Inode->nLink >= 0 )
+ return ;
+
+ Log_Error("RAMFS", "TODO: Clean up files when deleted");
+
+ // Need to delete file
+ switch( Inode->Type )
+ {
+ case 0: // File
+ break ;
+ case 1: // Directory
+ break ;
+ case 2: // Symlink
+ break ;
+ }
+ free(Inode);
+}