Pretend to allocate/deallocate memory correctly
[yaboot.git] / second / fs_ext2.c
index e2a5070f7a4480416e1aae2238a89bdbf91e8f7b..82db81a2e7bf1a9864c97f71d72ede81014773a0 100644 (file)
@@ -1,29 +1,29 @@
-/* ext2 filesystem
-   
-   Copyright (C) 1999 Benjamin Herrenschmidt
-
-   Adapted from quik/silo
-
-   Copyright (C) 1996 Maurizio Plaza
-                1996 Jakub Jelinek
-   
-   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 2 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, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-   Note: This version is way too slow due to the way we use bmap. This
        should be replaced by an iterator.
-*/
+/*
+ *  fs_ext2.c - an implementation for the Ext2/Ext3 filesystem
+ *
+ *  Copyright (C) 2001, 2002 Ethan Benson
+ *
+ *  Copyright (C) 1999 Benjamin Herrenschmidt
+ *
+ *  Adapted from quik/silo
+ *
+ *  Copyright (C) 1996 Maurizio Plaza
+ *                1996 Jakub Jelinek
+ *
+ *  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 2 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, write to the Free Software
*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
 
 #include "ctype.h"
 #include "types.h"
@@ -33,6 +33,8 @@
 #include "string.h"
 #include "partition.h"
 #include "fs.h"
+#include "errors.h"
+#include "debug.h"
 
 #define FAST_VERSION
 #define MAX_READ_RANGE 256
@@ -55,11 +57,11 @@ static int ext2_close(      struct boot_file_t*     file);
 
 struct fs_t ext2_filesystem =
 {
-    "ext2",
-    ext2_open,
-    ext2_read,
-    ext2_seek,
-    ext2_close
+     "ext2",
+     ext2_open,
+     ext2_read,
+     ext2_seek,
+     ext2_close
 };
 
 /* IO manager structure for the ext2 library */
@@ -73,14 +75,14 @@ static errcode_t linux_flush (io_channel channel);
 
 static struct struct_io_manager struct_linux_manager =
 {
-    EXT2_ET_MAGIC_IO_MANAGER,
-    "linux I/O Manager",
-    linux_open,
-    linux_close,
-    linux_set_blksize,
-    linux_read_blk,
-    linux_write_blk,
-    linux_flush
+     EXT2_ET_MAGIC_IO_MANAGER,
+     "linux I/O Manager",
+     linux_open,
+     linux_close,
+     linux_set_blksize,
+     linux_read_blk,
+     linux_write_blk,
+     linux_flush
 };
 
 static io_manager linux_io_manager = &struct_linux_manager;
@@ -114,7 +116,7 @@ static struct ext2_inode cur_inode;
 
 void com_err (const char *a, long i, const char *fmt,...)
 {
-    prom_printf ((char *) fmt);
+     prom_printf ((char *) fmt);
 }
 
 static int
