2 * inode_io.c --- This is allows an inode in an ext2 filesystem image
3 * to be accessed via the I/O manager interface.
5 * Copyright (C) 2002 Theodore Ts'o.
8 * This file may be redistributed under the terms of the GNU Library
9 * General Public License, version 2.
28 * For checking structure magic numbers...
31 #define EXT2_CHECK_MAGIC(struct, code) \
32 if ((struct)->magic != (code)) return (code)
34 struct inode_private_data {
40 struct ext2_inode inode;
42 struct inode_private_data *next;
45 #define CHANNEL_HAS_INODE 0x8000
47 static struct inode_private_data *top_intern;
48 static int ino_unique = 0;
50 static errcode_t inode_open(const char *name, int flags, io_channel *channel);
51 static errcode_t inode_close(io_channel channel);
52 static errcode_t inode_set_blksize(io_channel channel, int blksize);
53 static errcode_t inode_read_blk(io_channel channel, unsigned long block,
54 int count, void *data);
55 static errcode_t inode_write_blk(io_channel channel, unsigned long block,
56 int count, const void *data);
57 static errcode_t inode_flush(io_channel channel);
58 static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
59 int size, const void *data);
60 static errcode_t inode_read_blk64(io_channel channel,
61 unsigned long long block, int count, void *data);
62 static errcode_t inode_write_blk64(io_channel channel,
63 unsigned long long block, int count, const void *data);
65 static struct struct_io_manager struct_inode_manager = {
66 EXT2_ET_MAGIC_IO_MANAGER,
81 io_manager inode_io_manager = &struct_inode_manager;
83 errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
84 struct ext2_inode *inode,
87 struct inode_private_data *data;
90 if ((retval = ext2fs_get_mem(sizeof(struct inode_private_data),
93 data->magic = EXT2_ET_MAGIC_INODE_IO_CHANNEL;
94 sprintf(data->name, "%u:%d", ino, ino_unique++);
100 memcpy(&data->inode, inode, sizeof(struct ext2_inode));
101 data->flags |= CHANNEL_HAS_INODE;
103 data->next = top_intern;
109 errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
112 return ext2fs_inode_io_intern2(fs, ino, NULL, name);
116 static errcode_t inode_open(const char *name, int flags, io_channel *channel)
118 io_channel io = NULL;
119 struct inode_private_data *prev, *data = NULL;
124 return EXT2_ET_BAD_DEVICE_NAME;
126 for (data = top_intern, prev = NULL; data;
127 prev = data, data = data->next)
128 if (strcmp(name, data->name) == 0)
133 prev->next = data->next;
135 top_intern = data->next;
137 retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
140 memset(io, 0, sizeof(struct struct_io_channel));
142 io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
143 io->manager = inode_io_manager;
144 retval = ext2fs_get_mem(strlen(name)+1, &io->name);
148 strcpy(io->name, name);
149 io->private_data = data;
150 io->block_size = 1024;
155 open_flags = (flags & IO_FLAG_RW) ? EXT2_FILE_WRITE : 0;
156 retval = ext2fs_file_open2(data->fs, data->ino,
157 (data->flags & CHANNEL_HAS_INODE) ?
158 &data->inode : 0, open_flags,
168 ext2fs_free_mem(&io->name);
170 ext2fs_free_mem(&data);
172 ext2fs_free_mem(&io);
176 static errcode_t inode_close(io_channel channel)
178 struct inode_private_data *data;
179 errcode_t retval = 0;
181 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
182 data = (struct inode_private_data *) channel->private_data;
183 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
185 if (--channel->refcount > 0)
188 retval = ext2fs_file_close(data->file);
190 ext2fs_free_mem(&channel->private_data);
192 ext2fs_free_mem(&channel->name);
193 ext2fs_free_mem(&channel);
197 static errcode_t inode_set_blksize(io_channel channel, int blksize)
199 struct inode_private_data *data;
201 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
202 data = (struct inode_private_data *) channel->private_data;
203 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
205 channel->block_size = blksize;
210 static errcode_t inode_read_blk64(io_channel channel,
211 unsigned long long block, int count, void *buf)
213 struct inode_private_data *data;
216 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
217 data = (struct inode_private_data *) channel->private_data;
218 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
220 if ((retval = ext2fs_file_lseek(data->file,
221 block * channel->block_size,
225 count = (count < 0) ? -count : (count * channel->block_size);
227 return ext2fs_file_read(data->file, buf, count, 0);
230 static errcode_t inode_read_blk(io_channel channel, unsigned long block,
231 int count, void *buf)
233 return inode_read_blk64(channel, block, count, buf);
236 static errcode_t inode_write_blk64(io_channel channel,
237 unsigned long long block, int count, const void *buf)
239 struct inode_private_data *data;
242 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
243 data = (struct inode_private_data *) channel->private_data;
244 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
246 if ((retval = ext2fs_file_lseek(data->file,
247 block * channel->block_size,
251 count = (count < 0) ? -count : (count * channel->block_size);
253 return ext2fs_file_write(data->file, buf, count, 0);
256 static errcode_t inode_write_blk(io_channel channel, unsigned long block,
257 int count, const void *buf)
259 return inode_write_blk64(channel, block, count, buf);
262 static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
263 int size, const void *buf)
265 struct inode_private_data *data;
266 errcode_t retval = 0;
268 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
269 data = (struct inode_private_data *) channel->private_data;
270 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
272 if ((retval = ext2fs_file_lseek(data->file, offset,
276 return ext2fs_file_write(data->file, buf, size, 0);
280 * Flush data buffers to disk.
282 static errcode_t inode_flush(io_channel channel)
284 struct inode_private_data *data;
286 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
287 data = (struct inode_private_data *) channel->private_data;
288 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
290 return ext2fs_file_flush(data->file);