Add new inode I/O abstraction interface which exports an inode as
an I/O object.
Export ext2_file_flush as a public interface.
Also minor cleanups to tighten code in other I/O abstractions, and to
mark a void * pointer as const in the ext2_file_write interface.
diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog
index f229390..e32db2d 100644
--- a/lib/ext2fs/ChangeLog
+++ b/lib/ext2fs/ChangeLog
@@ -1,3 +1,14 @@
+2002-02-20 Theodore Tso <tytso@valinux.com>
+
+ * Makefile.in, inode_io.c, ext2fs.h, ext2_err.et.in: Add new io
+ abstraction interface which exports an ext2 inode.
+
+ * fileio.c (ext2fs_file_flush): Export ext2fs_file_flush as a
+ public interface.
+
+ * test_io.c (test_close), unix_io.c (unix_close): Remove unneeded
+ conditional; save a few bytes.
+
2002-02-12 Theodore Tso <tytso@valinux.com>
* Makefile.in (tst_badblocks): Add some extra .o files when
diff --git a/lib/ext2fs/Makefile.in b/lib/ext2fs/Makefile.in
index 2c2c94c..54dc160 100644
--- a/lib/ext2fs/Makefile.in
+++ b/lib/ext2fs/Makefile.in
@@ -43,6 +43,7 @@
initialize.o \
inline.o \
inode.o \
+ inode_io.o \
ismounted.o \
link.o \
llseek.o \
@@ -94,6 +95,7 @@
$(srcdir)/initialize.c \
$(srcdir)/inline.c \
$(srcdir)/inode.c \
+ $(srcdir)/inode_io.c \
$(srcdir)/ismounted.c \
$(srcdir)/link.c \
$(srcdir)/llseek.c \
@@ -377,6 +379,10 @@
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
$(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
$(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h $(srcdir)/e2image.h
+inode_io.o: $(srcdir)/inode_io.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
ismounted.o: $(srcdir)/ismounted.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
diff --git a/lib/ext2fs/ext2_err.et.in b/lib/ext2fs/ext2_err.et.in
index 235f75d..ab36c9d 100644
--- a/lib/ext2fs/ext2_err.et.in
+++ b/lib/ext2fs/ext2_err.et.in
@@ -59,8 +59,8 @@
ec EXT2_ET_MAGIC_E2IMAGE,
"Wrong magic number for Ext2 Image Header"
-ec EXT2_ET_MAGIC_RESERVED_8,
- "Wrong magic number --- RESERVED_8"
+ec EXT2_ET_MAGIC_INODE_IO_CHANNEL,
+ "Wrong magic number for inode io_channel structure"
ec EXT2_ET_MAGIC_RESERVED_9,
"Wrong magic number --- RESERVED_9"
@@ -272,5 +272,8 @@
ec EXT2_ET_LOAD_EXT_JOURNAL,
"Error loading external journal"
+ec EXT2_ET_NO_JOURNAL,
+ "Journal not found"
+
end
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 75512d1..e37b817 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -638,9 +638,10 @@
int flags, ext2_file_t *ret);
extern ext2_filsys ext2fs_file_get_fs(ext2_file_t file);
extern errcode_t ext2fs_file_close(ext2_file_t file);
+extern errcode_t ext2fs_file_flush(ext2_file_t file);
extern errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
unsigned int wanted, unsigned int *got);
-extern errcode_t ext2fs_file_write(ext2_file_t file, void *buf,
+extern errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
unsigned int nbytes, unsigned int *written);
extern errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
int whence, ext2_off_t *ret_pos);
@@ -678,6 +679,23 @@
struct ext2_super_block *param,
io_manager manager, ext2_filsys *ret_fs);
+/* icount.c */
+extern void ext2fs_free_icount(ext2_icount_t icount);
+extern errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, int size,
+ ext2_icount_t hint, ext2_icount_t *ret);
+extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size,
+ ext2_icount_t *ret);
+extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino,
+ __u16 *ret);
+extern errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
+ __u16 *ret);
+extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
+ __u16 *ret);
+extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
+ __u16 count);
+extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount);
+errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *);
+
/* inode.c */
extern errcode_t ext2fs_flush_icache(ext2_filsys fs);
extern errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
@@ -703,23 +721,9 @@
extern errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks);
extern errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino);
-/* icount.c */
-extern void ext2fs_free_icount(ext2_icount_t icount);
-extern errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, int size,
- ext2_icount_t hint, ext2_icount_t *ret);
-extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size,
- ext2_icount_t *ret);
-extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino,
- __u16 *ret);
-extern errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
- __u16 *ret);
-extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
- __u16 *ret);
-extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
- __u16 count);
-extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount);
-errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *);
-
+/* inode_io.c */
+extern io_manager inode_io_manager;
+
/* ismounted.c */
extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags);
extern errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
diff --git a/lib/ext2fs/fileio.c b/lib/ext2fs/fileio.c
index e2f4795..f0b216e 100644
--- a/lib/ext2fs/fileio.c
+++ b/lib/ext2fs/fileio.c
@@ -88,7 +88,7 @@
* This function flushes the dirty block buffer out to disk if
* necessary.
*/
-static errcode_t ext2fs_file_flush(ext2_file_t file)
+errcode_t ext2fs_file_flush(ext2_file_t file)
{
errcode_t retval;
ext2_filsys fs;
@@ -235,7 +235,7 @@
}
-errcode_t ext2fs_file_write(ext2_file_t file, void *buf,
+errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
unsigned int nbytes, unsigned int *written)
{
ext2_filsys fs;
diff --git a/lib/ext2fs/inode_io.c b/lib/ext2fs/inode_io.c
new file mode 100644
index 0000000..bb72403
--- /dev/null
+++ b/lib/ext2fs/inode_io.c
@@ -0,0 +1,264 @@
+/*
+ * inode_io.c --- This is allows an inode in an ext2 filesystem image
+ * to be accessed via the I/O manager interface.
+ *
+ * Copyright (C) 2002 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <time.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * For checking structure magic numbers...
+ */
+
+#define EXT2_CHECK_MAGIC(struct, code) \
+ if ((struct)->magic != (code)) return (code)
+
+struct inode_private_data {
+ int magic;
+ char name[32];
+ ext2_file_t file;
+ ext2_filsys fs;
+ ext2_ino_t ino;
+ int flags;
+ struct inode_private_data *next;
+};
+
+static struct inode_private_data *top_intern;
+static int ino_unique = 0;
+
+static errcode_t inode_open(const char *name, int flags, io_channel *channel);
+static errcode_t inode_close(io_channel channel);
+static errcode_t inode_set_blksize(io_channel channel, int blksize);
+static errcode_t inode_read_blk(io_channel channel, unsigned long block,
+ int count, void *data);
+static errcode_t inode_write_blk(io_channel channel, unsigned long block,
+ int count, const void *data);
+static errcode_t inode_flush(io_channel channel);
+static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
+ int size, const void *data);
+
+static struct struct_io_manager struct_inode_manager = {
+ EXT2_ET_MAGIC_IO_MANAGER,
+ "Inode I/O Manager",
+ inode_open,
+ inode_close,
+ inode_set_blksize,
+ inode_read_blk,
+ inode_write_blk,
+ inode_flush,
+ inode_write_byte
+};
+
+io_manager inode_io_manager = &struct_inode_manager;
+
+errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
+ char **name)
+{
+ struct inode_private_data *data;
+ errcode_t retval;
+
+ if ((retval = ext2fs_get_mem(sizeof(struct inode_private_data),
+ (void **) &data)))
+ return retval;
+ data->magic = EXT2_ET_MAGIC_INODE_IO_CHANNEL;
+ sprintf(data->name, "%lu:%d", ino, ino_unique++);
+ data->file = 0;
+ data->fs = fs;
+ data->ino = ino;
+ data->flags = 0;
+ data->next = top_intern;
+ top_intern = data;
+ *name = data->name;
+ return 0;
+}
+
+
+static errcode_t inode_open(const char *name, int flags, io_channel *channel)
+{
+ io_channel io = NULL;
+ struct inode_private_data *prev, *data = NULL;
+ errcode_t retval;
+ int open_flags;
+
+ if (name == 0)
+ return EXT2_ET_BAD_DEVICE_NAME;
+
+ for (data = top_intern, prev = NULL; data;
+ prev = data, data = data->next)
+ if (strcmp(name, data->name) == 0)
+ break;
+ if (!data)
+ return ENOENT;
+ if (prev)
+ prev->next = data->next;
+ else
+ top_intern = data->next;
+
+ retval = ext2fs_get_mem(sizeof(struct struct_io_channel),
+ (void **) &io);
+ if (retval)
+ goto cleanup;
+ memset(io, 0, sizeof(struct struct_io_channel));
+
+ io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
+ io->manager = inode_io_manager;
+ retval = ext2fs_get_mem(strlen(name)+1, (void **) &io->name);
+ if (retval)
+ goto cleanup;
+
+ strcpy(io->name, name);
+ io->private_data = data;
+ io->block_size = 1024;
+ io->read_error = 0;
+ io->write_error = 0;
+ io->refcount = 1;
+
+ open_flags = (flags & IO_FLAG_RW) ? EXT2_FILE_WRITE : 0;
+ retval = ext2fs_file_open(data->fs, data->ino, open_flags,
+ &data->file);
+ if (retval)
+ goto cleanup;
+
+ *channel = io;
+ return 0;
+
+cleanup:
+ if (data) {
+ ext2fs_free_mem((void **) &data);
+ }
+ if (io)
+ ext2fs_free_mem((void **) &io);
+ return retval;
+}
+
+static errcode_t inode_close(io_channel channel)
+{
+ struct inode_private_data *data;
+ errcode_t retval = 0;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct inode_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
+
+ if (--channel->refcount > 0)
+ return 0;
+
+ retval = ext2fs_file_close(data->file);
+
+ ext2fs_free_mem((void **) &channel->private_data);
+ if (channel->name)
+ ext2fs_free_mem((void **) &channel->name);
+ ext2fs_free_mem((void **) &channel);
+ return retval;
+}
+
+static errcode_t inode_set_blksize(io_channel channel, int blksize)
+{
+ struct inode_private_data *data;
+ errcode_t retval;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct inode_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
+
+ channel->block_size = blksize;
+ return 0;
+}
+
+
+static errcode_t inode_read_blk(io_channel channel, unsigned long block,
+ int count, void *buf)
+{
+ struct inode_private_data *data;
+ struct inode_cache *cache;
+ errcode_t retval;
+ char *cp;
+ int i, j;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct inode_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
+
+ if ((retval = ext2fs_file_lseek(data->file,
+ block * channel->block_size,
+ EXT2_SEEK_SET, 0)))
+ return retval;
+
+ count = (count < 0) ? -count : (count * channel->block_size);
+
+ return ext2fs_file_read(data->file, buf, count, 0);
+}
+
+static errcode_t inode_write_blk(io_channel channel, unsigned long block,
+ int count, const void *buf)
+{
+ struct inode_private_data *data;
+ struct inode_cache *cache;
+ errcode_t retval = 0, retval2;
+ const char *cp;
+ int writethrough;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct inode_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
+
+ if ((retval = ext2fs_file_lseek(data->file,
+ block * channel->block_size,
+ EXT2_SEEK_SET, 0)))
+ return retval;
+
+ count = (count < 0) ? -count : (count * channel->block_size);
+
+ return ext2fs_file_write(data->file, buf, count, 0);
+}
+
+static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
+ int size, const void *buf)
+{
+ struct inode_private_data *data;
+ errcode_t retval = 0;
+ size_t actual;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct inode_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
+
+ if ((retval = ext2fs_file_lseek(data->file, offset,
+ EXT2_SEEK_SET, 0)))
+ return retval;
+
+ return ext2fs_file_write(data->file, buf, size, 0);
+}
+
+/*
+ * Flush data buffers to disk.
+ */
+static errcode_t inode_flush(io_channel channel)
+{
+ struct inode_private_data *data;
+ errcode_t retval = 0;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct inode_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
+
+ return ext2fs_file_flush(data->file);
+}
+
diff --git a/lib/ext2fs/test_io.c b/lib/ext2fs/test_io.c
index b259d0f..baca786 100644
--- a/lib/ext2fs/test_io.c
+++ b/lib/ext2fs/test_io.c
@@ -154,8 +154,7 @@
if (data->real)
retval = io_channel_close(data->real);
- if (channel->private_data)
- ext2fs_free_mem((void **) &channel->private_data);
+ ext2fs_free_mem((void **) &channel->private_data);
if (channel->name)
ext2fs_free_mem((void **) &channel->name);
ext2fs_free_mem((void **) &channel);
diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c
index 7fa4b1a..0f993e4 100644
--- a/lib/ext2fs/unix_io.c
+++ b/lib/ext2fs/unix_io.c
@@ -385,8 +385,8 @@
if (close(data->dev) < 0)
retval = errno;
free_cache(channel, data);
- if (channel->private_data)
- ext2fs_free_mem((void **) &channel->private_data);
+
+ ext2fs_free_mem((void **) &channel->private_data);
if (channel->name)
ext2fs_free_mem((void **) &channel->name);
ext2fs_free_mem((void **) &channel);