@@ -123,131 +125,145 @@ ext2_open(      struct boot_file_t*     file,
                struct partition_t*     part,
                const char*             file_name)
 {
-       int result = 0;
-       static char buffer[1024];
-       int ofopened = 0;
+     int result = 0;
+     int error = FILE_ERR_NOTFOUND;
+     static char buffer[1024];
+     int ofopened = 0;
        
-        DEBUG_ENTER;
-        DEBUG_OPEN;
-
-       if (opened) {
-               prom_printf("ext2_open() : fs busy\n");
-               return FILE_ERR_NOTFOUND;
-       }
-       if (file->device_kind != FILE_DEVICE_BLOCK) {
-               prom_printf("Can't open ext2 filesystem on non-block device\n");
-               return FILE_ERR_NOTFOUND;
-       }
-
-       fs = NULL;
+     DEBUG_ENTER;
+     DEBUG_OPEN;
+
+     if (opened) {
+         DEBUG_LEAVE(FILE_ERR_FSBUSY);
+         return FILE_ERR_FSBUSY;
+     }
+     if (file->device_kind != FILE_DEVICE_BLOCK) {
+         DEBUG_LEAVE(FILE_ERR_BADDEV);
+         return FILE_ERR_BADDEV;
+     }
+
+     fs = NULL;
        
-       /* We don't care too much about the device block size since we run
-        * thru the deblocker. We may have to change that is we plan to be
-        * compatible with older versions of OF
-        */
-       bs = 1024;
-       doff = 0;
-       if (part)
-           doff = (unsigned long long)(part->part_start) * part->blocksize;
-       cur_file = file;
-
+     /* We don't care too much about the device block size since we run
+      * thru the deblocker. We may have to change that is we plan to be
+      * compatible with older versions of OF
+      */
+     bs = 1024;
+     doff = 0;
+     if (part)
+         doff = (unsigned long long)(part->part_start) * part->blocksize;
+     cur_file = file;
 
-       DEBUG_F("partition offset: %d\n", doff);
 
-       /* Open the OF device for the entire disk */
-       strncpy(buffer, dev_name, 1020);
-       strcat(buffer, ":0");
+     DEBUG_F("partition offset: %Lu\n", doff);
 
-       DEBUG_F("<%s>\n", buffer);
+     /* Open the OF device for the entire disk */
+     strncpy(buffer, dev_name, 1020);
+     strcat(buffer, ":0");
 
-       file->of_device = prom_open(buffer);
+     DEBUG_F("<%s>\n", buffer);
 
-       DEBUG_F("file->of_device = %08lx\n", file->of_device);
+     file->of_device = prom_open(buffer);
 
-       if (file->of_device == PROM_INVALID_HANDLE) {
+     DEBUG_F("file->of_device = %p\n", file->of_device);
 
-               DEBUG_F("Can't open device %s\n", file->of_device);
+     if (file->of_device == PROM_INVALID_HANDLE) {
 
-               return FILE_ERR_NOTFOUND;
-       }
-       ofopened = 1;
+         DEBUG_F("Can't open device %p\n", file->of_device);
+         DEBUG_LEAVE(FILE_IOERR);
+         return FILE_IOERR;
+     }
+     ofopened = 1;
        
-       /* Open the ext2 filesystem */
-       result = ext2fs_open (buffer, EXT2_FLAG_RW, 0, 0, linux_io_manager, &fs);
-       if (result) {
-
-            if(result == EXT2_ET_BAD_MAGIC)
-            {
-                DEBUG_F( "ext2fs_open returned bad magic loading file %s\n",
-                         file );
-            }
-            else
-            {
-                DEBUG_F( "ext2fs_open error #%d while loading file %s\n",
-                         result, file_name);
-            }
-
-           goto bail;
-       }
-
-       /* Allocate the block buffer */
-       block_buffer = malloc(fs->blocksize * 2);
-       if (!block_buffer) {
-
-           DEBUG_F("ext2fs: can't alloc block buffer (%d bytes)\n", fs->blocksize * 2);
-
-           goto bail;
-       }
+     /* Open the ext2 filesystem */
+     result = ext2fs_open (buffer, EXT2_FLAG_RW, 0, 0, linux_io_manager, &fs);
+     if (result) {
+
+         if(result == EXT2_ET_BAD_MAGIC)
+         {
+              DEBUG_F( "ext2fs_open returned bad magic loading file %p\n",
+                       file );
+         }
+         else
+         {
+              DEBUG_F( "ext2fs_open error #%d while loading file %s\n",
+                       result, file_name);
+         }
+         error = FILE_ERR_BAD_FSYS;
+         goto bail;
+     }
+
+     /* Allocate the block buffer */
+     block_buffer = malloc(fs->blocksize * 2);
+     if (!block_buffer) {
+
+         DEBUG_F("ext2fs: can't alloc block buffer (%d bytes)\n", fs->blocksize * 2);
+         error = FILE_IOERR;
+         goto bail;
+     }
        
-       /* Lookup file by pathname */
-       root = cwd = EXT2_ROOT_INO;
-       result = ext2fs_namei_follow(fs, root, cwd, file_name, &file->inode);
-       if (result) {
-
-           DEBUG_F("ext2fs_namei error #%d while loading file %s\n", result, file_name);
-           goto bail;
-       }
+     /* Lookup file by pathname */
+     root = cwd = EXT2_ROOT_INO;
+     result = ext2fs_namei_follow(fs, root, cwd, file_name, &file->inode);
+     if (result) {
+
+         DEBUG_F("ext2fs_namei error #%d while loading file %s\n", result, file_name);
+         if (result == EXT2_ET_SYMLINK_LOOP)
+              error = FILE_ERR_SYMLINK_LOOP;
+         else if (result == EXT2_ET_FILE_NOT_FOUND)
+              error = FILE_ERR_NOTFOUND;
+         else
+              error = FILE_IOERR;
+         goto bail;
+     }
 
 #if 0
-       result = ext2fs_follow_link(fs, root, cwd,  file->inode, &file->inode);
-       if (result) {
-
-           DEBUG_F("ext2fs_follow_link error #%d while loading file %s\n", result, file_name);
+     result = ext2fs_follow_link(fs, root, cwd,  file->inode, &file->inode);
+     if (result) {
 
-           goto bail;
-       }
+         DEBUG_F("ext2fs_follow_link error #%d while loading file %s\n", result, file_name);
+         error = FILE_ERR_NOTFOUND;
+         goto bail;
+     }
 #endif 
 
 #ifndef FAST_VERSION
-       result = ext2fs_read_inode(fs, file->inode, &cur_inode);
-       if (result) {
-
-           DEBUG_F("ext2fs_read_inode error #%d while loading file %s\n", result, file_name);
-
-           goto bail;
-       }
+     result = ext2fs_read_inode(fs, file->inode, &cur_inode);
+     if (result) {
+
+         DEBUG_F("ext2fs_read_inode error #%d while loading file %s\n", result, file_name);
+         if (result == EXT2_ET_FILE_TOO_BIG)
+              error = FILE_ERR_LENGTH;
+         else if (result == EXT2_ET_LLSEEK_FAILED)
+              error = FILE_CANT_SEEK;
+         else if (result ==  EXT2_ET_FILE_NOT_FOUND)
+              error = FILE_ERR_NOTFOUND;
+         else
+              error = FILE_IOERR;
+         goto bail;
+     }
 #endif /* FAST_VERSION */
-       file->pos = 0;
+     file->pos = 0;
        
-       opened = 1;
+     opened = 1;
 bail:
-       if (!opened) {
-           if (fs)
-               ext2fs_close(fs);
-           fs = NULL;
-           if (ofopened)
-               prom_close(file->of_device);
-           if (block_buffer)
-               free(block_buffer);
-           block_buffer = NULL;
-           cur_file = NULL;
+     if (!opened) {
+         if (fs)
+              ext2fs_close(fs);
+         fs = NULL;
+         if (ofopened)
+              prom_close(file->of_device);
+         if (block_buffer)
+              free(block_buffer);
+         block_buffer = NULL;
+         cur_file = NULL;
            
-            DEBUG_LEAVE(FILE_ERR_NOTFOUND);
-           return FILE_ERR_NOTFOUND;
-       }
+         DEBUG_LEAVE_F(error);
+         return error;
+     }
 
-       DEBUG_LEAVE(FILE_ERR_OK);
-       return FILE_ERR_OK;
+     DEBUG_LEAVE(FILE_ERR_OK);
+     return FILE_ERR_OK;
 }
 
 #ifdef FAST_VERSION
