-/* 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"
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 */
-
+
static errcode_t linux_open (const char *name, int flags, io_channel * channel);
static errcode_t linux_close (io_channel channel);
static errcode_t linux_set_blksize (io_channel channel, int blksize);
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;
void com_err (const char *a, long i, const char *fmt,...)
{
- prom_printf ((char *) fmt);
+ prom_printf ((char *) fmt);
}
static int
struct partition_t* part,
const char* file_name)
{
- 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");
- DEBUG_LEAVE(FILE_ERR_FSBUSY);
- return FILE_ERR_FSBUSY;
- }
- if (file->device_kind != FILE_DEVICE_BLOCK) {
- prom_printf("Can't open ext2 filesystem on non-block device\n");
- 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;
-
-
- DEBUG_F("partition offset: %Lu\n", doff);
-
- /* Open the OF device for the entire disk */
- strncpy(buffer, dev_name, 1020);
- strcat(buffer, ":0");
-
- DEBUG_F("<%s>\n", buffer);
-
- file->of_device = prom_open(buffer);
-
- DEBUG_F("file->of_device = %p\n", file->of_device);
-
- if (file->of_device == PROM_INVALID_HANDLE) {
-
- 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 %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);
- 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;
- }
+ int result = 0;
+ int error = FILE_ERR_NOTFOUND;
+ static char buffer[1024];
+ int ofopened = 0;
+
+ 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;
+
+
+ DEBUG_F("partition offset: %Lu\n", doff);
+
+ /* Open the OF device for the entire disk */
+ strncpy(buffer, dev_name, 1020);
+ strcat(buffer, ":0");
+
+ DEBUG_F("<%s>\n", buffer);
+
+ file->of_device = prom_open(buffer);
+
+ DEBUG_F("file->of_device = %p\n", file->of_device);
+
+ if (file->of_device == PROM_INVALID_HANDLE) {
+
+ 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 %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);
+ 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) {
+ 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);
- error = FILE_ERR_NOTFOUND;
- goto bail;
- }
-#endif
+ 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);
- 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;
- }
+ 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;
-
- opened = 1;
+ file->pos = 0;
+
+ 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;
-
- DEBUG_LEAVE_F(error);
- return error;
- }
-
- DEBUG_LEAVE(FILE_ERR_OK);
- return FILE_ERR_OK;
+ 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_F(error);
+ return error;
+ }
+
+ DEBUG_LEAVE(FILE_ERR_OK);
+ return FILE_ERR_OK;
}
#ifdef FAST_VERSION
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;
- }
-
- /* Range doesn't match. Dump existing range */
- if (read_range_start) {
+ ++read_range_count;
+ return ((read_range_count * bs) >= read_max) ? BLOCK_ABORT : 0;
+ }
+
+ /* 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 */
unsigned int size,
void* buffer)
{
- errcode_t retval;
+ errcode_t retval;
#ifdef FAST_VERSION
- if (!opened)
- return FILE_IOERR;
-
-
- 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;
-
- retval = ext2fs_block_iterate(fs, file->inode, 0, 0, read_iterator, 0);
- if (retval == BLOCK_ABORT)
- retval = read_result;
- if (!retval && read_range_start) {
+ if (!opened)
+ return FILE_IOERR;
+
+
+ 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;
+
+ 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 %ld in read\n", (long) retval);
-
- return read_total;
+ read_dump_range();
+ retval = read_result;
+ }
+ if (retval)
+ prom_printf ("ext2: i/o error %ld in read\n", (long) retval);
+
+ return read_total;
#else /* FAST_VERSION */
- int status;
- unsigned int read = 0;
-
- if (!opened)
- return FILE_IOERR;
-
-
- 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;
-
- 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) {
+ int status;
+ unsigned int read = 0;
+
+ if (!opened)
+ return FILE_IOERR;
+
+
+ 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;
+
+ 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;
-#endif /* FAST_VERSION */
+ }
+ } 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 */
}
static int
ext2_seek( struct boot_file_t* file,
unsigned int newpos)
{
- if (!opened)
- return FILE_CANT_SEEK;
+ 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_IOERR;
-
- if (block_buffer)
- free(block_buffer);
- block_buffer = NULL;
-
- if (fs)
- ext2fs_close(fs);
- fs = NULL;
-
- prom_close(file->of_device);
- DEBUG_F("ext2_close called\n");
-
- opened = 0;
-
- return 0;
+ if (!opened)
+ return FILE_IOERR;
+
+ if (block_buffer)
+ free(block_buffer);
+ block_buffer = NULL;
+
+ if (fs)
+ ext2fs_close(fs);
+ fs = NULL;
+
+ prom_close(file->of_device);
+ DEBUG_F("ext2_close called\n");
+
+ opened = 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;
-
- 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) {
- DEBUG_F("\nRead error on block %ld\n", block);
- return EXT2_ET_SHORT_READ;
- }
- return 0;
+ int size;
+ unsigned long long tempb;
+
+ 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) {
+ 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:
+ */