+ tRAMFS_File *file = Node->ImplPtr;
+
+ return RAMFS_int_DoIO(file, Offset, Size, Buffer, 1);
+}
+
+size_t RAMFS_Write(tVFS_Node *Node, off_t Offset, size_t Size, const void *Buffer)
+{
+ tRAMFS_File *file = Node->ImplPtr;
+
+ // TODO: Limit checks?
+ if( Offset == file->Size )
+ file->Size += Size;
+
+ return RAMFS_int_DoIO(file, Offset, Size, (void*)Buffer, 0);
+}
+
+// --- Internals ---
+void *RAMFS_int_GetPage(tRAMFS_File *File, int Page, int bCanAlloc)
+{
+ Uint32 page_id = 0;
+ Uint32 *page_in_1 = NULL;
+ Uint32 *page_in_2 = NULL;
+
+ int ofs = 0, block;
+
+ 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;