@@ -255,158 +271,158 @@ bail:
 static int
 read_dump_range(void)
 {
-       int count = read_range_count;
-       int size;
+     int count = read_range_count;
+     int size;
 
 #ifdef VERBOSE_DEBUG
-       DEBUG_F("   dumping range: start: 0x%x count: 0x%x\n",
-               read_range_count, read_range_start);
+     DEBUG_F("   dumping range: start: 0x%x count: 0x%x\n",
+            read_range_count, read_range_start);
 #endif
-       /* Check if we need to handle a special case for the last block */
-       if ((count * bs) > read_max)
-               count--;
-       if (count) {
-               size = count * bs;      
-               read_result = io_channel_read_blk(fs->io, read_range_start, count, read_buffer);
-               if (read_result)
-                       return BLOCK_ABORT;
-               read_buffer += size;
-               read_max -= size;
-               read_total += size;
-               read_cur_file->pos += size;
-               read_range_count -= count;
-               read_range_start += count;
-               read_last_logical += count;
-       }       
-       /* Handle remaining block */
-       if (read_max && read_range_count) {
-               read_result = io_channel_read_blk(fs->io, read_range_start, 1, block_buffer);
-               if (read_result)
-                       return BLOCK_ABORT;
-               memcpy(read_buffer, block_buffer, read_max);
-               read_cur_file->pos += read_max;
-               read_total += read_max;
-               read_max = 0;
-       }
-       read_range_count = read_range_start = 0;
-
-       return (read_max == 0) ? BLOCK_ABORT : 0;
+     /* Check if we need to handle a special case for the last block */
+     if ((count * bs) > read_max)
+         count--;
+     if (count) {
+         size = count * bs;    
+         read_result = io_channel_read_blk(fs->io, read_range_start, count, read_buffer);
+         if (read_result)
+              return BLOCK_ABORT;
+         read_buffer += size;
+         read_max -= size;
+         read_total += size;
+         read_cur_file->pos += size;
+         read_range_count -= count;
+         read_range_start += count;
+         read_last_logical += count;
+     } 
+     /* Handle remaining block */
+     if (read_max && read_range_count) {
+         read_result = io_channel_read_blk(fs->io, read_range_start, 1, block_buffer);
+         if (read_result)
+              return BLOCK_ABORT;
+         memcpy(read_buffer, block_buffer, read_max);
+         read_cur_file->pos += read_max;
+         read_total += read_max;
+         read_max = 0;
+     }
+     read_range_count = read_range_start = 0;
+
+     return (read_max == 0) ? BLOCK_ABORT : 0;
 }
 
 static int
 read_iterator(ext2_filsys fs, blk_t *blocknr, int lg_block, void *private)
 {
 #ifdef VERBOSE_DEBUG
-    DEBUG_F("read_it: p_bloc: 0x%x, l_bloc: 0x%x, f_pos: 0x%x, rng_pos: 0x%x   ",
-       *blocknr, lg_block, read_cur_file->pos, read_last_logical);
+     DEBUG_F("read_it: p_bloc: 0x%x, l_bloc: 0x%x, f_pos: 0x%x, rng_pos: 0x%x   ",
+            *blocknr, lg_block, read_cur_file->pos, read_last_logical);
 #endif
-    if (lg_block < 0) {
+     if (lg_block < 0) {
 #ifdef VERBOSE_DEBUG
-       DEBUG_F(" <skip lg>\n");
+         DEBUG_F(" <skip lg>\n");
 #endif
-       return 0;
-    }
+         return 0;
+     }
 
-    /* If we have not reached the start block yet, we skip */
-    if (lg_block < read_cur_file->pos / bs) {
+     /* If we have not reached the start block yet, we skip */
+     if (lg_block < read_cur_file->pos / bs) {
 #ifdef VERBOSE_DEBUG
-       DEBUG_F(" <skip pos>\n");
+         DEBUG_F(" <skip pos>\n");
 #endif
-       return 0;
-    }
-
-    /* If block is contiguous to current range, just extend range,
-     * exit if we pass the remaining bytes count to read
-     */
-    if (read_range_start && read_range_count < MAX_READ_RANGE
-       && (*blocknr == read_range_start + read_range_count)
-       && (lg_block == read_last_logical + read_range_count)) {
+         return 0;
+     }
+
+     /* If block is contiguous to current range, just extend range,
+      * exit if we pass the remaining bytes count to read
+      */
+     if (read_range_start && read_range_count < MAX_READ_RANGE
+        && (*blocknr == read_range_start + read_range_count)
+        && (lg_block == read_last_logical + read_range_count)) {
 #ifdef VERBOSE_DEBUG
-       DEBUG_F(" block in range\n");
+         DEBUG_F(" block in range\n");
 #endif
-       ++read_range_count;
-       return ((read_range_count * bs) >= read_max) ? BLOCK_ABORT : 0;
-    }
+         ++read_range_count;
+         return ((read_range_count * bs) >= read_max) ? BLOCK_ABORT : 0;
+     }
     
-    /* Range doesn't match. Dump existing range */
-    if (read_range_start) {
+     /* Range doesn't match. Dump existing range */
+     if (read_range_start) {
 #ifdef VERBOSE_DEBUG
-       DEBUG_F(" calling dump range \n");
+         DEBUG_F(" calling dump range \n");
 #endif
-       if (read_dump_range())
-               return BLOCK_ABORT;
-    }
+         if (read_dump_range())
+              return BLOCK_ABORT;
+     }
 
-    /* Here we handle holes in the file */
-    if (lg_block && lg_block != read_last_logical) {
-       unsigned long nzero;
+     /* Here we handle holes in the file */
+     if (lg_block && lg_block != read_last_logical) {
+         unsigned long nzero;
 #ifdef VERBOSE_DEBUG
-       DEBUG_F(" hole from lg_bloc 0x%x\n", read_last_logical);
+         DEBUG_F(" hole from lg_bloc 0x%x\n", read_last_logical);
 #endif
-       if (read_cur_file->pos % bs) {
-               int offset = read_cur_file->pos % bs;
-               int size = bs - offset;
-               if (size > read_max)
-                       size = read_max;
-               memset(read_buffer, 0, size);
-               read_max -= size;
-               read_total += size;
-               read_buffer += size;
-               read_cur_file->pos += size;
-               ++read_last_logical;
-               if (read_max == 0)
-                       return BLOCK_ABORT;
-       }
-       nzero = (lg_block - read_last_logical) * bs;
-       if (nzero) {
-               if (nzero > read_max)
-                       nzero = read_max;
-               memset(read_buffer, 0, nzero);
-               read_max -= nzero;
-               read_total += nzero;
-               read_buffer += nzero;
-               read_cur_file->pos += nzero;
-               if (read_max == 0)
-                       return BLOCK_ABORT;
-       }
-       read_last_logical = lg_block;
-    }
+         if (read_cur_file->pos % bs) {
+              int offset = read_cur_file->pos % bs;
+              int size = bs - offset;
+              if (size > read_max)
+                   size = read_max;
+              memset(read_buffer, 0, size);
+              read_max -= size;
+              read_total += size;
+              read_buffer += size;
+              read_cur_file->pos += size;
+              ++read_last_logical;
+              if (read_max == 0)
+                   return BLOCK_ABORT;
+         }
+         nzero = (lg_block - read_last_logical) * bs;
+         if (nzero) {
+              if (nzero > read_max)
+                   nzero = read_max;
+              memset(read_buffer, 0, nzero);
+              read_max -= nzero;
+              read_total += nzero;
+              read_buffer += nzero;
+              read_cur_file->pos += nzero;
+              if (read_max == 0)
+                   return BLOCK_ABORT;
+         }
+         read_last_logical = lg_block;
+     }
 
      /* If we are not aligned, handle that case */
-    if (read_cur_file->pos % bs) {
-       int offset = read_cur_file->pos % bs;
-       int size = bs - offset;
+     if (read_cur_file->pos % bs) {
+         int offset = read_cur_file->pos % bs;
+         int size = bs - offset;
 #ifdef VERBOSE_DEBUG
-       DEBUG_F(" handle unaligned start\n");
+         DEBUG_F(" handle unaligned start\n");
 #endif
-       read_result = io_channel_read_blk(fs->io, *blocknr, 1, block_buffer);
-       if (read_result)
-           return BLOCK_ABORT;
-       if (size > read_max)
-               size = read_max;
-       memcpy(read_buffer, block_buffer + offset, size);
-       read_cur_file->pos += size;
-       read_max -= size;
-       read_total += size;
-       read_buffer += size;
-       read_last_logical = lg_block + 1;
-       return (read_max == 0) ? BLOCK_ABORT : 0;
-    }
-
-   /* If there is still a physical block to add, then create a new range */
-    if (*blocknr) {
+         read_result = io_channel_read_blk(fs->io, *blocknr, 1, block_buffer);
+         if (read_result)
+              return BLOCK_ABORT;
+         if (size > read_max)
+              size = read_max;
+         memcpy(read_buffer, block_buffer + offset, size);
+         read_cur_file->pos += size;
+         read_max -= size;
+         read_total += size;
+         read_buffer += size;
+         read_last_logical = lg_block + 1;
+         return (read_max == 0) ? BLOCK_ABORT : 0;
+     }
+
+     /* If there is still a physical block to add, then create a new range */
+     if (*blocknr) {
 #ifdef VERBOSE_DEBUG
-       DEBUG_F(" new range\n");
+         DEBUG_F(" new range\n");
 #endif
-        read_range_start = *blocknr;
-        read_range_count = 1;
-        return (bs >= read_max) ? BLOCK_ABORT : 0;
-    }
+         read_range_start = *blocknr;
+         read_range_count = 1;
+         return (bs >= read_max) ? BLOCK_ABORT : 0;
+     }
     
 #ifdef VERBOSE_DEBUG
-       DEBUG_F("\n");
+     DEBUG_F("\n");
 #endif
-    return 0;
+     return 0;
 }
 
 #endif /* FAST_VERSION */
