1 /* vi: set sw=4 ts=4: */
3 * inode_io.c --- This is allows an inode in an ext2 filesystem image
4 * to be accessed via the I/O manager interface.
6 * Copyright (C) 2002 Theodore Ts'o.
9 * This file may be redistributed under the terms of the GNU Public
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
);
61 static struct struct_io_manager struct_inode_manager
= {
62 EXT2_ET_MAGIC_IO_MANAGER
,
73 io_manager inode_io_manager
= &struct_inode_manager
;
75 errcode_t
ext2fs_inode_io_intern2(ext2_filsys fs
, ext2_ino_t ino
,
76 struct ext2_inode
*inode
,
79 struct inode_private_data
*data
;
82 if ((retval
= ext2fs_get_mem(sizeof(struct inode_private_data
),
85 data
->magic
= EXT2_ET_MAGIC_INODE_IO_CHANNEL
;
86 sprintf(data
->name
, "%u:%d", ino
, ino_unique
++);
92 memcpy(&data
->inode
, inode
, sizeof(struct ext2_inode
));
93 data
->flags
|= CHANNEL_HAS_INODE
;
95 data
->next
= top_intern
;
101 errcode_t
ext2fs_inode_io_intern(ext2_filsys fs
, ext2_ino_t ino
,
104 return ext2fs_inode_io_intern2(fs
, ino
, NULL
, name
);
108 static errcode_t
inode_open(const char *name
, int flags
, io_channel
*channel
)
110 io_channel io
= NULL
;
111 struct inode_private_data
*prev
, *data
= NULL
;
116 return EXT2_ET_BAD_DEVICE_NAME
;
118 for (data
= top_intern
, prev
= NULL
; data
;
119 prev
= data
, data
= data
->next
)
120 if (strcmp(name
, data
->name
) == 0)
125 prev
->next
= data
->next
;
127 top_intern
= data
->next
;
129 retval
= ext2fs_get_mem(sizeof(struct struct_io_channel
), &io
);
132 memset(io
, 0, sizeof(struct struct_io_channel
));
134 io
->magic
= EXT2_ET_MAGIC_IO_CHANNEL
;
135 io
->manager
= inode_io_manager
;
136 retval
= ext2fs_get_mem(strlen(name
)+1, &io
->name
);
140 strcpy(io
->name
, name
);
141 io
->private_data
= data
;
142 io
->block_size
= 1024;
147 open_flags
= (flags
& IO_FLAG_RW
) ? EXT2_FILE_WRITE
: 0;
148 retval
= ext2fs_file_open2(data
->fs
, data
->ino
,
149 (data
->flags
& CHANNEL_HAS_INODE
) ?
150 &data
->inode
: 0, open_flags
,
160 ext2fs_free_mem(&data
);
163 ext2fs_free_mem(&io
);
167 static errcode_t
inode_close(io_channel channel
)
169 struct inode_private_data
*data
;
170 errcode_t retval
= 0;
172 EXT2_CHECK_MAGIC(channel
, EXT2_ET_MAGIC_IO_CHANNEL
);
173 data
= (struct inode_private_data
*) channel
->private_data
;
174 EXT2_CHECK_MAGIC(data
, EXT2_ET_MAGIC_INODE_IO_CHANNEL
);
176 if (--channel
->refcount
> 0)
179 retval
= ext2fs_file_close(data
->file
);
181 ext2fs_free_mem(&channel
->private_data
);
183 ext2fs_free_mem(&channel
->name
);
184 ext2fs_free_mem(&channel
);
188 static errcode_t
inode_set_blksize(io_channel channel
, int blksize
)
190 struct inode_private_data
*data
;
192 EXT2_CHECK_MAGIC(channel
, EXT2_ET_MAGIC_IO_CHANNEL
);
193 data
= (struct inode_private_data
*) channel
->private_data
;
194 EXT2_CHECK_MAGIC(data
, EXT2_ET_MAGIC_INODE_IO_CHANNEL
);
196 channel
->block_size
= blksize
;
201 static errcode_t
inode_read_blk(io_channel channel
, unsigned long block
,
202 int count
, void *buf
)
204 struct inode_private_data
*data
;
207 EXT2_CHECK_MAGIC(channel
, EXT2_ET_MAGIC_IO_CHANNEL
);
208 data
= (struct inode_private_data
*) channel
->private_data
;
209 EXT2_CHECK_MAGIC(data
, EXT2_ET_MAGIC_INODE_IO_CHANNEL
);
211 if ((retval
= ext2fs_file_lseek(data
->file
,
212 block
* channel
->block_size
,
216 count
= (count
< 0) ? -count
: (count
* channel
->block_size
);
218 return ext2fs_file_read(data
->file
, buf
, count
, 0);
221 static errcode_t
inode_write_blk(io_channel channel
, unsigned long block
,
222 int count
, const void *buf
)
224 struct inode_private_data
*data
;
227 EXT2_CHECK_MAGIC(channel
, EXT2_ET_MAGIC_IO_CHANNEL
);
228 data
= (struct inode_private_data
*) channel
->private_data
;
229 EXT2_CHECK_MAGIC(data
, EXT2_ET_MAGIC_INODE_IO_CHANNEL
);
231 if ((retval
= ext2fs_file_lseek(data
->file
,
232 block
* channel
->block_size
,
236 count
= (count
< 0) ? -count
: (count
* channel
->block_size
);
238 return ext2fs_file_write(data
->file
, buf
, count
, 0);
241 static errcode_t
inode_write_byte(io_channel channel
, unsigned long offset
,
242 int size
, const void *buf
)
244 struct inode_private_data
*data
;
245 errcode_t retval
= 0;
247 EXT2_CHECK_MAGIC(channel
, EXT2_ET_MAGIC_IO_CHANNEL
);
248 data
= (struct inode_private_data
*) channel
->private_data
;
249 EXT2_CHECK_MAGIC(data
, EXT2_ET_MAGIC_INODE_IO_CHANNEL
);
251 if ((retval
= ext2fs_file_lseek(data
->file
, offset
,
255 return ext2fs_file_write(data
->file
, buf
, size
, 0);
259 * Flush data buffers to disk.
261 static errcode_t
inode_flush(io_channel channel
)
263 struct inode_private_data
*data
;
265 EXT2_CHECK_MAGIC(channel
, EXT2_ET_MAGIC_IO_CHANNEL
);
266 data
= (struct inode_private_data
*) channel
->private_data
;
267 EXT2_CHECK_MAGIC(data
, EXT2_ET_MAGIC_INODE_IO_CHANNEL
);
269 return ext2fs_file_flush(data
->file
);