@@ -416,89 +432,89 @@ ext2_read(        struct boot_file_t*     file,
                unsigned int            size,
                void*                   buffer)
 {
-       errcode_t retval;
+     errcode_t retval;
 
 #ifdef FAST_VERSION
-       if (!opened)
-           return FILE_ERR_NOTFOUND;
+     if (!opened)
+         return FILE_IOERR;
 
 
-       DEBUG_F("ext_read() from pos 0x%x, size: 0x%x\n", file->pos, size);
+     DEBUG_F("ext_read() from pos 0x%Lx, size: 0x%ux\n", file->pos, size);
 
 
-       read_cur_file = file;
-       read_range_start = 0;
-       read_range_count = 0;
-       read_last_logical = file->pos / bs;
-       read_total = 0;
-       read_max = size;
-       read_buffer = (unsigned char*)buffer;
-       read_result = 0;
+     read_cur_file = file;
+     read_range_start = 0;
+     read_range_count = 0;
+     read_last_logical = file->pos / bs;
+     read_total = 0;
+     read_max = size;
+     read_buffer = (unsigned char*)buffer;
+     read_result = 0;
     
-       retval = ext2fs_block_iterate(fs, file->inode, 0, 0, read_iterator, 0);
-       if (retval == BLOCK_ABORT)
-               retval = read_result;
-       if (!retval && read_range_start) {
+     retval = ext2fs_block_iterate(fs, file->inode, 0, 0, read_iterator, 0);
+     if (retval == BLOCK_ABORT)
+         retval = read_result;
+     if (!retval && read_range_start) {
 #ifdef VERBOSE_DEBUG
-               DEBUG_F("on exit: range_start is 0x%x, calling dump...\n",
-                       read_range_start);
+         DEBUG_F("on exit: range_start is 0x%x, calling dump...\n",
+                 read_range_start);
 #endif
-               read_dump_range();
-               retval = read_result;
-       }
-       if (retval)
-               prom_printf ("ext2: i/o error %d in read\n", retval);
+         read_dump_range();
+         retval = read_result;
+     }
+     if (retval)
+         prom_printf ("ext2: i/o error %ld in read\n", (long) retval);
                
-       return read_total;
+     return read_total;
 
 #else /* FAST_VERSION */
-       int status;
-       unsigned int read = 0;
+     int status;
+     unsigned int read = 0;
        
-       if (!opened)
-           return FILE_ERR_NOTFOUND;
+     if (!opened)
+         return FILE_IOERR;
 
 
-       DEBUG_F("ext_read() from pos 0x%x, size: 0x%x\n", file->pos, size);
+     DEBUG_F("ext_read() from pos 0x%x, size: 0x%x\n", file->pos, size);
 
 
-       while(size) {   
-           blk_t fblock = file->pos / bs;
-           blk_t pblock;
-           unsigned int blkorig, s, b;
+     while(size) {     
+         blk_t fblock = file->pos / bs;
+         blk_t pblock;
+         unsigned int blkorig, s, b;
        
-           pblock = 0;
-           status = ext2fs_bmap(fs, file->inode, &cur_inode,
-                       block_buffer, 0, fblock, &pblock);
-           if (status) {
-
-               DEBUG_F("ext2fs_bmap(fblock:%d) return: %d\n", fblock, status);
-               return read;
-           }
-           blkorig = fblock * bs;
-           b = file->pos - blkorig;
-           s = ((bs - b) > size) ? size : (bs - b);
-           if (pblock) {
-               unsigned long long pos =
-                 ((unsigned long long)pblock) * (unsigned long long)bs;
-               pos += doff;
-               prom_lseek(file->of_device, pos);
-               status = prom_read(file->of_device, block_buffer, bs);
-               if (status != bs) {
+         pblock = 0;
+         status = ext2fs_bmap(fs, file->inode, &cur_inode,
+                              block_buffer, 0, fblock, &pblock);
+         if (status) {
+
+              DEBUG_F("ext2fs_bmap(fblock:%d) return: %d\n", fblock, status);
+              return read;
+         }
+         blkorig = fblock * bs;
+         b = file->pos - blkorig;
+         s = ((bs - b) > size) ? size : (bs - b);
+         if (pblock) {
+              unsigned long long pos =
+                   ((unsigned long long)pblock) * (unsigned long long)bs;
+              pos += doff;
+              prom_lseek(file->of_device, pos);
+              status = prom_read(file->of_device, block_buffer, bs);
+              if (status != bs) {
                    prom_printf("ext2: io error in read, ex: %d, got: %d\n",
-                       bs, status);
+                               bs, status);
                    return read;
-               }
-           } else
-               memset(block_buffer, 0, bs);
-
-          memcpy(buffer, block_buffer + b, s);
-          read += s;
-          size -= s;
-          buffer += s;
-          file->pos += s;
-       }
-       return read;
+              }
+         } else
+              memset(block_buffer, 0, bs);
+
+         memcpy(buffer, block_buffer + b, s);
+         read += s;
+         size -= s;
+         buffer += s;
+         file->pos += s;
+     }
+     return read;
 #endif /* FAST_VERSION */      
 }
 
@@ -506,99 +522,106 @@ static int
 ext2_seek(     struct boot_file_t*     file,
                unsigned int            newpos)
 {
-       if (!opened)
-               return FILE_ERR_NOTFOUND;
+     if (!opened)
+         return FILE_CANT_SEEK;
 
-       file->pos = newpos;
-       return FILE_ERR_OK;
+     file->pos = newpos;
+     return FILE_ERR_OK;
 }
 
 static int
 ext2_close(    struct boot_file_t*     file)
 {
-       if (!opened)
-               return FILE_ERR_NOTFOUND;
+     if (!opened)
+         return FILE_IOERR;
 
-       if (block_buffer)
-               free(block_buffer);
-       block_buffer = NULL;
+     if (block_buffer)
+         free(block_buffer);
+     block_buffer = NULL;
 
-       if (fs)
-               ext2fs_close(fs);
-       fs = NULL;
+     if (fs)
+         ext2fs_close(fs);
+     fs = NULL;
        
-       prom_close(file->of_device);
+     prom_close(file->of_device);
+     DEBUG_F("ext2_close called\n");
 
-       opened = 0;
+     opened = 0;
            
-       return 0;
+     return 0;
 }
 
 static errcode_t linux_open (const char *name, int flags, io_channel * channel)
 {
-    io_channel io;
-
-
-    if (!name)
-       return EXT2_ET_BAD_DEVICE_NAME;
-    io = (io_channel) malloc (sizeof (struct struct_io_channel));
-    if (!io)
-       return EXT2_ET_BAD_DEVICE_NAME;
-    memset (io, 0, sizeof (struct struct_io_channel));
-    io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
-    io->manager = linux_io_manager;
-    io->name = (char *) malloc (strlen (name) + 1);
-    strcpy (io->name, name);
-    io->block_size = bs;
-    io->read_error = 0;
-    io->write_error = 0;
-    *channel = io;
-
-    return 0;
+     io_channel io;
+
+
+     if (!name)
+         return EXT2_ET_BAD_DEVICE_NAME;
+     io = (io_channel) malloc (sizeof (struct struct_io_channel));
+     if (!io)
+         return EXT2_ET_BAD_DEVICE_NAME;
+     memset (io, 0, sizeof (struct struct_io_channel));
+     io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
+     io->manager = linux_io_manager;
+     io->name = (char *) malloc (strlen (name) + 1);
+     strcpy (io->name, name);
+     io->block_size = bs;
+     io->read_error = 0;
+     io->write_error = 0;
+     *channel = io;
+
+     return 0;
 }
 
 static errcode_t linux_close (io_channel channel)
 {
-    free(channel);
-    return 0;
+     free(channel);
+     return 0;
 }
 
 static errcode_t linux_set_blksize (io_channel channel, int blksize)
 {
-    channel->block_size = bs = blksize;
-    if (block_buffer) {
-       free(block_buffer);
-       block_buffer = malloc(bs * 2);
-    }  
-    return 0;
+     channel->block_size = bs = blksize;
+     if (block_buffer) {
+         free(block_buffer);
+         block_buffer = malloc(bs * 2);
+     } 
+     return 0;
 }
 
 static errcode_t linux_read_blk (io_channel channel, unsigned long block, int count, void *data)
 {
-    int size;
-    unsigned long long tempb;
+     int size;
+     unsigned long long tempb;
 
-    if (count == 0)
-       return 0;
+     if (count == 0)
+         return 0;
     
-    tempb = (((unsigned long long) block) *
-       ((unsigned long long)bs)) + (unsigned long long)doff;
-    size = (count < 0) ? -count : count * bs;
-    prom_lseek(cur_file->of_device, tempb);
-    if (prom_read(cur_file->of_device, data, size) != size) {
-       prom_printf ("\nRead error on block %d", block);
-       return EXT2_ET_SHORT_READ;
-    }
-    return 0;
+     tempb = (((unsigned long long) block) *
+             ((unsigned long long)bs)) + (unsigned long long)doff;
+     size = (count < 0) ? -count : count * bs;
+     prom_lseek(cur_file->of_device, tempb);
+     if (prom_read(cur_file->of_device, data, size) != size) {
+         DEBUG_F("\nRead error on block %ld\n", block);
+         return EXT2_ET_SHORT_READ;
+     }
+     return 0;
 }
 
 static errcode_t linux_write_blk (io_channel channel, unsigned long block, int count, const void *data)
 {
-    return 0;
+     return 0;
 }
 
 static errcode_t linux_flush (io_channel channel)
 {
-    return 0;
+     return 0;
 }
 
+/* 
+ * Local variables:
+ * c-file-style: "k&r"
+ * c-basic-offset: 5
+ * End:
+ */